依據前篇文章:參數傳入 dynamic 會讓函式傳回值也變成 dynamic,導致無法使用 LINQ Lambda 運算式。文末提到,依據方法多載(Method Overloading)與 dynamic 一文的研究心得,.NET 呼叫函式時若遇到參數為 dynamic 時,將改用System.Runtime.CompilerServices、System.CSharp.RuntimeBinder 命名空間物件與方法間接觸發,程序曲拆繁瑣許多。由此推測,參數傳入 dynamic 型別肯定會產生效能損耗,好奇心驅使之下,索性寫幾行程式實測親見為憑。

我設計測試程式如下,執行 100 萬次 "2017/08/26".Split('/').Length,連跑 10 回合測量執行時間,Test1() 與 Test2() 只差在 "2017/08/26" 宣告為 string 還是 dynamic:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TestDynamic
{
    class Program
    {
        static void Main(string[] args)
        {
            for (var i = 0; i < 10; i++)
            {
                Test1();
                Test2();
            }
            Console.ReadLine();
        }
 
        const int TEST_COUNT = 1000000;
 
        static void Test1()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            var str = "2017/08/26";
            long c = 0;
            for (var i = 0; i< TEST_COUNT; i++)
            {
                c += str.Split('/').Length;
            }
            sw.Stop();
            Console.WriteLine($"Strong Typed: {sw.ElapsedMilliseconds:n0}ms");
        }
        static void Test2()
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            dynamic str = "2017/08/26";
            long c = 0;
            for (var i = 0; i < TEST_COUNT; i++)
            {
                c += str.Split('/').Length;
            }
            sw.Stop();
            Console.WriteLine($"dynamic: {sw.ElapsedMilliseconds:n0}ms");
        }
    }
}

用 ildasm 反組譯工具先比較二者編譯結果的差異。

Test1 寫成 string str = "2017/08/26",MSIL 程式碼單刀直入,直接了當:

Test2 使用 dynamic str = "2017/08/26",其餘部分與 Test1 完全相同,但因為這一點差異,MSIL 程式碼截然不同,步驟多了 N 倍:

實測數據排除前面暖機階段,使用 dynamic 速度比明確宣告型別慢了約一倍。

慢一倍聽起來很恐怖,但不要忘記這畢竟是跑 100 萬次差不到 1 秒的奈米級差異,實務上對效能的影響幾可被忽略。但改幾個字元能讓程式變快又可回歸強型別檢查及 Intellisense 等諸多優勢,實在沒理由不做。在能用強型別取代 dynamic 的場合請明確宣告型別,尤其 CSHTML 使用 var 宣告變數承接 ViewBag 參數是不自覺使用 dynamic 的常見陷阱,應極力避免。 


Comments

Be the first to post a comment

Post a comment