Xamarin.Mac 미리 컴파일

개요

AOT(미리) 컴파일은 시작 성능을 개선하기 위한 강력한 최적화 기술입니다. 그러나 빌드 시간, 애플리케이션 크기 및 프로그램 실행에도 큰 영향을 줍니다. 적용하는 장단 부분을 이해하기 위해 애플리케이션의 컴파일 및 실행에 대해 자세히 알아보겠습니다.

C# 및 F#과 같은 관리되는 언어로 작성된 코드는 IL이라는 중간 표현으로 컴파일됩니다. 라이브러리 및 프로그램 어셈블리에 저장된 이 IL은 프로세서 아키텍처 간에 비교적 압축되고 이식 가능합니다. 그러나 IL은 중간 명령 집합일 뿐이며 어떤 시점에서는 IL을 프로세서와 관련된 머신 코드로 변환해야 합니다.

이 처리를 수행할 수 있는 두 가지 지점이 있습니다.

  • JIT(Just-In-Time) – 애플리케이션을 시작하고 실행하는 동안 IL은 메모리에서 머신 코드로 컴파일됩니다.
  • AOT(미리) – 빌드하는 동안 IL은 네이티브 라이브러리에 컴파일 및 기록되고 애플리케이션 번들 내에 저장됩니다.

각 옵션에는 다음과 같은 다양한 이점과 장단점이 있습니다.

  • JIT
    • 시작 시간 – 시작 시 JIT 컴파일을 수행해야 합니다. 대부분의 애플리케이션의 경우 이 순서는 100ms이지만, 대형 애플리케이션의 경우 이번에는 훨씬 더 많을 수 있습니다.
    • 실행 – JIT 코드를 사용 중인 특정 프로세서에 맞게 최적화할 수 있으므로 약간 더 나은 코드를 생성할 수 있습니다. 대부분의 애플리케이션에서 이것은 최대 몇 퍼센트 포인트 더 빠릅니다.
  • AOT
    • 시작 시간 – 미리 컴파일된 dylibs를 로드하는 것이 JIT 어셈블리보다 훨씬 빠릅니다.
    • 디스크 공간 – 이러한 dylibs는 상당한 양의 디스크 공간을 사용할 수 있습니다. AOTed 어셈블리에 따라 애플리케이션의 코드 부분 크기를 두 배 이상 늘릴 수 있습니다.
    • 빌드 시간 – AOT 컴파일은 JIT보다 훨씬 느리며 이를 사용하는 빌드 속도가 느려집니다. 이 속도 저하는 컴파일된 어셈블리의 크기와 수에 따라 초에서 1분 이상까지 다양할 수 있습니다.
    • 난독 처리 – 기계 코드보다 리버스 엔지니어링하기가 훨씬 쉬운 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을 사용할 수 있어야 합니다. iOS에서 애플리케이션은 JIT 컴파일을 사용할 수 없습니다. 코드의 해당 섹션도 AOT 컴파일됩니다.

하이브리드 옵션은 컴파일러에 이러한 섹션(예: iOS)을 컴파일하고 런타임에 IL을 사용할 수 없다고 가정하도록 지시합니다. 그런 다음 빌드 후 이 IL을 제거할 수 있습니다. 위에서 설명한 것처럼 런타임은 일부 위치에서 덜 최적화된 루틴을 사용해야 합니다.

추가 고려 사항

처리된 어셈블리의 크기 및 수와 함께 AOT 크기 조정의 부정적인 결과입니다. 예를 들어 전체 대상 프레임워크 는 최신보다 훨씬 더 큰 BCL(기본 클래스 라이브러리)을 포함하므로 AOT는 훨씬 더 오래 걸리고 더 큰 번들을 생성합니다. 이는 사용되지 않는 코드를 제거하는 링크와 전체 대상 프레임워크의 비호환성으로 인해 더욱 복잡해졌습니다. 애플리케이션을 최신으로 이동하고 최상의 결과를 위해 연결을 사용하도록 설정하는 것이 좋습니다.

AOT의 한 가지 추가 이점은 네이티브 디버깅 및 프로파일링 도구 체인과의 상호 작용이 향상됩니다. 대부분의 코드베이스는 미리 컴파일되므로 네이티브 크래시 보고서, 프로파일링 및 디버깅 내에서 더 쉽게 읽을 수 있는 함수 이름과 기호가 있습니다. JIT 생성 함수에는 이러한 이름이 없으며 종종 해결하기 어려운 이름 없는 16진수 오프셋으로 표시됩니다.