zoukankan      html  css  js  c++  java
  • 使用Linq求和方法Sum计算集合中多个元素和时应该注意的性能问题

    使用Linq求和方法Sum计算集合中多个元素和时应该注意的性能问题

    三五月儿 2014-09-10 22:40:31 21633 收藏 2
    分类专栏: C# 文章标签: Linq Sum Linq性能 Linq求和
    版权
    提出问题

    本文使用下面的实例来说明问题,以下是实例的完整代码。

    //************************************************************
    //
    // Sum应用示例代码
    //
    // Author:三五月儿
    //
    // Date:2014/09/10
    //
    // http://blog.csdn.net/yl2isoft
    //
    //************************************************************
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Linq;

    namespace LinqSumExp
    {
    class Program
    {
    static void Main(string[] args)
    {
    Console.WriteLine("数据准备中,请稍后...");

    List<Score> scoreList = CreateScoreList();

    Console.WriteLine("正在执行中,请稍后...");

    Stopwatch sw1 = new Stopwatch();
    sw1.Start();
    //------------代码片段1--------------------start
    int mathScoreSum1 = 0;
    int chineseScoreSum1 = 0;
    int engLishScoreSum1 = 0;
    int physicsScoreSum1 = 0;
    int chemistryScoreSum1 = 0;
    int biologyScoreSum1 = 0;
    foreach (var s in scoreList)
    {
    mathScoreSum1 += s.MathScore;
    chineseScoreSum1 += s.ChineseScore;
    engLishScoreSum1 += s.EngLishScore;
    physicsScoreSum1 += s.PhysicsScore;
    chemistryScoreSum1 += s.ChemistryScore;
    biologyScoreSum1 += s.BiologyScore;
    }
    //------------代码片段1--------------------end
    sw1.Stop();
    TimeSpan ts1 = sw1.Elapsed;
    Console.WriteLine("代码片段1的执行时间为:" + ts1.TotalMilliseconds);

    Stopwatch sw2 = new Stopwatch();
    sw2.Start();
    //------------代码片段2--------------------start
    int mathScoreSum2 = 0;
    int chineseScoreSum2 = 0;
    int engLishScoreSum2 = 0;
    int physicsScoreSum2 = 0;
    int chemistryScoreSum2 = 0;
    int biologyScoreSum2 = 0;
    mathScoreSum2 = scoreList.Sum(it => it.MathScore);
    chineseScoreSum2 = scoreList.Sum(it => it.ChineseScore);
    engLishScoreSum2 = scoreList.Sum(it => it.EngLishScore);
    physicsScoreSum2 = scoreList.Sum(it => it.PhysicsScore);
    chemistryScoreSum2 = scoreList.Sum(it => it.ChemistryScore);
    biologyScoreSum2 = scoreList.Sum(it => it.BiologyScore);
    //------------代码片段2--------------------end
    sw2.Stop();
    TimeSpan ts2 = sw2.Elapsed;
    Console.WriteLine("代码片段2的执行时间为:" + ts2.TotalMilliseconds);
    }
    static List<Score> CreateScoreList()
    {
    List<Score> scoreList = new List<Score>();
    Random rd = new Random();
    for (int i = 0; i < 100; i++)
    {
    Score s = new Score();
    s.StudentId = i;
    s.StudentName = "s" + i.ToString();
    s.MathScore = rd.Next(0, 100);
    s.ChineseScore = rd.Next(0, 100);
    s.EngLishScore = rd.Next(0, 100);
    s.PhysicsScore = rd.Next(0, 100);
    s.ChemistryScore = rd.Next(0, 100);
    s.BiologyScore = rd.Next(0, 100);
    scoreList.Add(s);
    }
    return scoreList;
    }
    }
    public class Score
    {
    public int StudentId { get; set; }
    public string StudentName { get; set; }
    public int MathScore { get; set; }
    public int ChineseScore { get; set; }
    public int EngLishScore { get; set; }
    public int PhysicsScore { get; set; }
    public int ChemistryScore { get; set; }
    public int BiologyScore { get; set; }
    }
    }
    实例中先定义Score类,使用Score类来保存学生各门功课的成绩,其中属性MathScore、ChineseScore、EngLishScore、PhysicsScore、ChemistryScore、BiologyScore分别用来保存数学、语文、英语、物理、化学、生物的成绩。接着,在CreateScoreList方法中生成包含100个Score对象的集合。最后,使用代码片段1和代码片段2来计算集合中各门功课的总和,其中,代码片段1通过遍历集合的方法来求和,而代码片段2使用Linq的求和方法Sum来实现求和。很显然,两种方法都可以完成求和这个基本功能。但是,在实际开发中,很多时候除了实现基本功能外,还需要考虑其他许多东西,比如性能。那么,这里我就弱弱的问一句:那种方法性能更好?
     

    答案揭晓

    大家请看黑板。(呵呵,是不是好黑好黑的一块板子啊)

    图1 程序运行结果图

    从程序的执行结果来看,方法1的性能更好。

    你可能会说,仅仅通过一次结果无法得出这个结论,因为偶然性。

    为了让你心服口服,那我就继续执行,执行,再执行。
    经过我n多次重复试验(n到底有多大,你猜),发现:每一次都是方法1耗时更少,方法1性能好于方法2。

    为了让我们的实验更具有说服力,增加数据量为1000,10000,100000来执行程序,下面是实验结果:

    1000次:方法1--1.2628;方法2--3.3205
    10000次:方法1--3.1866;方法2--8.8877
    100000次:方法1--15.3749;方法2--65.5758
    还是方法1耗时更少吧?

    你要是还不服,那我也没办法了,反正我是相信这个结果了。

    那么为什么会有这个结果呢?

    原因说明

    查看Linq求和方法Sum的源码,代码如下所示:

    public static int Sum(this IEnumerable<int> source)
    {
    if (source == null)
    {
    throw Error.ArgumentNull("source");
    }
    int num = 0;
    foreach (int num2 in source)
    {
    num += num2;
    }
    return num;
    }
    很显然,每调用一次Linq的求和方法都会遍历一次集合,所以,方法2会遍历集合5次,而方法1只需遍历集合1次,这就是原因所在。

    当然,需要求和的字段越多,数据量越大,两种方法的性能差距将越大。其实,除了在使用Linq的求和方法Sum时会遇见这个问题外,在使用Linq中其他扩展方法时也会遇到这种问题,希望大家以后注意了。

     
    ————————————————
    版权声明:本文为CSDN博主「三五月儿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/yl2isoft/article/details/39188641

    1.你好?是因為你,身邊的人好。—— by潇沫明月 -dont't repeat yourself 2.下辈子 无论 爱与不爱 我们 都不会 再见 3.有所见略同的对手 有对酒当歌的友人 有真心相对的红颜 有识千里马的伯乐 有一颗炽烈真诚的心 所以----- 要知道你最想做的 i will not repeat myself
  • 相关阅读:
    Encrypted Handshake Message
    RSAParameters Struct
    What if JWT is stolen?
    What's the difference between JWTs and Bearer Token?
    RSA Algorithm Example
    第18届Jolt大奖结果公布
    Ruby on rails开发从头来(windows)(三十六) 调试技巧
    Ruby on rails开发从头来(四十二) ActiveRecord基础(主键和ID)
    YouTube开放基础技术架构 让用户建自家YouTube
    Ruby on rails开发从头来(四十) ActiveRecord基础(Boolean属性)
  • 原文地址:https://www.cnblogs.com/kissy/p/14626938.html
Copyright © 2011-2022 走看看