我有一个应用程序执行一些代码A多次迭代,通常最多1M次迭代。 在代码A执行完之后,我收集信息,如时间,错误消息,如果抛出异常等,在专门的对象中让我们说ExecutionInfo。然后我在ConcurrentBag中添加了ExecutionInfo的实例(没关系ConcurrentBag,它可能也是一个List但需要是线程安全的)。
在1M次迭代后,我得到了一组1M ExecutionInfo实例。下一步是将所有内容汇总为ExecutionInfoAggregation,使用Linq扩展,例如Average,Min,Max,Count来获取各种有趣的数据。以下代码在1M次迭代后运行,并消耗92%的CPU(表示探查器):
private void Summarize(IEnumerable<MethodExecutionResult> methodExecutions)
{
List<MethodExecutionResult> items = methodExecutions.ToList();
if (!items.Any())
{
return;
}
AvgMethodExecutionTime = Math.Round(items.Average(x => x.ExecutionTime.TotalMilliseconds),3);
MinMethodExecutionTime = Math.Round(items.Min(x => x.ExecutionTime.TotalMilliseconds),3);
MaxMethodExecutionTime = Math.Round(items.Max(x => x.ExecutionTime.TotalMilliseconds),3);
FailedExecutionsCount = items.Count(x => !x.Success);
}
顺便说一下,应用程序的内存使用量是“暴涨”#。
这显然不具备高效性。我对此的解决方案如下:
使用更合适的集合类型替换集合类型,允许快速插入和快速查询。那可能是什么,如果有的话? 不要在1M迭代后查询集合,而是在每次执行代码后聚合。 尝试找到一种更紧凑的方式来存储收集的数据。
如何优化查询的任何想法?有更好的方法吗?
编辑:刚看到没有必要调用ToList()
答案 0 :(得分:0)
我会在每次执行方法后聚合它们,而不是保存每次执行的信息。
public class MethodExecutions
{
private int _excCount = 0;
private Int64 _totalExcTime = 0;
private int _excMaxTimeTotalMilliseconds = 0;
private int _excMinTimeTotalMilliseconds = int.MaxValue;
private int _failCount = 0;
public void Add(int excTime, bool isFail)
{
_excCount += 1;
_totalExcTime += excTime;
if (excTime > _excMaxTimeTotalMilliseconds)
_excMaxTimeTotalMilliseconds = excTime;
if (excTime < _excMinTimeTotalMilliseconds)
_excMinTimeTotalMilliseconds = excTime;
if (isFail)
_failCount++;
}
public void Summarize(out int avgTime, out int minTime, out int maxTime, out int failCount)
{
avgTime = (int) Math.Round((double) _totalExcTime / _excCount);
minTime = _excMinTimeTotalMilliseconds;
maxTime = _excMaxTimeTotalMilliseconds;
failCount = _failCount;
}
}