Xamarin.Mac 事先編譯

概觀

事先 (AOT) 編譯是一種功能強大的優化技術,可改善啟動效能。 不過,它也會以深遠的方式影響建置時間、應用程式大小和程序執行。 為了瞭解它所強加的取捨,我們將深入探討應用程式的編譯和執行。

以 C# 和 F# 等 Managed 語言撰寫的程式代碼會編譯為稱為 IL 的中繼表示法。 此 IL 儲存在您的連結庫和程式元件中,在處理器架構之間相對精簡且可攜。 不過,IL 只是一組中繼指令,而且在某些時候,IL 必須轉譯為處理器特定的機器碼。

此處理有兩點可以完成:

  • Just In Time (JIT) - 在啟動和執行應用程式期間,IL 會在記憶體中編譯為機器程式代碼。
  • 事先 (AOT) – 在建置期間,IL 會編譯並寫出至原生連結庫,並儲存在應用程式套件組合內。

每個選項都有一些優點和取捨:

  • JIT
    • 啟動時間 – 必須在啟動時完成 JIT 編譯。 對於大部分的應用程式而言,這會依 100 毫秒的順序排列,但對於大型應用程式而言,這次可能會大幅增加。
    • 執行 – JIT 程式代碼可以針對所使用的特定處理器進行優化,因此可以產生稍微更好的程序代碼。 在大部分的應用程式中,這最多會加快幾個百分點。
  • AOT
    • 啟動時間 – 載入預先編譯的動態連結庫比 JIT 元件快得多。
    • 磁碟空間 – 這些動態連結庫可能需要大量的磁碟空間。 視哪些元件為 AOTed 而定,它可以將應用程式的程式代碼部分大小加倍或更多。
    • 建置時間 – AOT 編譯明顯較慢 JIT,且會讓建置使用速度變慢。 視編譯的元件大小和數目而定,此速度變慢的範圍可能從秒到一分鐘以上。
    • 混淆 – 因為 IL 比機器碼更容易進行反向工程,因此不一定需要它來協助模糊化敏感性程序代碼。 這需要以下所述的「混合式」選項。

啟用 AOT

未來更新中,AOT 選項將會新增至 [Mac 組建] 窗格。 在此之前,啟用 AOT 需要透過 Mac Build 中的 [其他 mmp 自變數] 欄位傳遞命令行自變數。 選項如下:

--aot[=VALUE]          Specify assemblies that should be AOT compiled
                          - none - No AOT (default)
                          - all - Every assembly in MonoBundle
                          - core - Xamarin.Mac, System, mscorlib
                          - sdk - Xamarin.Mac.dll and BCL assemblies
                          - |hybrid after option enables hybrid AOT which
                          allows IL stripping but is slower (only valid
                          for 'all')
                          - Individual files can be included for AOT via +
                          FileName.dll and excluded via -FileName.dll

                          Examples:
                            --aot:all,-MyAssembly.dll
                            --aot:core,+MyOtherAssembly.dll,-mscorlib.dll

混合式 AOT

在執行 macOS 應用程式期間,運行時間預設會使用從 AOT 編譯所產生的原生連結庫載入的電腦程式代碼。 不過,有些程式代碼區域,例如 trampolines,JIT 編譯可能會產生更優化的結果。 這需要 IL 的 Managed 元件才能使用。 在 iOS 上,應用程式受限於任何 JIT 編譯的使用;程序代碼的那些區段也會進行 AOT 編譯。

混合式選項會指示編譯程式同時編譯這兩個區段(例如 iOS),但也假設在運行時間無法使用 IL。 然後,這個 IL 就可以在建置後移除。 如上所述,運行時間會強制在某些地方使用較不優化的例程。

進一步考量

AOT 縮放的負面後果,以及處理元件的大小和數目。 例如,完整 目標架構 包含比Modern大得多的基類連結庫 (BCL),因此AOT會花費相當長的時間併產生較大的套件組合。 這會由完整目標架構與連結的不相容所複合,這會去除未使用的程序代碼。 請考慮將您的應用程式移至新式,並啟用連結以獲得最佳結果。

AOT 的另一個優點是改善原生偵錯和分析工具鏈的互動。 由於大部分的程式代碼基底會事先編譯,因此其函式名稱和符號在原生當機報告、分析及偵錯內更容易讀取。 JIT 產生的函式沒有這些名稱,而且通常會顯示為難以解析的未命名十六進位位移。