実行時間とメモリの上限
終わらないループの打ち切りと、1アプリが使えるメモリ
実行時間の上限(命令数)
Luaのコールバック(loop(dt) やイベント)の中に終わらないループがあると、OS全体が止まってしまいます。そうならないよう、1回の呼び出しで実行できるLuaの命令数に上限(200万命令)があります。
while true do end -- 上限に達するとエラーとして打ち切られる
- 数えるのは、トップレベルの実行・
setup()・loop()・各イベント・HTTPやタイマーのコールバックなど、OSから呼ばれる1回ごとです。 - 上限に達するとエラーダイアログが出ます。
loop()で起きたときは、それ以降loop()は呼ばれなくなります。 - 時間ではなく命令数で数えます。
pico.sd_read()のようなOSの関数の中で待っている時間は数えません。 - 重い計算を1フレームでやりきろうとすると引っかかることがあります。何フレームかに分けてください。
pcall では止められない
上限に達した呼び出しは、pcall / xpcall / コルーチンで捕まえても、最後まで打ち切られます。次にOSから呼ばれたとき(次の loop() や次のイベント)にまた動けるようになります。
それでも止まらないもの
とても重い string.find のパターンのように、Luaの命令ではなくOSの関数の中で時間がかかるものは数えられません。設定アプリの「固まったら再起動する」を入れておくと、固まったときに再起動します。
メモリの上限
1つのアプリのLuaが使えるメモリは 200KB までです。スクリプトのコード、テーブル、文字列など、Luaが確保するもの全部が入ります。
- 超えると、Luaの「メモリ不足」(
not enough memory)のエラーになります。OSは落ちません。 - ウィジェットと画像(
pico.image_load)はこの200KBとは別に数えます(画像は8枚・96KiBまで)。 - 今の使用量は
pico.memory_info()で分かります。 - 大きなJSONを丸ごと
pico.json_decodeすると一気に使います。数個の値だけならpico.json_pickを使ってください。 - コードが大きいアプリは、
app.cfgのstrip_debug=trueでモジュールの大きさを減らせます(モジュール)。
つまずいたときに疑う場所
| 症状 | 疑うところ |
|---|---|
エラーダイアログが出て loop() が止まった | 命令数の上限、またはスクリプトのバグ(ダイアログのスタックトレースを見る) |
pico.sd_read() が nil | ファイルが16KiBより大きい、ファイルが無い、権限(アプリのフォルダの外) |
pico.image_load() が nil | 枚数(8枚)・合計(96KiB)の上限、形式(プログレッシブJPEG等)、権限 |
pico.http_request() が false | permission_network が無い、順番待ちがいっぱい、URLが不正、送る本文が16KiBより大きい |
not enough memory | Luaのメモリ(200KB)を使い切った |
上限の一覧は 上限 にあります。