クライアントエンジニアの加賀です。
昔は何も知らずにLINQのメソッドを使うと、iOS実機で動かした時に以下のようなエラーが出ることがありました。
System.ExecutionEngineException: Attempting to JIT compile method
だいぶ前からですが、すこしずつ改善がされてきているので、現在の状況を一度纏めてみました。
※メソッドの実行結果が正しいかは、今回確認していません。
あくまで、実行時にエラーが起きるかどうかを確認しています。
今回確認した環境は以下の通りです。
- 2016/11/22
- Unity 5.4.2f2
- Mac OS X 10.11.6
- iOS 9.2.1
検証結果を記載しますが、Result値の意味は以下のとおりです。
Result値 | 意味 |
---|---|
o | エラーにならない |
x | エラーになる |
Average
エラーの条件
- 引数に変換関数を渡すオーバーロード
-
TSource
が値型 -
TSource
が参照型(条件によってはエラーにならない場合もあり)
現在の状況
Scripting Backend | Result |
---|---|
Mono2x | o |
IL2CPP | o |
Max、Min、Sum
エラーの条件
- 引数に変換関数を渡すオーバーロード
-
TSource
が参照型
現在の状況
Scripting Backend | Method | Result |
---|---|---|
Mono2x | Max Min Sum |
x x o |
IL2CPP | Max Min Sum |
o o o |
FirstOrDefault、Last、LastOrDefault、Single、SingleOrDefault
似たメソッドとしてFirst
がありますが、こちらは以前から問題ありませんでした。
エラーの条件
- 引数に何も渡さないオーバーロード
-
TSource
が値型
現在の状況
Scripting Backend | Method | Result |
---|---|---|
Mono2x | FirstOrDefault Last LastOrDefault Single SingleOrDefault |
o o o o o |
IL2CPP | FirstOrDefault Last LastOrDefault Single SingleOrDefault |
o o o o o |
ToDictionary
エラーの条件
- 引数に
Func<TSource, TElement> elementSelector
を渡さないオーバーロード -
TSource
が値型
現在の状況
Scripting Backend | Result |
---|---|
Mono2x | x |
IL2CPP | o |
ToLookup
エラーの条件
- 引数に
Func<TSource, TElement> elementSelector
を渡さないオーバーロード -
TSource
が値型
現在の状況
Scripting Backend | Result |
---|---|
Mono2x | x |
IL2CPP | o |
または
- 引数に
Func<TSource, TKey> keySelector
、IEqualityComparer<TKey> comparer
の2つを渡すオーバーロード -
TSource
が参照型 -
TKey
が値型
現在の状況
Scripting Backend | Result |
---|---|
Mono2x | x |
IL2CPP | o |
Join、GroupJoin
エラーの条件
-
Join
、GroupJoin
のすべてのオーバーロード -
TInner
(相手のストリーム型)が値型
現在の状況
Scripting Backend | Method | Result |
---|---|---|
Mono2x | Join GroupJoin |
x x |
IL2CPP | Join GroupJoin |
o o |
または
-
Join
、GroupJoin
のすべてのオーバーロード -
TInner
(相手のストリーム型)が参照型 -
TKey
が値型
現在の状況
Scripting Backend | Method | Result |
---|---|---|
Mono2x | Join GroupJoin |
x x |
IL2CPP | Join GroupJoin |
o o |
OrderBy、OrderByDescending
エラーの条件
-
TSource
が値型
現在の状況
Scripting Backend | Method | Result |
---|---|---|
Mono2x | OrderBy OrderByDescending |
x x |
IL2CPP | OrderBy OrderByDescending |
o o |
ThenBy、ThenByDescending
エラーの条件
-
Func<TSource, TKey> keySelecter
のTKey
が値型
現在の状況
Scripting Backend | Method | Result |
---|---|---|
Mono2x | ThenBy ThenByDescending |
x x |
IL2CPP | ThenBy ThenByDescending |
o o |
enum配列のToArray
現在の状況
Scripting Backend | Result |
---|---|
Mono2x | x |
IL2CPP | o |
まとめ
なんと、IL2CPPで出力した場合は、記事内の全てのLINQメソッドでエラーが起きませんでした!(全オーバーロードは流石に確認できていません)
また、Mono2xでも一部のLINQメソッドで改善が見られるようです。
iOSで64bit対応が必須になり、IL2CPPが使用され始めました。
その時点で、LINQはAOTエラーと決別出来ていたようです。
これで少しは安心してLINQを使うことができそうです。