對大型網站,技術涉及面非常廣,對硬體,軟體,程式設計語言,Web Service,防火牆等等有很高要求。
面對大量使用者,高並發請求,可以使用高效能伺服器,高效能程式設計語言,高效能資料庫,加大頻寬等,這意味著巨大的投入。
如果你沒有這樣的打算,而又想獲得更好的系統效能,則需要我們精打細算,從"軟"的方面著手。
如果你有過以下的一些用法,或者有不同見解,請賜教。
(1)Foreach比for有更好的執行效率。
Foreach所花的時間大約只有for的30%,通過測試結果,在兩者都可以使用的情況下,我們推薦效率更高的Foreach。另外用for寫入資料的時間大約是讀取資料時間的10倍。
(2)避免使用ArrayList
因為任何對象存放到裡面,都要轉化為System.Object類型,從ArrayList中取出資料要拆箱回原來的類型。建議使用.NET2.0的泛型,這是一個強型別,可以避免裝箱拆箱的效能消耗。
(3)不要使用UpperCase,LowerCase轉換字串,再進行比較。用String.Compare代替,他可以忽略大小寫進行比較。
(4)用StringBuilder代替字串串連符"+"
原因,見我的另一篇文章String 和BulidString效能比較和內在機制
(5)避免在迴圈內聲明變數,應該在迴圈外聲明變數,在迴圈裡初始化
1 // 避免
2
3 for ( int i = 0 ;i < 10 ;i ++ )
4
5 {
6
7 AnyClass cl = new AnyClass();
8
9 // ……
10
11 }
12
13 // 推薦
14 for ( int i = 0 ;i < 10 ;i ++ )
15
16 {
17
18 cl = new AnyClass();
19
20 // ……
21
22 }
(6)捕獲異常,不用使用System.Exception
1 // 避免
2 try
3 {
4 // TODO
5 }
6 catch (Exception ex)
7 {
8 // TODO(雖然簡單,但效能較差)
9 }
10
11 // 推薦
12 try
13 {
14 // TODO
15 }
16 catch (System.NullReferenceException ex)
17 {
18 // 對Null 物件異常處理
19 }
20 catch (System.ArgumentOutOfRangeException ex)
21 {
22 // 超出範圍異常處理
23 }
24 catch (System.InvalidCastException ex)
25 {
26 // 對異常轉化的處理
27 }
(7)不要使用異常控製程序流程。
異常捕獲對效能的消耗很大,眾所周知的,能避免使用最好不用
1 // 避免
2
3 try
4 {
5 result = 200 / num;
6 }
7 catch (Exception ex)
8 {
9 result = 0
10 }
11
12 // 推薦
13 try
14 {
15 result = num != 0 ? 200 / num: 0 ;
16 }
17 catch (Exception ex)
18 {
19 result = 0
20 }
(8)在遇到調用實現IDisposable對象的時候,用Using和try/finally來釋放資源
1 // 避免
2
3 public void ExceuteCommand()
4 {
5 SqlConnection sql = new SqlConnection(strCon);
6 SqlCommand cmd = new SqlCommand(sql);
7 sql.Dispose(); // 上面出錯,此處有可能永遠都調用不到
8 cmd.Dispose();
9 }
10
11 // 建議
12
13 // Using內並不是可以放任何對象,只有實現了IDisposable介面的對象才能被使用。
14 // 編譯器成IL時候,Using會自動把內容放在try/finally裡面。
15
16 try
17 {
18 using (SqlConnection sql = new SqlConnection(strCon))
19 {
20 using (SqlCommand cmd = new SqlCommand(sql))
21 {
22 // TODO
23 }
24 }
25 }
26 catch (Exception ex)
27 {
28 //
29 }
30 finally {
31 // 或者
32 // sql.Dispose();
33 // cmd.Dispose();
34 }
35
36 // 推薦
37
38 因為如果遇到多個實現IDisposable介面的對象需要釋放, try / finally更好些
39
40 // 推薦
41 SqlConnection sql = null ;
42 SqlCommand cmd = null ;
43
44 try
45 {
46 sql = new SqlConnection(strCon);
47 cmd = new SqlCommand(sql);
48 sql.Open();
49 cmd.ExecuteNonQuery();
50
51 }
52 finally {
53 if (sql != null )
54 sql.Dispose();
55 if (cmd != null )
56 cmd.Dispose();
57 }
(9)避免使用反射,反射是比較浪費效能的操作
通過反射來調用類型或方法,欄位或屬性是CLR要做更多的工作,如校正參數,檢查許可權,所以速度是非常慢的。對於打算寫一個動態構造類型(晚綁定)的應用程式,可以通過繼承,介面,委託來實現。
(10)實值型別組合成字串,請使用.ToStrng()方法,避免裝箱操作。
1 // 避免
2
3 var str = " hello " + 1 + 2 ;
4
5 // 推薦
6
7 var str = " hello " + 1 .ToString() + 2 .ToString();
(11)StopWatch類測試回合時間
View Code
1 public delegate void AddHandler();
2 class Program
3 {
4 static void Main( string [] args)
5 {
6 Utility.ProcessTimeSpan(Program.Add);
7 Console.Read();
8 }
9
10 public static void Add()
11 {
12 var a = 0 ;
13 for ( int i = 0 ; i < 100000000 ; i ++ )
14 {
15 a ++ ;
16 }
17 }
18 }
19
20 public static class Utility
21 {
22 public static void ProcessTimeSpan(AddHandler addDelegate)
23 {
24 // 推薦
25 DateTime start = DateTime.Now;
26 var timer = Stopwatch.StartNew();
27 addDelegate();
28 timer.Stop();
29 Console.WriteLine( " Method took {0} ms " , timer.ElapsedMilliseconds);
30
31 // 傳統
32
33 DateTime start = DateTime.Now;
34 SomeCodeToTime();
35 DateTime end = DateTime.Now;
36 Console.WriteLine( " Method took {0} ms " , (end - start).TotalMilliseconds);
37
38
39
40 }
41 }