LoginSignup
1

More than 3 years have passed since last update.

【Unity】Assembly Definitionの参照方法によるコンパイル時間の違いについて調査してみた

Last updated at Posted at 2020-01-08

Assembly Definition Filesを導入する/している方向けの小ネタです。
Assembly Definition Filesだと長いので記事中ではADFと表記

ADFを導入して開発を行っていると、ADFの参照方法によって体感的にコンパイル時間の違いを感じることが有りました。 (私だけ..?)
参照方法に紐づくコンパイル時間については以下のように分類できそうな印象があります。

そしてこれらの参照方法の挙動を見た感じだと、内部的に.csprojが生成されるかどうかの条件にもなっているように思われました。簡潔にまとめると以下のように分類できそうです。

  • Project以下及びローカルパッケージにあるADFを参照
    • .csprojが生成される
  • 公式レジストリ/リポジトリから取得してパッケージ内のADFを参照
    • .csprojは生成されない
    • 取得したパッケージそのものはLibrary/PackageCache以下にキャッシュされる 2

この挙動の違いがコンパイル時間に影響を及ぼしている?と予想して簡単に調査の方を行ってみました。
まだ分からない点や未調査項目がチラホラと残っており...ほぼ個人メモの公開みたいな内容にはなりますが、一先ずは現状見えている範囲についてだけ纏めていきます。
(間違いとかあればコメントなりTwitterなりで直接教えて頂けると幸いです :bow:)

※注意点

※この記事中ではADFに関する基本的な所は解説しません。
基本的な情報については以下の記事がおすすめです。

検証環境

  • Windows 10
    • CPU: Core i7-8700K
  • Unity 2018.4.14f

TL;DR

先に要点を纏めます。

  • .csprojが生成されないほうがコンパイル時間が短くなった
    • Unity公式のレジストリやリポジトリ1から取得すると.csprojが生成されない
    • コード量を多く含むADFを参照している際に、.csprojの有無でコンパイル時間が大幅に変わる事は無い
      • とは言えども.csprojがある場合には0.5~1sec以内でコンパイル時間が伸びているので、チリツモ案件ではあるかもしれない..
    • ADFの参照が多い上で.csprojもある場合には、その分コンパイル時間が伸びる
      • 入れているパッケージ数が多い場合には注意しても良いかも
      • 公式レジストリから取得した公式パッケージを無闇にローカル参照(Embedded Packageなど)に切り替えるとコンパイル時間が長くなる
        • → 公式パッケージを変更したり追うときにだけEmbedded Packageに切り替えるなりしたほうが良いかもしれない

調査内容

調査にあたっては以下のテストを行ってコンパイル時間を計測してみました。
これらが.csprojの有無でコンパイル時間にどう影響を及ぼしていくのかを見ていきます。

  • ① 大量のコードを含んだADFを参照してコンパイル
    • → コード量が多いアセンブリを参照している時のコンパイル時間の影響について調査
  • ② PackageManagerから公式パッケージを30個近くインストールした上でコンパイル
    • → 数多くのアセンブリを参照している状態でのコンパイル時間の影響について調査

計測方法について

コンパイル時間の計測方法としては、以下の2つのスクリプトに変更を掛けてそれぞれのコンパイル時間を計測していきます。
(コードに1行変更を加えてコンパイルを実行)

  • Sample.csに変更を加えてAssembly-CSharp.dllAssembly-CSharp-Editor.dllのコンパイル時間を計測
  • AsmDefSample.csに変更を加えてAsmDefSample.dll及びAssembly-CSharp.dllAssembly-CSharp-Editor.dllのコンパイル時間を計測
    • AsmDefSample.asmdef【Auto Referenced】3は有効化
      • → 故にAssembly-CSharp.dllAssembly-CSharp-Editor.dllも合わせてコンパイルされる)
フォルダ構成
[Assets]
    L [Scripts]
        L [AsmDefSample]
            L AsmDefSample.cs
            L AsmDefSample.asmdef
        L Sample.cs

// ※[]はフォルダを指す

※実際のコンパイル時間はコードの変更量なども踏まえて変動していくかと思われるので、あくまでご参考程度に。。

コンパイル時間の計測

コンパイル時間の計測については以下の記事を参考にしました。

コンパイル時間の表記については以下のようにそれぞれのスクリプトを更新した際の時間を載せていきます。4

Sample.cs AsmDefSample.cs
-sec -sec

※追記

上記の計測ではEditorApplication.isCompilingを用いて計測してますが...以下のAPIを使うと「コンパイル時間」「アセンブリのリロードに掛かった時間」を分けた上で更に正確な時間を計測できそうです。
(後から知ったので....この記事中ではEditorApplication.isCompilingの計測結果を記載)

更に補足しておくと、EditorApplication.isCompilingは2019の最新辺り?から挙動が怪しいっぽいので、こちらも踏まえて上記のAPIを利用したほうが良いかもしれません。

① 大量のコードを含んだADFを参照してコンパイル

「大量のコードを含んでいるADFを参照していたらどの程度の影響が出るのか?」について調べてみました。
→ 懸念事項として「大量のコードを含んでいるADF.csprojの有無によってコンパイル時間が大きく変わってくる」とかあると怖いので..。

調査にあたっては以下の計測用パッケージを用意したので、こちらをプロジェクトに導入して計測を行います。

  • mao-test-h/large-code-sample
    • LargeCodeSample.asmdefは【Auto Referenced】を有効化
    • ※計測対象のAsmDefSample.asmdefLargeCodeSample.asmdefを参照するように設定
パッケージのフォルダ構成
[Large code sample]
    L [Runtime]
        L [Generated]
            L ※コンパイル時間計測用の自動生成コード一式
        L LargeCodeSample.asmdef
    L CHANGELOG.md
    L LICENSE.md
    L package.json
    L README.md

計測用に用意した大量のコードは自動生成で出力してます。
※自動生成コードとしては「Unityでコンパイル時間を可視化する」のGenerateHugeを参考に生成。

ちなみに、このコード含むアセンブリ単体のコンパイル時間は大体28.35sec近く掛かりました。

計測結果

条件別に計測結果を載せていきます。

● 検証用パッケージをリポジトリ1から直接取得してADFを参照

先ずは公開リポジトリにある検証用パッケージを以下のようにmanifest.jsonに登録して取得します。

冒頭でも軽く触れてある通り、この手法で取得したパッケージはLibrary/PackageCacheにキャッシュされてアセンブリに対応する.csprojが生成されない状態となります。

manifest.json
{
  "dependencies": {
    "com.mao.large-code-sample": "https://github.com/mao-test-h/large-code-sample.git",
    ※中略

こちらを計測用コード側(Sample.cs/AsmDefSample.cs)から参照するようにした上でコンパイルを行います。
計測結果は以下のようになりました。

Sample.cs AsmDefSample.cs
4.15sec 4.8sec

この結果を踏まえつつ、ローカル参照時(.csprojが生成されるパターン)と比較してどれくらいコンパイル時間に影響が出るのかを見ていきます。

● ローカルに有るパッケージを登録してADFを参照

↑で公開リポジトリより取得した検証用パッケージをローカル読みに変更する形で検証を進めます。

ローカル読みに切り替える方法としては幾つかありますが、今回はLibrary/PackageCache以下にある該当パッケージをPackages以下に移動することによる「Embedded Package」としての切り替えで対応を進めます。
※詳細はドキュメント参照 → Local packages inside your Project

このパターンで読み込むと、アセンブリに対応する.csprojが生成されるようになります。
その上でコンパイル時間の計測結果としては以下のようになりました。

Sample.cs AsmDefSample.cs
4.83sec 5.59sec

.csprojが無い方と比べると少しコンパイル時間が伸びました。 (差分的には1sec以内ではあるが...)
※おそらくは.csprojが生成されたことによってコンパイル周りに影響が生じた?と予想してますが...詳細については調べきれておらず...。

何れにせよ「.csprojがある場合には、コードサイズに影響してコンパイル時間が大きく伸びる」と言った懸念事項が無いことを確認できました。

● パッケージの中身をAssets/Scripts以下に直接配置してADFを参照

そもそもとしてコードを「Assets以下に置いた時」と「パッケージとして参照する時」とでコンパイル時間に違いが出てくるのか?が気になったので、参考序に検証用パッケージからコード一式を抜き出す形で簡単に調査してみました。
※この方式でも同じく.csprojは生成される。

配置時のフォルダ構成としては以下のようになります。

[Assets]
    L [Scripts]
        L [Runtime]                // 検証用パッケージから抜き出したコード
            L [Generated]
                L ※コンパイル時間計測用の自動生成コード一式
            L LargeCodeSample.asmdef
        L [AsmDefSample]
            L AsmDefSample.cs
            L AsmDefSample.asmdef
        L Sample.cs

検証結果としては以下のようになりました。

Sample.cs AsmDefSample.cs
4.74sec 4.8sec

ローカルパッケージ参照と比べると、Sample.csを更新した時のコンパイル時間はほぼ変わらないものの...AsmDefSample.csを更新した時のコンパイル時間が短くなっている...?

① まとめ

一先ずはここまでの検証で以下のポイントが見えてきました。

  • コード量を多く含むADFを参照している際に、.csprojの有無でコンパイル時間が大幅に変わる事は無い
    • とは言えども0.5~1sec以内でコンパイル時間が伸びているので、チリツモ案件ではあるかもしれない...

大幅に違いは出ないにせよチリツモ案件かもしれないので、可能そうであれば「公式レジストリやリポジトリからの取得(.csprojが生成されない方)」がコンパイル速度的には良いかもしれません。

② PackageManagerから公式パッケージを30個近くインストールした上でコンパイル

①の検証だけだと参照しているパッケージそのものは1つしか無いので、情報としては少し乏しい感がありました。
なので「数多くのADFを参照していたらどの程度の影響が出るのか?」について調査すべく、PackageManagerから30個近くのパッケージをインストールして検証を行ってみました。

今回導入したパッケージとしては以下のものになります。5

導入パッケージについて (クリックで展開)

Art000.png

manifest.json (クリックで展開)
manifest.json
{
  "dependencies": {
    "com.mao.large-code-sample": "https://github.com/mao-test-h/large-code-sample.git",
    "com.unity.2d.animation": "2.0.0-preview.3",
    "com.unity.2d.ik": "1.0.8-preview.1",
    "com.unity.2d.pixel-perfect": "1.0.1-preview",
    "com.unity.2d.spriteshape": "1.0.14-preview.2",
    "com.unity.addressables": "1.5.0",
    "com.unity.analytics": "3.2.3",
    "com.unity.assetbundlebrowser": "1.7.0",
    "com.unity.assetgraph": "1.6.0-preview",
    "com.unity.build-report-inspector": "0.1.2-preview",
    "com.unity.burst": "1.1.2",
    "com.unity.cinemachine": "2.2.9",
    "com.unity.collab-proxy": "1.2.16",
    "com.unity.collections": "0.0.9-preview.12",
    "com.unity.entities": "0.0.12-preview.24",
    "com.unity.jobs": "0.0.7-preview.6",
    "com.unity.mathematics": "1.1.0",
    "com.unity.package-manager-ui": "2.0.8",
    "com.unity.performance.profile-analyzer": "0.5.0-preview.1",
    "com.unity.postprocessing": "2.2.2",
    "com.unity.purchasing": "2.0.6",
    "com.unity.quicksearch": "1.4.1",
    "com.unity.render-pipelines.core": "4.10.0-preview",
    "com.unity.render-pipelines.lightweight": "4.10.0-preview",
    "com.unity.rendering.hybrid": "0.0.1-preview.4",
    "com.unity.scriptablebuildpipeline": "1.5.4",
    "com.unity.shadergraph": "4.10.0-preview",
    "com.unity.textmeshpro": "1.4.1",
    "com.unity.vectorgraphics": "1.0.0-preview.33",
    "com.unity.visualeffectgraph": "4.10.0-preview",
    "com.unity.modules.ai": "1.0.0",
    "com.unity.modules.animation": "1.0.0",
    "com.unity.modules.assetbundle": "1.0.0",
    "com.unity.modules.audio": "1.0.0",
    "com.unity.modules.cloth": "1.0.0",
    "com.unity.modules.director": "1.0.0",
    "com.unity.modules.imageconversion": "1.0.0",
    "com.unity.modules.imgui": "1.0.0",
    "com.unity.modules.jsonserialize": "1.0.0",
    "com.unity.modules.particlesystem": "1.0.0",
    "com.unity.modules.physics": "1.0.0",
    "com.unity.modules.physics2d": "1.0.0",
    "com.unity.modules.screencapture": "1.0.0",
    "com.unity.modules.terrain": "1.0.0",
    "com.unity.modules.terrainphysics": "1.0.0",
    "com.unity.modules.tilemap": "1.0.0",
    "com.unity.modules.ui": "1.0.0",
    "com.unity.modules.uielements": "1.0.0",
    "com.unity.modules.umbra": "1.0.0",
    "com.unity.modules.unityanalytics": "1.0.0",
    "com.unity.modules.unitywebrequest": "1.0.0",
    "com.unity.modules.unitywebrequestassetbundle": "1.0.0",
    "com.unity.modules.unitywebrequestaudio": "1.0.0",
    "com.unity.modules.unitywebrequesttexture": "1.0.0",
    "com.unity.modules.unitywebrequestwww": "1.0.0",
    "com.unity.modules.vehicles": "1.0.0",
    "com.unity.modules.video": "1.0.0",
    "com.unity.modules.vr": "1.0.0",
    "com.unity.modules.wind": "1.0.0",
    "com.unity.modules.xr": "1.0.0"
  },
  "lock": {
    "com.mao.large-code-sample": {
      "hash": "66eb5cc55d65d8fe0401c5401c4a7501d46f831a",
      "revision": "HEAD"
    }
  }
}

AsmDefSample.asmdefの参照設定 (クリックで展開)

Art001.png

計測結果

条件別に計測結果を載せていきます。

● 公式パッケージをPackageManagerからインストールしてADFを参照

先ずは.csprojが生成されないパターンであるインストール取得の方から結果を載せていきます。

Sample.cs AsmDefSample.cs
6.81sec 7.41sec

参照の数が増えているので、コンパイル時間については①の検証結果よりも伸びています。

今回の検証では全パッケージの参照を持っているので、実際に使う上では「不必要なADFの参照を切る」なり「【Auto Referenced】の設定を適用する」なりすれば短く出来るかもしれません..。

● インストール済みの公式パッケージをローカルに配置してADFを参照

次に.csprojが生成されるパターンについてです。
①の検証と同じく、Library/PackageCacheにキャッシュされているパッケージをPackages以下に移動して「Embedded Package」として切り替えます。

計測結果は以下。

Sample.cs AsmDefSample.cs
10.45sec 11.19sec

割と伸びました。

上記にもある通り、不必要なADFの依存を切るなり【Auto Referenced】の設定を適用するなりすれば短く出来るかもしれませんが...とりあえずはADFの参照が多い上で.csprojもある場合には、その分コンパイル時間が伸びる」点については見えてきました。

② まとめ

こちらの検証では以下のポイントが見えてきました。

  • ADFの参照が多い上で.csprojもある場合には、その分コンパイル時間が伸びる

余談ですが、よく公式パッケージのソースを追う際には意図的に「Embedded Package」に切り替えて運用することがあったのですが...数が多いとコンパイル時間に影響が出てくるかと思われるので、無闇に切り替えずに必要なときだけ参照するようにしたほうが良い感出てきました..。
※意図的にEmbedded Packageに切り替える理由としては、一時的な変更やコード定義ジャンプと言った補完が効くようになるため。

未調査項目

この記事中ではまだ調査できていない項目が幾つかあります。
最後に思いついた範囲での項目を幾つかリストアップだけしておきます。

  • 「① 大量のコードを含んだADFを参照してコンパイル」 未調査項目
    • 検証用パッケージの【Auto Referenced】を切ったらコンパイル時間にどう影響が出てくるのか?
  • 共通の未調査項目
    • Assets以下にあるADFで分割しているアセンブリや、ローカル読み込みのパッケージを.csproj非生成状態に出来ないか?
    • Unity2019系統での調査
    • .csprojの有無による正確なコンパイルの挙動の把握
      • ※時間では無く、コンパイルステージの挙動的な意味で

参考/関連リンク


  1. GitHubの公開リポジトリとか 

  2. もう少し正確に言うとGlobal Cacheにもキャッシュされるっぽい 

  3. 【Auto Referenced】・・・ADFの設定の一つで、有効にするとデフォルトのアセンブリ(Assembly-CSharp.dll/Assembly-CSharp-Editor.dll)から参照できるようになる。 

  4. 記事中で表記しているコンパイル時間は全て「5回実行した際の相加平均(算術平均)」を記載。 

  5. Unity2018.4の段階なので一部パッケージは更新されずにPreviewのままなので注意。(e.g. Entitiesとか。2019.3だと最新版が取れる) 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1