将 90000 个 XElement 添加到 XDocument

发布于 2024-08-25 01:03:52 字数 1111 浏览 4 评论 0原文

我有一个 Dictionary

它包含 100,000 个项目,

其中填充了 10,000 个项目值,而 90,000 个项目为空。

我有这样的代码:

var nullitems = MyInfoCollection.Where(x => x.Value == null).ToList();
nullitems.ForEach(x => LogMissedSequenceError(x.Key + 1));

private void LogMissedSequenceError(long SequenceNumber)
        {
            DateTime recordTime = DateTime.Now;

            var errors = MyXDocument.Descendants("ERRORS").FirstOrDefault();
            if (errors != null)
            {

                errors.Add(
                    new XElement("ERROR",
                        new XElement("DATETIME", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff")),
                        new XElement("DETAIL", "No information was read for expected sequence number " + SequenceNumber),
                        new XAttribute("TYPE", "MISSED"),
                        new XElement("PAGEID", SequenceNumber)
                        )
                );
            }
        }

这似乎需要大约 2 分钟才能完成。我似乎找不到瓶颈可能在哪里,或者这个时机听起来是否合适?

任何人都可以看出为什么要花这么长时间吗?

I have a Dictionary<int, MyClass>

It contains 100,000 items

10,000 items value is populated whilst 90,000 are null.

I have this code:

var nullitems = MyInfoCollection.Where(x => x.Value == null).ToList();
nullitems.ForEach(x => LogMissedSequenceError(x.Key + 1));

private void LogMissedSequenceError(long SequenceNumber)
        {
            DateTime recordTime = DateTime.Now;

            var errors = MyXDocument.Descendants("ERRORS").FirstOrDefault();
            if (errors != null)
            {

                errors.Add(
                    new XElement("ERROR",
                        new XElement("DATETIME", DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff")),
                        new XElement("DETAIL", "No information was read for expected sequence number " + SequenceNumber),
                        new XAttribute("TYPE", "MISSED"),
                        new XElement("PAGEID", SequenceNumber)
                        )
                );
            }
        }

This seems to take about 2 minutes to complete. I can't seem to find where the bottleneck might be or if this timing sounds about right?

Can anyone see anything to why its taking so long?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

洒一地阳光 2024-09-01 01:03:52

如果您的 MyInfoCollection 很大,我不会对其调用 ToList() ,以便您可以使用 ForEach 扩展方法。调用 ToList() 将创建并填充一个巨大的列表。我将删除 ToList() 调用,并将 .ForEach 放入 foreach 语句中,或者编写一个 .ForEach IEnumerable 的扩展方法。

然后对其进行分析并查看需要多长时间。另一件要做的事情是删除 ERRORS 元素的查找和 null 检查。如果不存在,则不要调用上面的 foreach 语句。这样你就可以对它进行一次 null 检查,而不是 90,000 次。

另外,正如 Michael Stum 指出的那样,我定义一个字符串来保存值 DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff"),然后引用它或另外,您甚至不使用此调用:

DateTime recordTime = DateTime.Now;

If your MyInfoCollection is huge, I wouldn't call ToList() on it just so you can use the ForEach extension method. Calling ToList() is going to create and populate a huge list. I'd remove the ToList() call, and make the .ForEach into a for each statement, or write a .ForEach extension method for IEnumerable<T>.

Then profile it and see how long it takes. One other thing to do is remove the find and null check of the ERRORS element. If it's not there, then don't call the for each statement above. That way you null check it one time instead of 90,000 times.

Plus as Michael Stum pointed out, I'd define a string to hold the value DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff"), then reference it or pass it in. Plus, you don't even use this call:

DateTime recordTime = DateTime.Now;
楠木可依 2024-09-01 01:03:52

这是我最有可能做的事情。

private void BuildErrorNodes()
{
    const string nodeFormat = @"<ERROR TYPE=""MISSED""><DATETIME>{0}</DATETIME><DETAIL>No information was read for expected sequence number {1}</DETAIL><PAGEID>{1}</PAGEID></ERROR>";

    var sb = new StringBuilder("<ERRORS>");
    foreach (var item in MyInfoCollection)
    {
        if (item.Value == null) 
        {
            sb.AppendFormat(
                nodeFormat,
                DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff"),
                item.Key + 1
            );
        }
    }

    sb.Append("</ERRORS>");

    var errorsNode = MyXDocument.Descendants("ERRORS").FirstOrDefault();
    errorsNode.ReplaceWith(XElement.Parse(sb.ToString()));
}

This is what I would most likely do.

private void BuildErrorNodes()
{
    const string nodeFormat = @"<ERROR TYPE=""MISSED""><DATETIME>{0}</DATETIME><DETAIL>No information was read for expected sequence number {1}</DETAIL><PAGEID>{1}</PAGEID></ERROR>";

    var sb = new StringBuilder("<ERRORS>");
    foreach (var item in MyInfoCollection)
    {
        if (item.Value == null) 
        {
            sb.AppendFormat(
                nodeFormat,
                DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff"),
                item.Key + 1
            );
        }
    }

    sb.Append("</ERRORS>");

    var errorsNode = MyXDocument.Descendants("ERRORS").FirstOrDefault();
    errorsNode.ReplaceWith(XElement.Parse(sb.ToString()));
}
浮生面具三千个 2024-09-01 01:03:52

用 LINQ 查询替换方法调用怎么样?

static void Main(string[] args)
{

    var MyInfoCollection = (from key in Enumerable.Range(0, 100000)
                            let value = (MoreRandom() % 10 != 0)
                                                    ? (string)null
                                                    : "H"
                            select new { Value = value, Key = key }
                           ).ToDictionary(k => k.Key, v => v.Value);

    var MyXDocument = new XElement("ROOT",
                                    new XElement("ERRORS")
                                  );
    var sw = Stopwatch.StartNew();
    //===
    var errorTime = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff");
    var addedIndex = MyInfoCollection.Select((item, index) =>
                                                    new
                                                    {
                                                        Value = item.Value,
                                                        Key = item.Key,
                                                        Index = index
                                                    });
    var errorQuery = from item in addedIndex
                     where string.IsNullOrEmpty(item.Value)
                     let sequenceNumber = item.Key + 1
                     let detail = "No information was read for expected " +
                                  "sequence number " + sequenceNumber
                     select new XElement("ERROR",
                        new XElement("DATETIME", errorTime),
                        new XElement("DETAIL", detail),
                        new XAttribute("TYPE", "MISSED"),
                        new XElement("PAGEID", sequenceNumber)
                        );

    var errors = MyXDocument.Descendants("ERRORS").FirstOrDefault();
    if (errors != null)
        errors.Add(errorQuery);
    //===
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds); //623
}
static RandomNumberGenerator rand = RandomNumberGenerator.Create();
static int MoreRandom()
{
    var buff = new byte[1];
    rand.GetBytes(buff);
    return buff[0];
}

How about replacing the method call with a LINQ query?

static void Main(string[] args)
{

    var MyInfoCollection = (from key in Enumerable.Range(0, 100000)
                            let value = (MoreRandom() % 10 != 0)
                                                    ? (string)null
                                                    : "H"
                            select new { Value = value, Key = key }
                           ).ToDictionary(k => k.Key, v => v.Value);

    var MyXDocument = new XElement("ROOT",
                                    new XElement("ERRORS")
                                  );
    var sw = Stopwatch.StartNew();
    //===
    var errorTime = DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff");
    var addedIndex = MyInfoCollection.Select((item, index) =>
                                                    new
                                                    {
                                                        Value = item.Value,
                                                        Key = item.Key,
                                                        Index = index
                                                    });
    var errorQuery = from item in addedIndex
                     where string.IsNullOrEmpty(item.Value)
                     let sequenceNumber = item.Key + 1
                     let detail = "No information was read for expected " +
                                  "sequence number " + sequenceNumber
                     select new XElement("ERROR",
                        new XElement("DATETIME", errorTime),
                        new XElement("DETAIL", detail),
                        new XAttribute("TYPE", "MISSED"),
                        new XElement("PAGEID", sequenceNumber)
                        );

    var errors = MyXDocument.Descendants("ERRORS").FirstOrDefault();
    if (errors != null)
        errors.Add(errorQuery);
    //===
    sw.Stop();
    Console.WriteLine(sw.ElapsedMilliseconds); //623
}
static RandomNumberGenerator rand = RandomNumberGenerator.Create();
static int MoreRandom()
{
    var buff = new byte[1];
    rand.GetBytes(buff);
    return buff[0];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文