我需要使用Linq查询或在应用程序中迭代100,000多个数据。速度至关重要。我写了一个测试,但没有得到预期的结果。基本上,我将完全相同的数据在一个循环中提供给两个不同的函数100次。这些功能是相似的,除了其中一个我使用多个Linq查询,而另一个我手动迭代数据以构建信息。代码如下:
Linq版本:
//Get max and min of each
double maxX = (from node in pointCloud
select node.Node.Value.X).Max();
double maxY = (from node in pointCloud
select node.Node.Value.Y).Max();
double maxZ = (from node in pointCloud
select node.Node.Value.Z).Max();
double minX = (from node in pointCloud
select node.Node.Value.X).Min();
double minY = (from node in pointCloud
select node.Node.Value.Y).Min();
double minZ = (from node in pointCloud
select node.Node.Value.Z).Min();
//Extract all the x, y and z values into arrays
double[] x = (from node in pointCloud
select node.Node.Value.X).ToArray();
double[] y = (from node in pointCloud
select node.Node.Value.Y).ToArray();
double[] z = (from node in pointCloud
select node.Node.Value.Z).ToArray();
VS:
手册版本:
//Get max and min of each
double maxX = double.MinValue;
double maxY = double.MinValue;
double maxZ = double.MinValue;
double minX = double.MaxValue;
double minY = double.MaxValue;
double minZ = double.MaxValue;
List<double> x = new List<double>();
List<double> y = new List<double>();
List<double> z = new List<double>();
foreach (NodeDistance<KDTreeNode<g.Point3d>> node in pointCloud)
{
maxX = msf.Max(maxX, node.Node.Value.X);
maxY = msf.Max(maxY, node.Node.Value.Y);
maxZ = msf.Max(maxZ, node.Node.Value.Z);
minX = msf.Min(minX, node.Node.Value.X);
minY = msf.Min(minY, node.Node.Value.Y);
minZ = msf.Min(minZ, node.Node.Value.Z);
x.Add(node.Node.Value.X);
y.Add(node.Node.Value.Y);
z.Add(node.Node.Value.Z);
}
这是难题。当运行Linq版本时,第一次需要花费更长的时间。我在开始循环之前先启动秒表,然后在每次运行该功能后写下经过的时间。这是Linq函数运行的前5次:
00:00:00.0425169 (after 1st run)
00:00:00.0433850
00:00:00.0437312
00:00:00.0440666
00:00:00.0443969
....
00:00:00.1352192 (Total time for all 100 executions)
当我运行手动迭代的版本时,前五次是这样的:
00:00:00.0124269 (after 1st run)
00:00:00.0138497
00:00:00.0152502
00:00:00.0166348
00:00:00.0180180
....
00:00:00.1060389 (Total time for all 100 executions)
我将有30或40个不同的Linq查询,这些查询将在不同的时间运行。数据并没有全部排队,并且同一查询一遍又一遍地运行。如果我先运行一个Linq查询,然后再执行其他操作,则每次运行该查询实际上要花费0.04秒,那么该应用程序的运行速度将会非常慢。如果第一次运行任何Linq查询需要0.04秒,然后该应用不再发生该时间,那么使用Linq会更好。
有人在Linq和手动迭代方面有经验,并且在速度方面有一些指导吗?
答案 0 :(得分:4)
我想不出“直线C#”至少不如LINQ快的情况。肯定有可能LINQ明显慢。
因此,如果“速度”至关重要,那么最好不使用LINQ表达式。
重要要点:
请务必进行基准测试
<=我不确定您上面的示例是否真的有效基准测试
请务必使用大数据集
进行基准测试<=几年前,我遇到了一个看起来很无辜的LINQ表达式(由其他人编写),看上去不错,并且在少数项目中表现良好...但是速度却成倍地变慢,最终自爆出现堆栈溢出(无双关语)...包含1000项...
答案 1 :(得分:1)
您写道:
数据并没有全部排队,并且同一查询一遍又一遍地运行。
如果您将使用相同的输入多次执行LINQ查询,则明智的做法是保存结果。
var cityGroups = persons.GroupBy (person => person.City);
如果您查看references source of Enumerable.GroupBy,则会发现当您请求第一个元素时,会枚举完整的源序列以将各项放入“查找”表中。因此,如果再次枚举,将再次创建查找表:
因此,如果必须多次枚举,明智的做法是执行查询并将结果存储起来,以提高再次枚举时的效率:
var result = cityGroups.ToList();
foreach (var cityGroup in cityGroups)
{
DoSomething(cityGroup};
}
foreach (var cityGroup in cityGroups)
{
DoSomethinElse(cityGroup);
}
即使您不只是枚举,而是在其后添加一些LINQ语句,保存中间结果可能也是明智的:
var newYorkers = cityGroups.Where(cityGroup => cityGroup.Key == "New York").ToList();
var ghostTowns = cityGroups.Where(cityGroup => !cityGroup.Any()).ToList();
查找表将被创建两次。如果您在扩展结果之前执行ToList(),则查找表将仅创建一次
var result = cityGroups.ToList();
var newYorkers = result.Where(cityGroup => cityGroup.Key == "New York").ToList();
var ghostTowns = result.Where(cityGroup => !cityGroup.Any()).ToList();
我的建议是:如果您要一遍又一遍地执行相同的查询,请执行ToList(或“随您所需”)。