asp.net如何加快頁面加載(三)——後臺代碼之細節2(while,do..while,for,foreach)

上一章節將的是如何使用選擇判斷語法,今天講的大家都熟悉的循環語句。我想大家對while,do..while,for,foreach都不陌生吧,但在於性能方面上似乎又覺得陌生? 到底哪個性能更高,效率更快呢。讓我們做個測試吧。

     其實在while,do...while,for這三個循環體中效率是一樣,爲什麼會這麼說? 其實在執行這三個循環過程中所執行的指令數是一樣,只不過執行過程中步驟,內容有細微的不一樣。讓我們看看下面代碼:

        public void Test_While() {
            int n = 10;
            while (n-- > 0) {
                //執行內容
            }
        }

        public void Test_For() {
            for (int n = 10; n > 0; n--) {
                //執行內容
            }
        }

        public void Test_doWhile() {
            int n = 10;
            do {
                //執行內容
            } while (--n > 0);
        }

      小計:從以上代碼來上,for語法最近簡潔,也最複雜;while語法最簡單;do..while執行方式比較特別,先執行內容後判斷條件,無論如何至少執行一次以上。在效率方面上while,do..while循環體方法中所執行的指令是一樣,而for會比前兩種多執行一次。在我們仔細觀察看着個多執行一次指令是因爲要聲明實例化n。那麼其實在執行whilehuo do..while之前也是對n先進性實例化。所以三者執行次數是一樣,執行效率同時也是一樣。至於會影響效率的是執行內容。

       而foreach在效率方面上與前三種有所不同。首先我們先看看foreach工作原理——在foreach循環中,迭代集合collectionObject的過程如下:

  1. 調用collectionObject.GetEnumerator(),返回一個IEnumerator引用。這個方法可以通過IEnumerable接口的實現代碼來獲得。但這是可選的。
  2. 調用返回的IEnumerator接口的MoveNext()方法。
  3. 如果MoveNext()方法返回true,就使用IEnumerator接口的Current屬性獲取對象的一個引用,用於foreach循環。
  4. 重複前面兩步,直到MoveNext()方法返回false爲止,此時循環停止。

接下來我們看看for 與foreach測試:

a.代碼部分:

public static void Test_For(string[] inits) {        
            int length = inits.Length;
            string txtfor="";
            for (int i = 0; i < length; i++) {
                //執行內容
                txtfor += inits[i];
            }
        }

        public static void Test_Foreach(string[] inits) {
            string txt = "";
            foreach (string s in inits) {
                txt += s;
            }
        }

        static void Main(string[] args)
        {

            string[] inits = new string[] { "1", "1", "1", "1", "1", "1", "1",
             "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1",
             "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1", "1"};
            Test.CodeTimer.Initialize();
            Test.CodeTimer.Time("一般for循環:", 5, () => { Test_For(inits); });
            Test.CodeTimer.Time("一般foreach循環:", 5, () => { Test_Foreach(inits); });
            Test.CodeTimer.Time("並行for循環:", 5, () =>
            {
                Parallel.For(0, inits.Length, (i) =>
                {
                    Test_For(inits);
                });
            });
            Test.CodeTimer.Time("並行foreach循環:", 5, () =>
            {
                Parallel.ForEach(inits, (i) =>
                {
                    Test_Foreach(inits);
                });
            });
            Console.Read();
            Console.ReadLine();

}

在測試代碼計數時間最早使用系統的stopWatch來完成,但考慮到系統的其他程序佔用資源,以及該程序的優先級別設置,數據統計等等。最終選擇採用老趙設計的CodeTimer來兩者之間的比較,當然我們也考慮現有的cpu都是多核多線程,所以我還加入了並行循環的比較, 在計算時間上我做了小改動:watch.ElapsedMilliseconds.ToString("N0") + "ms" 改爲 watch.Elapsed,更精確。

  這是結果如下:

我們從上述可以得出,在單線程執行foreach會比for佔用cpu之原來得大,但在執行效率上有很大的提升。在並行執行中,foreach佔盡了各個優勢。

那麼我們在所有的執行循環體中是不是都把for改成foreach來執行呢? 回答:肯定不是。接下來我們說說哪些情況下使用的for而不是foreach:

1.在片段執行過程使用for,原因是foreach是逐個遍歷,至始至終都是從第0位置開始遍歷。

2.對循環執行的對象需要更改時使用for,原因foreach遍歷過程對象是隻讀狀態,不允許更改對象值。

3.循環的對象不是數組,列表對象使用for,原因foreach只能是集合對象遍歷。

總結:選擇使用哪個循環語法時,事先考慮是否存在集合對象,對象是否需要遍歷,以及代碼如何更加簡練。



打個自己剛開發的網站廣告:生活信息查詢平臺

 轉載請標明原文地址,請大家支持版權。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章