介绍:我花了一整天的时间研究为什么我的处理操作这么慢。对于低数据来说,这是非常缓慢的。我检查了sql视图、过程和linq逻辑--它们都工作得很完美。但后来我发现这件小事需要很长时间才能处理。
member X.CountStatistics()=
linq.TrueIncidents
|> PSeq.groupBy (fun v -> v.Name)
|> PSeq.map (fun (k, vs) -> k, PSeq.length vs)
|> Array.ofSeq
它只是计算分组值,但它花费了多少时间!在简单的桌子上大约10秒,
一定有什么愤怒的递归,但我看不见.
如何使此操作“更快”或将其重新编码到linq中?
发布于 2011-05-11 05:20:16
当前版本的F# LINQ支持有点有限。
我认为编写它的最好方法是牺牲使用F#的一些优雅,并将其作为一个存储过程写入SQL中。然后,您可以将存储过程添加到linq
数据上下文中,并使用生成的方法很好地调用它。将来,当F# LINQ有所改进时,您可以将其更改为:-)。
关于PSeq
示例--据我所知,存在一些效率问题,因为这些方法没有内联(由于内联,编译器能够进行一些额外的优化,并消除了一些开销)。您可以尝试下载源代码并将inline
添加到map
和groupBy
中。
发布于 2011-05-11 05:47:21
如果我正确理解,TrueIncidents是db中的一个表,您将整个内容拖到客户端应用程序中进行分组和计数。如果TrueIncidents是一个大表,那么这个操作将始终是缓慢的,因为您要移动大量的数据。这样做的“正确”方式是在数据库上,正如您建议使用linq到SQL,或者像Tomas建议的那样使用存储过程。
关于PSeq,我不认为内联会产生很大的影响。并行化有一种开销,为此,对列表进行摊销的开销需要相对较大,并且您对列表中的每一项执行的操作都必须是重要的。如果您对每个项执行的操作非常昂贵,那么对于一个小列表来说,并行化可能是值得的,然而,相反的情况似乎是正确的;即使一个列表非常大,并行一个小操作也不值得开销。因此,本例中的问题是,您对列表中的每个项执行的操作太小,因此并行化的成本总是会使操作更慢。要看到这一点,请考虑下面的C#程序,如果我们在一个包含1,000万项的列表上执行一个简单的添加操作,您将看到并行版本总是运行得很慢(嗯,在我目前正在工作的机器上,它有两个核,我猜在一台有更多核心的机器上,结果可能会有所不同)。
static void Main(string[] args)
{
var list = new List<int>();
for (int i = 0; i < 10000000; i++)
{
list.Add(i);
}
var stopwatch = new Stopwatch();
stopwatch.Start();
var res1 = list.Select(x => x + 1);
foreach (var i in res1)
{
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);
// 00:00:00.1950918 sec on my machine
stopwatch.Start();
var res2 = list.Select(x => x + 1).AsParallel();
foreach (var i in res2)
{
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);
// 00:00:00.3748103 sec on my machine
}
发布于 2011-05-11 21:19:04
正如在其他答案中已经提到的,如果您从数据库中获取大量数据,然后对这个大数据集进行一些计算,就会比它更昂贵(我认为IO部分将比计算部分更昂贵)。在您的具体情况下,您似乎希望对每个事件名称进行计数。其中一种方法可以是使用F# linq,只需从数据库中获取事件的“名称”(不需要其他列),然后在F#中进行分组和映射。它可能会帮助你提高性能,但不确定会有多大的改善。
https://stackoverflow.com/questions/5964826
复制相似问题