LINQ 性能问题:记录较少且求和时间较长

发布于 2024-10-07 02:58:37 字数 873 浏览 0 评论 0原文

使用 WCF RIA 服务的 Silverlight 4 应用程序

我有一个带有 ComboBox 和 TabControl 的页面。每个 TabItem 都有一个显示 RAD Chart 控件的用户控件。组合框包含用于过滤用户控件在图表中显示的数据的项目。当组合框选择更改时,页面会更新实例/单例类的属性上保存的实体集合。用户控件会收到更改通知,并访问更新的实体集合以提供给图表控件。这一切都有效。当组合框选择更改时,用户控件将显示基于组合框所选项目选择的数据的子集。

让我感到困惑的是在准备传递给图表控件的值时迭代实体集合所需的时间。该图表显示 12 个月的数据,因此我迭代该集合 12 次,并使用 LINQ 查询来获取集合中对象的属性的 Sum。我已将性能问题隔离到执行 Sum 的单个 LINQ 查询:

Decimal sum = myCollection.Where(m => m.CreationDate.Month == month).Sum(m => (m.SalePrice ?? 0));

该单行代码有时可能需要一秒钟以上的时间才能运行。这并不可怕,但我迭代了 12 个月,因此该行代码运行了 12 次。

关键在于...

顶部的组合框选项是“所有记录”。因此,在我的测试示例中,第一次使用上面的代码行来获取“Sum”时,集合有 500 多条记录。它会在 0.2 秒内返回总和。我将 ComboBox 更改为过滤结果的选择,因此集合中只有 80 条记录。请注意,这并不是一组完全不同的记录,它只是满足另一个标准的 500 条记录的子集。上面这行代码运行需要 1.2 秒。 当我要求从 500 多条记录中求和时,需要 0.2 秒。当我要求 80 条记录求和时,需要 1.2 秒。

是什么原因导致的?

谢谢,

Silverlight 4 app using WCF RIA Services

I have a page with a ComboBox and a TabControl. Each TabItem has a usercontrol that displays a RAD Chart control. The ComboBox contains items that are used to filter the data that the user controls display in the charts. When the ComboBox selection changes, the page updates a collection of entities held on a property of a instance/singleton class. The user controls are notified of the change, and they access the updated collection of entities to give to the chart control. It all works. When the ComboBox selection changes, the usercontrols display a subset of the data chosen based on the ComboBox selected item.

What has me confused is the time it takes to iterate through the collection of entities while preparing the values that are handed to the chart control. The chart displays 12 months of data, so I iterate the collection 12 times and use a LINQ query to get a Sum on a property of the objects in the collection. I have isolated the performance issue to the single LINQ query that performs the Sum:

Decimal sum = myCollection.Where(m => m.CreationDate.Month == month).Sum(m => (m.SalePrice ?? 0));

That single line of code can sometimes take more than a second to run. That's not horrible, but I am iterating 12 months, so that line of code is run 12 times.

Here is the kicker...

The top ComboBox option is 'all records'. So in my test example, the first time the line of code above is used to get a 'Sum', the collection has 500+ records. It returns the Sum in .2 seconds. I change the ComboBox to a selection that filters the results down so the collection has only 80 records in it. Mind you, it is not a totally different set of records, it is just a subset of the 500 that meet another criteria. The line of code above takes 1.2 seconds to run. When I ask for a sum from 500+ records, it takes .2 seconds. When I ask for a sum from 80 records, it takes 1.2 seconds.

What could cause this?

Thanks,

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

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

发布评论

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

评论(1

别理我 2024-10-14 02:58:37

如何过滤以创建子集? “Collection”本身是一个 Linq 查询吗?它的执行会延迟到这一行吗?如果是这样,您看到的速度差异可能是过滤逻辑的应用。

加快计算速度的一种常见方法是一次性计算所有 12 个数字。通过使用 GroupBy Linq 运算符,这很容易:

var AllSums = Collection.GroupBy(m=>m.CreationData.Month).ToDictionary(g => g.Key, g => g.Sum(m => m.SalePrice ?? 0));
var JanuarySum = AllSums[January]; 

这应该优于 12 个完全独立的循环。

编辑:
以下是延迟执行的详细描述: Linq 和延迟执行

How do you filter to create the subset? Is "Collection" a Linq query itself, that is deffered in execution until this line? If so, the speed difference you are seeing could be the application of the filtering logic.

One general possibility for making this faster would be to compute all 12 numbers in a single pass. That is easy enough by using the GroupBy Linq operator:

var AllSums = Collection.GroupBy(m=>m.CreationData.Month).ToDictionary(g => g.Key, g => g.Sum(m => m.SalePrice ?? 0));
var JanuarySum = AllSums[January]; 

This should outperform 12 completely separate loops.

Edit:
Here is a good description of deferred execution: Linq and Deferred Execution

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文