Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中求和方法的比较#_C#_Performance_Linq_Sum - Fatal编程技术网

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,则仍然会产生错误。我接受这个答案,因为您展示了另一种计算结果的方法