我有Dictionary<int, MyClass>
它包含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分钟才能完成。我似乎无法找到瓶颈可能的位置,或者这个时间听起来是否合适?
任何人都可以看到它花了这么长时间的原因吗?
答案 0 :(得分:3)
如果您的MyInfoCollection
很大,我就不会在其上调用ToList()
,因此您可以使用ForEach
扩展方法。调用ToList()
将创建并填充一个巨大的列表。我将移除ToList()
来电,并将.ForEach
转换为for each
语句,或为ForEach
编写。IEnumerable<T>
扩展方法。
然后对其进行分析,看看需要多长时间。另一件事是删除ERRORS
元素的find和null检查。如果不存在,则不要调用上面的for each
语句。这样你就可以检查一次而不是90,000次。
正如Michael Stum指出的那样,我会定义一个字符串来保存值DateTime.Now.ToString("dd/MM/yyyy HH:mm:ss:fff")
,然后引用它或传入它。另外,你甚至不使用这个调用:
DateTime recordTime = DateTime.Now;
答案 1 :(得分:2)
这是我最有可能做的。
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()));
}
答案 2 :(得分:1)
如何用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];
}