Round Robin 實作方法的效能分析

我在「[Winform] 在 Windows Form 中讓背景流動的方法」一文的程式中使用了取餘數的方法讓圖片位移以 Round Robin 方式不斷的循環 (0, 1, 2, 3, 4, ... 15 再重頭 0, 1, 2, 3, 4, ... 15...) ...

我在「[Winform] 在 Windows Form 中讓背景流動的方法」一文的程式中使用了取餘數的方法讓圖片位移以 Round Robin 方式不斷的循環 (0, 1, 2, 3, 4, ... 15 再重頭 0, 1, 2, 3, 4, ... 15...), 本來的寫法是像

if (offset >= backImage.Width)
    offset = 0;
offset++;

但後來想想, 我應該可以使用取餘數的方法讓上述方法更精簡:

offset = offset % backImage.Width;
offset++;

這兩種方法實際上並不會造成任何不同, 但是第二種寫法看起來好像比較專業的樣子。但是再仔細想想, 第一種寫法其實比較直覺, 而且並未用到整數計算; 說實在的, 即使第二種寫法看起來似乎比較精簡, 但會不會犧牲效能呢?

基於研究的精神, 我乾脆就寫了一個 Console 專案來證實:

using System.Diagnostics;

namespace Compare
{
    class Program
    {
        static Stopwatch sw = new Stopwatch();
        const long loop = 1000000000;

        static void Main(string[] args)
        {
            bool cont = true;
            while (cont)
            {
                Console.Write("Method 1 or 2? (0 to exit) ");
                ConsoleKeyInfo input = Console.ReadKey(true);
                Console.WriteLine();
                switch (input.KeyChar)
                {
                    case '1':
                        method1();
                        break;
                    case '2':
                        method2();
                        break;
                    case '0':
                        cont = false;
                        break;
                }
            }
        }

        static void method1()
        {
            long j = 0;
            sw.Restart();
            for (int i = 0; i < loop; i++)
            {
                j = j % loop;
                j++;                
            }
            Console.WriteLine("Method 1 (Use % operator)");
            Console.WriteLine("Elapsed: {0}", sw.Elapsed.ToString());
            Console.WriteLine();
        }

        static void method2()
        {
            long j = 0;
            sw.Restart();
            for (int i = 0; i < loop; i++)
            {
                if (j >= loop) j = 0;
                j++;
            }
            Console.WriteLine("Method 2 (Use if statement)");
            Console.WriteLine("Elapsed: {0}", sw.Elapsed.ToString());
            Console.WriteLine();
        }
    }
}

程式中 Method2() 方法採用 if 判斷, 不做計算, Method1() 則採用餘數計算。在我的機器上其結果如下:

Method 1 or 2? (0 to exit)
Method 1 (Use % operator)
Elapsed: 00:00:12.5213474

Method 1 or 2? (0 to exit)
Method 2 (Use if statement)
Elapsed: 00:00:05.0958347

從結果看來, 兩者效能果然有蠻大的差異。簡單的 if 判斷所花費的時間 (5.09 秒) 比使用餘數計算所花費的時間 (12.52秒) 少了一倍以上。從這裡可以看出我的判斷果然是正確的。

不過話說回來, 如果情況不是非常 critical 的話, 其實二者的差異也不是太大; 如果運算達十億次才差七秒鐘, 應該可以算是微小差異了。


Dev 2Share @ 點部落