Lua 技術ノート 1

最小限の Lua 3.2 インストール

このノートでは、メモリがあまりない環境で Lua をビルドする方法について説明します。

ウェルカムページで明示的に述べられているように、Lua の実装の目標の一つは、低い組み込みコストです。これは、2つのことを意味します。1つ目は、Luaをアプリケーションに簡単に組み込むことができること、2つ目は、Luaの追加コードが大きすぎないことです。

最初の要件は、LuaのC APIの単純さによって満たされています。2番目の要件は、次のデモンストレーションによって満たされます。

以下は、Linux を実行している Intel マシンでコンパイルされた Lua 3.2 のいくつかの数値です (他のプラットフォームでの数値は異なるでしょうが、相対的にはほぼ同じでしょう)。

% size liblua.a liblualib.a
   text    data     bss     dec     hex filename
   4483     121       0    4604    11fc lapi.o (ex liblua.a)
   1037       0       0    1037     40d lauxlib.o (ex liblua.a)
    345       0       0     345     159 lbuffer.o (ex liblua.a)
   5193     272       0    5465    1559 lbuiltin.o (ex liblua.a)
   3183       0       0    3183     c6f ldo.o (ex liblua.a)
    381       0       0     381     17d lfunc.o (ex liblua.a)
   1363       0       0    1363     553 lgc.o (ex liblua.a)
   5429     108       0    5537    15a1 llex.o (ex liblua.a)
    222       0       0     222      de lmem.o (ex liblua.a)
    686     156       0     842     34a lobject.o (ex liblua.a)
   8560     244       0    8804    2264 lparser.o (ex liblua.a)
    446       4       0     450     1c2 lstate.o (ex liblua.a)
   1845      36       0    1881     759 lstring.o (ex liblua.a)
   1109       0       0    1109     455 ltable.o (ex liblua.a)
   1293     202       0    1495     5d7 ltm.o (ex liblua.a)
   2035       0       0    2035     7f3 lundump.o (ex liblua.a)
   4864       8       0    4872    1308 lvm.o (ex liblua.a)
    336       0       0     336     150 lzio.o (ex liblua.a)
     25       0       0      25      19 linit.o (ex liblualib.a)
   1489      56       0    1545     609 ldblib.o (ex liblualib.a)
   4236     264       0    4500    1194 liolib.o (ex liblualib.a)
   1651     184       0    1835     72b lmathlib.o (ex liblualib.a)
   5277      88       0    5365    14f5 lstrlib.o (ex liblualib.a)
このリストでは、text は実際にコードのサイズをバイト単位で表します。Lua コア (liblua.a) は 42810 バイト、Lua 標準ライブラリ (liblualib.a) は 12678 バイトであることがわかります。つまり、Lua コード全体で 55488 バイト、つまり 54K 未満です。言い換えれば、Lua がアプリケーションに与える影響は、54K の追加コードであり、これはかなり小さいものです。(もちろん、Lua は実行時にメモリを使用しますが、その量はアプリケーションによって異なります。)

最近のマシンはメインメモリを何メガバイトも搭載しているので、54K は非常に小さいように思えますが、電子レンジやロボットで Lua を使用しようとしている人にとっては違いが生じる可能性があります。それでは、この 54K をさらに減らす方法を見てみましょう。(組み込みシステムで Lua を使用していない場合でも、以下の説明から何かを学ぶことができるかもしれません。)

最初にすべきことは、不要な標準ライブラリをすべて削除することです。たとえば、ldblib.o はほとんどのアプリケーションでは不要でしょう。しかし、標準ライブラリを削除しても、それらはすでに小さいので、あまり進展はありません。そこで、コアの数値をもう一度見てみましょう。ただし、今度はサイズでソートします。

text     %core   %whole filename
 222     1%      0%     lmem.o
 336     1%      1%     lzio.o
 345     1%      1%     lbuffer.o
 381     1%      1%     lfunc.o
 446     1%      1%     lstate.o
 686     2%      1%     lobject.o
1037     2%      2%     lauxlib.o
1109     3%      2%     ltable.o
1293     3%      2%     ltm.o
1363     3%      2%     lgc.o
1845     4%      3%     lstring.o
2035     5%      4%     lundump.o
3183     7%      6%     ldo.o
4483    10%      8%     lapi.o
4864    11%      9%     lvm.o
5193    12%      9%     lbuiltin.o
5429    13%     10%     llex.o
8560    20%     15%     lparser.o
このリストから、字句解析器 (llex.o) とパーサー (lparser.o) がコアの 33% (全体では 25%) を占めていることがわかります。したがって、これらは削除の主な候補です。実行時に Lua コードをコンパイルする必要がないアプリケーションには、字句解析器とパーサーは必要ありません。

コードは、これらの 2 つのモジュールを簡単に削除できるように設計されています。パーサーを呼び出すモジュールは 1 つだけで (ldo.o)、パブリック関数は 1 つだけ (luaY_parser) です。字句解析器を呼び出すモジュールは、lua_open で使用される初期化関数 (luaX_init) を除き、パーサーだけです。したがって、字句解析器とパーサーを削除するには、以下のコードをアプリケーションに追加するだけで済みます(デフォルトで無効になっている lua/src/luac/stubs.c から抽出できます)。

#include "llex.h"
#include "lparser.h"

void luaX_init(void){}

TProtoFunc* luaY_parser(ZIO *z) {
 lua_error("parser not loaded");
 return NULL;
}

このコードを含むアプリケーションは、llex.o または lparser.o にリンクせず、Lua ソースコードをロードしようとするとエラーが発生します。しかし、それでは、アプリケーションはどのようにして Lua コードをロードするのでしょうか?答えは、ソースコードの代わりにプリコンパイルされたチャンクをロードすることです。プリコンパイルされたチャンクは luac で作成されます。luac は字句解析器とパーサーを *含んでいますが、外部アプリケーションです。プリコンパイルされたチャンクをロードするモジュールは lundump.o で、これは十分に小さいです。

lua_dofiledofile はプリコンパイルされたチャンクを自動的に検出しますが、便利な方法の 1 つは、プリコンパイルされたチャンクをアプリケーションに静的にリンクして lua_dobuffer を使用することです (このためには lua/etc/bin2c.c が役立ちます)。組み込みシステムにはファイルシステムすらないからです。(これは高速なソリューションですが、アプリケーションのサイズが増加し、柔軟性に欠ける可能性があります。)

字句解析器とパーサーを削除すると、コアはわずか 28821 バイト、つまり 28K 強になります。Lua のような強力な言語にしては、これは非常に小さいです!この削減はソースコードに触れることなく行われたことにも注意してください。リンカーからの少しの助けが必要なだけです。

削除のもう 1 つの候補は、組み込み関数を含む lbuiltin.o です。標準ライブラリと同様に、スリムな Lua を必要とするアプリケーションは、本当に必要な組み込み関数を検討する必要があります。lbuiltin.c を調べて、不要な関数を削除するのは簡単です。それらはコメント内の対応する {...} でマークされたブロックに分割されているため、簡単に識別できます。組み込み関数がまったく必要ない場合は、最も簡単な方法は以下を追加することです。

#include "lbuiltin.h"
void luaB_predefine(void){}
上記のスタブコードに追加し、lbuiltin.o をロードしないようにリンカーに頼ることです。

このノートでは、Lua ライブラリによってアプリケーションに追加されるコードの量を減らすことに焦点を当ててきました。これを必要とするアプリケーションは、Lua の数値に浮動小数点数ではなく整数を使用することも好むでしょう。(電子レンジに浮動小数点数が必要でしょうか?)これは lua/config で説明されているように簡単に行うことができますが、詳細は別の LTN で議論されるでしょう。


最終更新日: 2001 年 2 月 11 日 (日) 18:45:01 EDT lhf による。