Assembly Definition Filesを導入する/している方向けの小ネタです。
※Assembly Definition Files
だと長いので記事中では**ADF
**と表記
ADF
を導入して開発を行っていると、ADF
の参照方法によって体感的にコンパイル時間の違いを感じることが有りました。 (私だけ..?)
参照方法に紐づくコンパイル時間については以下のように分類できそうな印象があります。
-
A: (Bと比べるとコンパイル時間が長い?)
- →
Assets
以下にあるスクリプトをADF
で分割して参照する時 - → ローカルにあるパッケージを登録してパッケージ内の
ADF
を参照する時
- →
-
B: (Aと比べるとコンパイル時間が短い?)
- → 公式パッケージをインストールしてパッケージ内の
ADF
を参照する時 - → 自作パッケージをリポジトリ1から直接取得してパッケージ内の
ADF
を参照する時
- → 公式パッケージをインストールしてパッケージ内の
そしてこれらの参照方法の挙動を見た感じだと、内部的に.csproj
が生成されるかどうかの条件にもなっているように思われました。簡潔にまとめると以下のように分類できそうです。
- Project以下及びローカルパッケージにある
ADF
を参照- →
.csproj
が生成される
- →
- 公式レジストリ/リポジトリから取得してパッケージ内の
ADF
を参照- →
.csproj
は生成されない -
取得したパッケージそのものは
Library/PackageCache
以下にキャッシュされる 2
- →
この挙動の違いがコンパイル時間に影響を及ぼしている?と予想して簡単に調査の方を行ってみました。
まだ分からない点や未調査項目がチラホラと残っており...ほぼ個人メモの公開みたいな内容にはなりますが、一先ずは現状見えている範囲についてだけ纏めていきます。
(間違いとかあればコメントなりTwitterなりで直接教えて頂けると幸いです )
※注意点
※この記事中ではADF
に関する基本的な所は解説しません。
基本的な情報については以下の記事がおすすめです。
- 【Unity】「AssemblyDefinitionを分けるとコンパイルが高速になる」ってホント?検証してみた!
- Unity Assembly Definition 完全に理解した
- Unity2017.3のAssembly Definition Filesを適切に設定してコンパイルにかかる時間を削減する
- How I Cut Unity Compile Times by 75%
検証環境
- 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
に切り替えるなりしたほうが良いかもしれない
- → 公式パッケージを変更したり追うときにだけ
- Unity公式のレジストリやリポジトリ1から取得すると
調査内容
調査にあたっては以下のテストを行ってコンパイル時間を計測してみました。
これらが.csproj
の有無でコンパイル時間にどう影響を及ぼしていくのかを見ていきます。
-
① 大量のコードを含んだ
ADF
を参照してコンパイル- → コード量が多いアセンブリを参照している時のコンパイル時間の影響について調査
-
② PackageManagerから公式パッケージを30個近くインストールした上でコンパイル
- → 数多くのアセンブリを参照している状態でのコンパイル時間の影響について調査
計測方法について
コンパイル時間の計測方法としては、以下の2つのスクリプトに変更を掛けてそれぞれのコンパイル時間を計測していきます。
(コードに1行変更を加えてコンパイルを実行)
- ①
Sample.cs
に変更を加えて**Assembly-CSharp.dll
とAssembly-CSharp-Editor.dll
**のコンパイル時間を計測 - ②
AsmDefSample.cs
に変更を加えて**AsmDefSample.dll
**及びAssembly-CSharp.dll
とAssembly-CSharp-Editor.dll
のコンパイル時間を計測- ※
AsmDefSample.asmdef
の**【Auto Referenced】3**は有効化- → 故に
Assembly-CSharp.dll
とAssembly-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
の計測結果を記載)
- CompilationPipeline.assemblyCompilationStarted
- CompilationPipeline.assemblyCompilationFinished
- AssemblyReloadEvents.beforeAssemblyReload
- AssemblyReloadEvents.afterAssemblyReload
更に補足しておくと、EditorApplication.isCompiling
は2019の最新辺り?から挙動が怪しいっぽいので、こちらも踏まえて上記のAPIを利用したほうが良いかもしれません。
① 大量のコードを含んだADF
を参照してコンパイル
**「大量のコードを含んでいるADF
を参照していたらどの程度の影響が出るのか?」**について調べてみました。
→ 懸念事項として「大量のコードを含んでいるADF
が.csproj
の有無によってコンパイル時間が大きく変わってくる」とかあると怖いので..。
調査にあたっては以下の計測用パッケージを用意したので、こちらをプロジェクトに導入して計測を行います。
-
mao-test-h/large-code-sample
- ※
LargeCodeSample.asmdef
は【Auto Referenced】を有効化 - ※計測対象の
AsmDefSample.asmdef
はLargeCodeSample.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
が生成されない状態となります。
{
"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
**`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"
}
}
}
計測結果
条件別に計測結果を載せていきます。
● 公式パッケージを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
の有無による正確なコンパイルの挙動の把握- ※時間では無く、コンパイルステージの挙動的な意味で
-
参考/関連リンク
- Assembly Definitions
- 【Unity】「AssemblyDefinitionを分けるとコンパイルが高速になる」ってホント?検証してみた!
- Unity Assembly Definition 完全に理解した
- Unity2017.3のAssembly Definition Filesを適切に設定してコンパイルにかかる時間を削減する
- How I Cut Unity Compile Times by 75%
- Unityでコンパイル時間を可視化する
-
もう少し正確に言うとGlobal Cacheにもキャッシュされるっぽい ↩
-
【Auto Referenced】・・・
ADF
の設定の一つで、有効にするとデフォルトのアセンブリ(Assembly-CSharp.dll
/Assembly-CSharp-Editor.dll
)から参照できるようになる。 ↩ -
記事中で表記しているコンパイル時間は全て「5回実行した際の相加平均(算術平均)」を記載。 ↩
-
Unity2018.4の段階なので一部パッケージは更新されずにPreviewのままなので注意。(e.g. Entitiesとか。2019.3だと最新版が取れる) ↩