빌트인 프로파일러로 성능 측정(Measuring Performance with the Built-in Profiler)
물리 성능 최적화

빌드한 iOS 플레이어 크기 최적화(Optimizing the Size of the Built iOS Player)

플레이어 크기를 줄이는 방법에는 Xcode 안에서 적절한 Release build 를 만드는 방법과 Unity 에디터에서 Stripping Level 을 변경하는 방법 두 가지가 주로 사용됩니다.

배포용 빌드

최종 릴리스 빌드는 Xcode 4.x/5.x 커맨드인 Product -> Archive__를 사용하여 만들어야 합니다. 커맨드를 사용하면 빌드가 릴리스 설정을 사용하여 만들어지고 모든 디버그 심볼이 스트립됩니다. 커맨드를 전달한 후에는 최근 Xcode가 Organizer 창의 Archives__ 탭으로 전환됩니다. Window -> Organizer 메뉴를 통해 수동으로 이 탭으로 이동할 수 있습니다. 탭에는 App Store size estimation__과 Distribution__이라는 매우 유용한 기능이 2개 있습니다. 빌드 크기 추정 기능은 꽤 효과적이지만, 3G 다운로드 최고 속도(현재 100MB)를 목표로 하는 경우 항상 약간의 오차를 감안하는 것이 좋습니다.

iOS 스트리핑 레벨(Stripping Level)

스트리핑 작업에 의한 크기 최적화는 다음과 같이 진행됩니다.

  1. Strip assemblies 수준: 스크립트의 바이트코드를 분석하여 스크립트에서 레퍼런스되지 않는 클래스와 메서드가 DLL에서 삭제하고 AOT 컴파일 단계에서 제외합니다. 이 최적화는 메인 바이너리와 첨부되는 DLL의 크기를 줄이며, 반사를 사용하지 않는 한 안전합니다.

  2. Strip ByteCode 수준: (Data 폴더에 저장된) .NET DLL은 메타데이터만 남도록 스트립됩니다. 이렇게 할 수 있는 이유는 모든 코드가 AOT 단계에서 이미 미리 컴파일되어 메인 바이너리에 링크되기 때문입니다.

  3. Use micro mscorlib 수준: 더 작고 특수한 mscorlib 버전을 사용합니다. Security, Reflection.Emit, Remoting, non-Gregorian calendars 등 일부 컴포넌트는 라이브러리에서 삭제됩니다. 또한 내부 컴포넌트 간 상호 종속성이 최소화됩니다. 이 최적화는 메인 바이너리와 mscorlib.dll의 크기를 줄이지만, 일부 System 및 System.Xml 어셈블리 클래스와 호환되지 않으므로 주의해서 사용해야 합니다.

각 수준은 누적되어 적용됩니다. 3수준 최적화는 1수준과 2수준 최적화를 포함하고, 2수준 최적화는 1수준 최적화를 포함합니다.

Micro mscorlib 은 많이 스트립된 코어 라이브러리 버전입니다. Mono 런타임에 필요한 항목만 Unity 에디터에 남습니다. Micro mscorlib을 사용하는 모범 사례는 애플리케이션에 필요하지 않은 클래스나 기타 .NET 기능을 사용하지 않는 것입니다. 제외할 수 있는 좋은 예로 GUID가 있습니다. GUID는 커스텀 의사(pseudo) GUID로 쉽게 대체할 수 있고, 이렇게 하면 성능이 향상되고 앱 크기가 줄어듭니다.

IL2CPP로 스트리핑

The equivalent of Strip ByteCode is always enabled when the IL2CPP scripting backend is used. In this case, the Stripping Level option is replaced with an Boolean option named Strip Engine Code. If this option is enabled, unused modules and classes in the Unity Engine code will be removed, if it is disabled, all of the modules and classes in the Unity Engine code will be preserved.

The link.xml file (described below) can be used to effectively disable byte code stripping by preserving both types and full assemblies. For example, to prevent the System assembly from being stripped, the following link.xml file can be used:

<linker>
       <assembly fullname="System" preserve="all"/>
</linker>

Note: The ability to preserve an entire assembly applies only to the IL2CPP scripting backend.

반사(Reflection)를 사용하면서 스트리핑하는 방법

Stripping depends highly on static code analysis and sometimes this can’t be done effectively, especially when dynamic features like reflection are used. In such cases, it is necessary to give some hints as to which classes shouldn’t be touched. Unity supports a per-project custom stripping blacklist. Using the blacklist is a simple matter of creating a link.xml file and placing it into the Assets folder (or any subdirectory of Assets). An example of the contents of the link.xml file follows. Classes marked for preservation will not be affected by stripping:

<linker>
       <assembly fullname="System.Web.Services">
               <type fullname="System.Web.Services.Protocols.SoapTypeStubInfo" preserve="all"/>
               <type fullname="System.Web.Services.Configuration.WebServicesConfigurationSectionHandler" preserve="all"/>
       </assembly>

       <assembly fullname="System">
               <type fullname="System.Net.Configuration.WebRequestModuleHandler" preserve="all"/>
               <type fullname="System.Net.HttpRequestCreator" preserve="all"/>
               <type fullname="System.Net.FileWebRequestCreator" preserve="all"/>
       </assembly>

       <assembly fullname="mscorlib">
               <type fullname="System.AppDomain" preserve="fields"/>
               <type fullname="System.InvalidOperationException" preserve="fields">
                       <method signature="System.Void .ctor()"/>
               </type>
               <type fullname="System.Object" preserve="nothing">
                      <method name="Finalize"/>
               </type>
       </assembly>
</linker>

A project can include multiple link.xml files. Each link.xml file can specify a number of different options.

  • The assembly element indicates the managed assembly where the nested directives should apply.
  • The type element is used to indicate how a specific type should be handled. It must be a child of the assembly element. The fullname attribute can accept the ‘*’ wild card to match one or more characters.
  • The preserve attribute can take on one of three values:
    • all: Keep everything from the given type (or assembly, for IL2CPP only).
    • fields: Keep only the fields of the given type.
    • nothing: Keep only the given type, bug none of its contents.
  • The method element is used to indicate that a specific method should be preserved. It must be a child of the type element. The method can be specified by name or by signature.

The stripped assemblies are output to a directory below the Temp directory in the project (the exact location varies depending on the target platform). The original, unstripped assemblies are available in the not-stripped directory in the same location as the stripped assemblies. A tool like ILSpy can be used to inspect the stripped and unstripped assemblies to determine what parts of the code were removed.

참고: 때로는 어떤 클래스가 애플리케이션에 필요한데도 스트립되는 것은 아닌지 알기 어려울 수 있습니다. 스트립된 애플리케이션을 시뮬레이터에서 실행하고 Xcode 콘솔에 표시되는 오류 메시지를 확인하여 이와 관련된 유용한 정보를 얻을 수 있습니다.

배포판을 최대한 작게 만들기 위한 간단한 체크리스트

  1. 에셋을 최소화합니다. 텍스처의 PVRTC 압축을 활성화하고 해상도를 최대한 줄입니다. 비압축 사운드 수도 최소화합니다. 여기에서 파일 크기를 줄이는 방법에 대한 팁을 몇 개 더 확인할 수 있습니다.
  2. iOS 스트리핑 레벨을 Use micro mscorlib 으로 설정합니다.
  3. 스크립트 호출 최적화 레벨을 Fast but no exceptions 로 설정합니다.
  4. System.dll 또는 System.Xml.dll에 있는 것을 코드에 사용하지 않습니다. 이런 라이브러리는 마이크로 mscorlib와 호환되지 않습니다.
  5. 불필요한 코드 종속성을 제거합니다.
  6. API 호환성 수준을 .Net 2.0 subset 으로 설정합니다. .Net 2.0 서브셋은 다른 라이브러리와 제한적으로 호환됩니다.
  7. JS 배열을 사용하지 않습니다.
  8. 일반 컨테이너를 값 타입(구조체 포함)과 함께 사용하지 않습니다.

Unity로 앱을 얼마나 작게 만들 수 있습니까?

모든 크기 최적화를 끄고 만든 빈 프로젝트는 앱 스토어에서 22MB 미만의 공간을 차지합니다. 코드 스트리핑을 사용하면 메인 카메라만 포함하는 빈 씬의 크기를 앱 스토어에서 12MB 미만(압축하고 DRM 연결 시)까지 줄일 수 있습니다.

앱을 앱 스토어에 릴리스한 후 크기가 커지는 이유는 무엇입니까?

앱을 퍼블리시하면 Apple 앱 스토어 서비스가 바이너리 파일을 먼저 암호화한 다음 zip 파일로 압축합니다. 암호화하면 코드 세그먼트의 “임의성”이 증가하므로 압축하기가 더 어려워집니다. 제출하기 전에 위의 “배포용 빌드” 섹션에서 앱 스토어 크기를 최적화하는 방법을 참조하십시오.

빌트인 프로파일러로 성능 측정(Measuring Performance with the Built-in Profiler)
물리 성능 최적화