C# C语言中求和方法的比较#
我正在处理一个项目的一个部分,该部分使用了大量的求和方法。这些求和方法应用于数据表 为了测试最佳方法,我使用以下方法 数据表结构C# C语言中求和方法的比较#,c#,performance,linq,sum,C#,Performance,Linq,Sum,我正在处理一个项目的一个部分,该部分使用了大量的求和方法。这些求和方法应用于数据表 为了测试最佳方法,我使用以下方法 数据表结构 class LogParser { public DataTable PGLStat_Table = new DataTable(); public LogParser() { PGLStat_Table.Columns.Add("type", typeof(string)); PGLStat_Tab
class LogParser
{
public DataTable PGLStat_Table = new DataTable();
public LogParser()
{
PGLStat_Table.Columns.Add("type", typeof(string));
PGLStat_Table.Columns.Add("desc", typeof(string));
PGLStat_Table.Columns.Add("count", typeof(int));
PGLStat_Table.Columns.Add("duration", typeof(decimal));
PGLStat_Table.Columns.Add("cper", typeof(decimal));
PGLStat_Table.Columns.Add("dper", typeof(decimal));
PGLStat_Table.Columns.Add("occurancedata", typeof(string));
}
}
LogParser pglp = new LogParser();
Random r2 = new Random();
for (int i = 1; i < 1000000; i++)
{
int c2 = r2.Next(1, 1000);
pglp.PGLStat_Table.Rows.Add("Type" + i.ToString(), "desc" + i , c2, 0, 0, 0, " ");
}
Stopwatch s2 = new Stopwatch();
s2.Start();
object sumObject;
sumObject = pglp.PGLStat_Table.Compute("Sum(count)", " ");
s2.Stop();
long d1 = s2.ElapsedMilliseconds;
以下方法用于填写表格
class LogParser
{
public DataTable PGLStat_Table = new DataTable();
public LogParser()
{
PGLStat_Table.Columns.Add("type", typeof(string));
PGLStat_Table.Columns.Add("desc", typeof(string));
PGLStat_Table.Columns.Add("count", typeof(int));
PGLStat_Table.Columns.Add("duration", typeof(decimal));
PGLStat_Table.Columns.Add("cper", typeof(decimal));
PGLStat_Table.Columns.Add("dper", typeof(decimal));
PGLStat_Table.Columns.Add("occurancedata", typeof(string));
}
}
LogParser pglp = new LogParser();
Random r2 = new Random();
for (int i = 1; i < 1000000; i++)
{
int c2 = r2.Next(1, 1000);
pglp.PGLStat_Table.Rows.Add("Type" + i.ToString(), "desc" + i , c2, 0, 0, 0, " ");
}
Stopwatch s2 = new Stopwatch();
s2.Start();
object sumObject;
sumObject = pglp.PGLStat_Table.Compute("Sum(count)", " ");
s2.Stop();
long d1 = s2.ElapsedMilliseconds;
使用Foreach循环的方法2
s2.Restart();
int totalcount = 0;
foreach (DataRow dr in pglp.PGLStat_Table.Rows)
{
int c = Convert.ToInt32(dr["count"].ToString());
totalcount = totalcount + c;
}
s2.Stop();
long d2 = s2.ElapsedMilliseconds;
使用Linq的方法3
s2.Restart();
var sum = pglp.PGLStat_Table.AsEnumerable().Sum(x => x.Field<int>("count"));
MessageBox.Show(sum.ToString());
s2.Stop();
long d3 = s2.ElapsedMilliseconds;
Linq语句产生一个错误
算术运算导致溢出
而Compute和Foreach循环仍然能够完成计算,尽管可能不正确
这种行为是否引起关注,或者我是否遗漏了指令?
(计算的数字也很大)
查询2
我觉得Linq做得最快,有没有优化的方法或参数
这使得它的表现更好
谢谢你的建议
阿文德查询1.正如您在文档中所看到的,扩展方法抛出一个on整数溢出。没有类似于方法2中使用的整数运算的功能
更新: 问题2
我的印象是Linq做得最快,是否有优化的方法或参数使其性能更好
另外,没有优化数组求和算法的方法(不使用并行计算)。Linq使foreach使用的时间加倍。因此,我认为这与linq性能无关,而是与计算效率低下有关(请注意,查询字符串解释存在开销) 您可以对linq示例(
AsEnumerable
)进行一些改进,但这是预期的行为-linq(2个对象)作为循环不能更快(使用for(var i=…)
循环而不是foreach可以做得更好)-我猜您想做的是使用Linq2Sql-然后是聚合(sum)将在数据库上完成,速度应该更快-但由于您似乎不使用数据库数据…下一步是最快的求和(使用预计算数据列并直接转换为int):
统计数字:
00:00:00.1442297, for/each, by column, (int)
00:00:00.1595430, for/each, by column, Field<int>
00:00:00.6961964, for/each, by name, Convert.ToInt
00:00:00.1959104, linq, cast<DataRow>, by column, (int)
00:00:00.1442297,按列列出(int)
00:00:00.1595430,针对/每个,按列、字段
00:00:00.6961964,for/each,by name,Convert.ToInt
00:00:00.1959104,林克,铸造,按柱,(内部)
其他代码:
static int Sum_ForEach_ByColumn_Field(LogParser pglp)
{
var column = pglp.PGLStat_Table.Columns["count"];
int totalcount = 0;
foreach (DataRow dr in pglp.PGLStat_Table.Rows)
{
totalcount += dr.Field<int>(column);
}
return totalcount;
}
static int Sum_ForEach_ByName_Convert(LogParser pglp)
{
int totalcount = 0;
foreach (DataRow dr in pglp.PGLStat_Table.Rows)
{
int c = Convert.ToInt32(dr["count"].ToString());
totalcount = totalcount + c;
}
return totalcount;
}
static int Sum_Linq(LogParser pglp)
{
var column = pglp.PGLStat_Table.Columns["count"];
return pglp.PGLStat_Table.Rows.Cast<DataRow>().Sum(row => (int)row[column]);
}
var data = GenerateData();
Sum(data);
Sum_Linq2(data);
var count = 3;
foreach (var info in new[]
{
new {Name = "for/each, by column, (int)", Method = (Func<LogParser, int>)Sum},
new {Name = "for/each, by column, Field<int>", Method = (Func<LogParser, int>)Sum_ForEach_ByColumn_Field},
new {Name = "for/each, by name, Convert.ToInt", Method = (Func<LogParser, int>)Sum_ForEach_ByName_Convert},
new {Name = "linq, cast<DataRow>, by column, (int)", Method = (Func<LogParser, int>)Sum_Linq},
})
{
var watch = new Stopwatch();
for (var i = 0; i < count; ++i)
{
watch.Start();
var sum = info.Method(data);
watch.Stop();
}
Console.WriteLine("{0}, {1}", TimeSpan.FromTicks(watch.Elapsed.Ticks / count), info.Name);
}
static int Sum\u ForEach\u ByColumn\u字段(LogParser pglp)
{
var column=pglp.PGLStat_Table.Columns[“count”];
int totalcount=0;
foreach(pglp.PGLStat_Table.Rows中的数据行dr)
{
totalcount+=dr.字段(列);
}
返回totalcount;
}
静态int Sum\u ForEach\u ByName\u Convert(LogParser pglp)
{
int totalcount=0;
foreach(pglp.PGLStat_Table.Rows中的数据行dr)
{
int c=Convert.ToInt32(dr[“count”].ToString());
totalcount=totalcount+c;
}
返回totalcount;
}
静态整数和(LogParser pglp)
{
var column=pglp.PGLStat_Table.Columns[“count”];
返回pglp.PGLStat_Table.Rows.Cast().Sum(row=>(int)row[column]);
}
var data=GenerateData();
总和(数据);
Sum_Linq2(数据);
var计数=3;
foreach(新[]中的var信息)
{
新的{Name=“for/each,by column,(int)”,Method=(Func)Sum},
新的{Name=“for/each,by column,Field”,方法=(Func)Sum\u ForEach\u by column\u Field},
新的{Name=“for/each,by Name,Convert.ToInt”,方法=(Func)Sum\u ForEach\u ByName\u Convert},
新的{Name=“linq,cast,by column,(int)”,方法=(Func)sumu linq},
})
{
var watch=新秒表();
对于(变量i=0;i
我的意思是,它似乎对大数字抛出异常,我甚至尝试将随机最小值和最大值更改为更大的范围1100000,并且每个和计算都有正确的结果,但linq命令抛出错误。虽然数据库不用于此场景,但我会检查是否也为表列生成了此错误。我同意linq可能更好,因为它是Sql相关的计算,并且可能存在orderby,其中clauseit在一定范围后是相同的。请注意,int type仍然在Foreach和Compute中使用,它们都计算并生成正确的结果。我想补充一点,对于一个常用的报表,当至少对5列或更多列求和时,总体性能水平确实非常高。Foreach的性能几乎是linq的3倍,是compute的5倍。虽然如果在同一列上应用相同的计算,则计算会有所改进,但在同一列上很少发生这种情况report@arvind你说的正确是什么意思?当您将c2更改为i时,您将得到从1到1000000的所有整数的总和。它是500000500000,而Int32.MaxValue是2147483647。区别在于linq检测溢出,而Compute和integer summation默默地计算错误的结果。是的,这就是我的意思,我同意foreach的计算速度很快。如果你看到我提到的问题,这些是更大的数字。但对于范围内的数字,速度的差异是值得注意的,如果用长时间代替int,则仍然会产生错误。我接受这个答案,因为您展示了另一种计算结果的方法