C#性能优化5大技巧(最高可达62倍)

原文http://www.c-sharpcorner.com/UploadFile/dacca2/5-tips-to-improve-your-C-Sharp-code-part-1/

在阅读这篇文章之前,先阅读下面这篇文章。

优化C#代码性能的5个小窍门

1、你是否用异常机制来处理过用户输入验证?

如果是,那么你的程序性能已经降低了62倍。你不相信吗?等几分钟,我将会告诉你怎么回事。但是在示例之前,我们先了解清楚哪里进行异常是真正必要的。

举个例子,你验证用户输入的数据,如果无效,则抛出异常到客户端(我假定你是基于业务逻辑校验用户输入的)。

 

 
  1. class BusinessLogcCheck

  2. {

  3. public void Check()

  4. {

  5. try

  6. {

  7. //Your validation code is here

  8. }

  9. catch (Exception ex)

  10. {

  11. throw new Exception("My own exception");

  12. }

  13. }

  14. }


亲爱的朋友,在接下来的例子中,当你看到了屏幕输出的结果后,你将会认识到那是多么糟糕的习惯。让我们来看下面的代码。

 

 

 
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Diagnostics;

  6. using System.IO;

  7. using System.Net;

  8. using System.Net.NetworkInformation;

  9. namespace Test1

  10. {

  11. class Program

  12. {

  13. public static void ThrowTest()

  14. {

  15. throw new Exception("This is exceptopn");

  16. }

  17. public static Boolean Return()

  18. {

  19. return false;

  20. }

  21. static void Main(string[] args)

  22. {

  23. Stopwatch sw = new Stopwatch();

  24. sw.Start();

  25. try

  26. {

  27. ThrowTest();

  28. }

  29. catch

  30. {

  31. }

  32. sw.Stop();

  33. Console.WriteLine("With Exception " + sw.ElapsedTicks);

  34. sw.Restart();

  35. try

  36. {

  37. Return();

  38. }

  39. catch

  40. {

  41. }

  42. sw.Stop();

  43. Console.WriteLine("With Return " + sw.ElapsedTicks);

  44. Console.ReadLine();

  45. }

  46. }

  47. }


这是你正在等待的输入结果。

 

C#性能优化5大技巧(最高可达62倍)

 

我的证明非常简单。在一个函数中引发一个异常,而在另一个函数中返回用户输入校验后的布尔值。而且我附加了一个计算器让你相信异常处理是如何影响代码性能的。

所以我们可以得出一个结果:不要针对用户输入验证抛出一个异常,而使用布尔值来返回验证输入的业务逻辑(或者其他相似的技术)。因为异常对象代价太高了。(不过也高不过你所钟爱的衬衣。哈哈)

2.绝对不要在循环中使用try-Catch.

是的,这也是和异常处理相关的。我再重复一遍:绝对不要在循环中使用try-Catch。让我用一个例子来证明。

 

 
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Diagnostics;

  6. using System.IO;

  7. using System.Net;

  8. using System.Net.NetworkInformation;

  9. namespace Test1

  10. {

  11. class Program

  12. {

  13. static void Method1()

  14. {

  15. for (int i = 0; i < 1000; i++)

  16. {

  17. try

  18. {

  19. int value = i * 100;

  20. if (value == -1)

  21. {

  22. throw new Exception();

  23. }

  24. }

  25. catch

  26. {

  27. }

  28. }

  29. }

  30. static void Method2()

  31. {

  32. try

  33. {

  34. for (int i = 0; i < 1000; i++)

  35. {

  36. int value = i * 100;

  37. if (value == -1)

  38. {

  39. throw new Exception();

  40. }

  41. }

  42. }

  43. catch

  44. {

  45. }

  46. }

  47. static void Main(string[] args)

  48. {

  49. Stopwatch sw = new Stopwatch();

  50. sw.Start();

  51. Method1();

  52. sw.Stop();

  53. Console.WriteLine("Within Loop " + sw.ElapsedTicks);

  54. sw.Restart();

  55. Method2();

  56. sw.Stop();

  57. Console.WriteLine("Outside of Loop " + sw.ElapsedTicks);

  58. Console.ReadLine();

  59. }

  60. }

  61. }

这是屏幕输出结果。

 

C#性能优化5大技巧(最高可达62倍)

在这个程序中,方法1我在for循环中实现了异常处理机制,在方法2中则没有。输出结果说明在循环外面比在循环里面处理异常会快上2倍。

于是我们又得到一个结论:在项目中,不要在循环内部实现try-catch。(注意:不只是for循环,包括所有的循环。)

 

3.你是否疯狂了,以致于使用new操作符来创建整型变量?

亲爱的读者,不要为标题太长而怪我。绝不要使用new操作符来创建一个简单的整型变量。我知道你将会争辩说,如果你使用new操作符去创建一个简单的整型变量,系统会自动赋值为0,这样就可以免除像“变量未赋值”的错误。但是,在你创建本地变量去储存的位置,真的有必要自动赋值为0吗?让我们看看new操作符是如何把代码执行性能拖慢的。

 

 
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Diagnostics;

  6. using System.IO;

  7. using System.Net;

  8. using System.Net.NetworkInformation;

  9. namespace Test1

  10. {

  11. class Program

  12. {

  13. static void Main(string[] args)

  14. {

  15. Stopwatch sw = new Stopwatch();

  16. sw.Start();

  17. for (int i = 0; i < 1000; i++)

  18. {

  19. int a = new int();

  20. a = 100;

  21. }

  22. sw.Stop();

  23. Console.WriteLine("Using New operator:- " + sw.ElapsedTicks);

  24. sw.Restart();

  25. for (int i = 0; i < 1000; i++)

  26. {

  27. int a;

  28. a = 100;

  29. }

  30. sw.Stop();

  31. Console.WriteLine("Without new operator:- "+ sw.ElapsedTicks);

  32. Console.ReadLine();

  33. }

  34. }

  35. }


这是输出快照。

 

C#性能优化5大技巧(最高可达62倍)

是的,new操作符将执行速度拖慢了5倍。嗯...Sourav,我可以举出一个问题来否认结果。你一次创建1000个变量,而在我们的项目中是不可能一次创建1000个变量的。我们最多也只是创建2个或者3个。

OK!如果你的程序是web程序呢?如果你要校验流行的web程序的点击数,我确定每天将会超过1000个。

因此,我们又得到了一个结论:别太疯狂的使用new操作符来创建整型变量。

 

4.根据目的选择最好的集合。

作为.NET开发者,对于C#中的集合是非常熟悉的,而且他们到处被用于存值。让我们看看查询整数的性能如何?这是我的代码。

 

 
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Diagnostics;

  6. using System.IO;

  7. using System.Net;

  8. using System.Net.NetworkInformation;

  9. namespace Test1

  10. {

  11. class Program

  12. {

  13. static void Main(string[] args)

  14. {

  15. List<Int32> li = new List<Int32>(1000);

  16. Dictionary<int, int> di = new Dictionary<int, int>(1000);

  17. int[] arr = new int[1000];

  18. int a;

  19. for (int i = 0; i < 1000; i++)

  20. {

  21. li.Add(i);

  22. di.Add(i, i);

  23. arr[i] = i;

  24. }

  25. Stopwatch sw = new Stopwatch();

  26. sw.Start();

  27. a = li[500];

  28. sw.Stop();

  29. Console.WriteLine("From list:- " + sw.ElapsedTicks);

  30. sw.Start();

  31. a = arr[500];

  32. sw.Stop();

  33. Console.WriteLine("From Integer array:- " + sw.ElapsedTicks);

  34. sw.Restart();

  35. a = di[500];

  36. sw.Stop();

  37. Console.WriteLine("From Dictionary:- " + sw.ElapsedTicks);

  38. Console.ReadLine();

  39. }

  40. }

  41. }

这是输出结果。

 

C#性能优化5大技巧(最高可达62倍)

我们可以清晰的看到,字典集合的查询性能是最差的,而表单和整型数据的性能差不多。

C#性能优化5大技巧(最高可达62倍)

 

5.函数很好,但有时却不时。

如果你们还记得学习编程的日子,你们学到的第一个概念一般都是函数实现是一个好习惯,而且也很乐于将函数实现作为一个主要任务。函数在编程中有成千上万的优点,但是我们还是要看看函数是如何降低执行性能的。不过,这样的目的并不是反对函数,而是向你展示函数调用是有代价的机制,并且提供了一个观点:哪里需要实现函数,哪里不需要实现函数。让我们看看下面的代码。

 

 
  1. using System;

  2. using System.Collections.Generic;

  3. using System.Linq;

  4. using System.Text;

  5. using System.Diagnostics;

  6. using System.IO;

  7. using System.Net;

  8. using System.Net.NetworkInformation;

  9. namespace Test1

  10. {

  11. class test

  12. {

  13. public static void Print()

  14. {

  15. Console.WriteLine("I am function from Class");

  16. }

  17. }

  18. class Program

  19. {

  20. static void Main(string[] args)

  21. {

  22. Stopwatch sw = new Stopwatch();

  23. sw.Start();

  24. test.Print();

  25. sw.Stop();

  26. Console.WriteLine(sw.ElapsedTicks);

  27. sw.Restart();

  28. Console.WriteLine("I am single statement within main");

  29. sw.Stop();

  30. Console.WriteLine(sw.ElapsedTicks);

  31. Console.ReadLine();

  32. }

  33. }

  34. }


这是输入结果。

 

C#性能优化5大技巧(最高可达62倍)

这里我想在窗口上打印简单的信息,第一次调用类的静态方法,第二次直接在主函数中输出。是非常简单的Console.Writeline().而从屏幕输出的结果说明简单的单行输出比函数快了9倍。很显然,我们并没有去争论“函数的优缺点”的问题。(哈哈)

所以,我们又得到了一个简单的结论:在盲目实现一个函数前,先尝试理解情景,再作出最好的决定。

 

结论:

多谢读者们忍受了我这么长时间,以上示例都在电脑上进行了测试,并且是在程序的条件下编程,在release模式下输出结果。我的电脑是I3处理器、4G内存、Windows系统。如果你使用不同的电脑或者不同的输出,请看下面。那里有足够的空间来写这个版块的评论。