我有一个应用程序,它执行一些代码A多次迭代,通常最多1M次迭代。在执行完代码A之后,我收集了一些信息,比如所用的时间、错误消息、异常是否被抛出等等,都放在一个专门的对象中,比如ExecutionInfo。然后,我将ExecutionInfo的实例添加到一个ConcurrentBag中(别管ConcurrentBag,它也可以是一个列表,但必须是线程安全的)。
在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次迭代后查询集合,而是在每次代码A执行后进行聚合。尝试找到一种更紧凑的方式来存储收集的数据。
有什么想法可以优化查询吗?有没有更好的方法?
编辑:刚刚看到对ToList()的调用不是必需的
发布于 2014-05-21 16:00:22
我不会保存每次执行的信息,而是在每次方法执行后将它们聚合在一起。
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;
}
}https://stackoverflow.com/questions/23766798
复制相似问题