クライアントエンジニアの加賀です。
昔は何も知らずに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を使うことができそうです。