Lua 技術ノート 2

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

このノートでは、組み込みシステムのような、あまりメモリを持たない環境向けに Lua をビルドする方法について説明します。これは 技術ノート 1 の Lua 4.0 用の更新版です。

「概要」ページ で明示的に述べられているように、私たちの Lua 実装の目標の1つは、低い組み込みコストです。これは、次の2つのことを意味します。まず、Lua をアプリケーションに組み込むのが容易であるべきです。次に、Lua 用の追加コードが大きすぎないようにする必要があります。

最初の要件は、Lua の C API の単純さによって満たされています。2番目の要件は、以下に示すように実証によって満たされています。

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

% size liblua.a
   text	   data	    bss	    dec	    hex	filename
   3328	      0	      0	   3328	    d00	lapi.o (ex liblua.a)
   4054	      0	      0	   4054	    fd6	lcode.o (ex liblua.a)
   3031	      0	      0	   3031	    bd7	ldebug.o (ex liblua.a)
   2372	      0	      0	   2372	    944	ldo.o (ex liblua.a)
    574	      0	      0	    574	    23e	lfunc.o (ex liblua.a)
   1874	      0	      0	   1874	    752	lgc.o (ex liblua.a)
   4909	      0	      0	   4909	   132d	llex.o (ex liblua.a)
    225	      0	      0	    225	     e1	lmem.o (ex liblua.a)
    734	      0	      0	    734	    2de	lobject.o (ex liblua.a)
   7634	      0	      0	   7634	   1dd2	lparser.o (ex liblua.a)
    598	      0	      0	    598	    256	lstate.o (ex liblua.a)
    953	      0	      0	    953	    3b9	lstring.o (ex liblua.a)
   1651	      0	      0	   1651	    673	ltable.o (ex liblua.a)
      0	      0	      0	      0	      0	ltests.o (ex liblua.a)
   1495	      0	      0	   1495	    5d7	ltm.o (ex liblua.a)
   2491	      0	      0	   2491	    9bb	lundump.o (ex liblua.a)
   5487	      0	      0	   5487	   156f	lvm.o (ex liblua.a)
    336	      0	      0	    336	    150	lzio.o (ex liblua.a)
% size liblualib.a
   text	   data	    bss	    dec	    hex	filename
   1437	      0	      0	   1437	    59d	lauxlib.o (ex liblualib.a)
   5619	      0	      0	   5619	   15f3	lbaselib.o (ex liblualib.a)
   1674	      0	      2	   1676	    68c	ldblib.o (ex liblualib.a)
   5288	      0	      0	   5288	   14a8	liolib.o (ex liblualib.a)
   2301	      0	      0	   2301	    8fd	lmathlib.o (ex liblualib.a)
   6209	      0	      0	   6209	   1841	lstrlib.o (ex liblualib.a)
このリストでは、text は実際にはコードのサイズ(バイト単位)です。Lua のコア(liblua.a)が 41746 バイト、Lua の標準ライブラリ(liblualib.a)が 22528 バイトであると結論付けられます。したがって、Lua のコード全体は 64274 バイト、つまり 63K 未満です。言い換えれば、アプリケーションにおける Lua の影響は、63K の追加コードであり、これは非常に小さいものです。(もちろん、Lua は実行時にメモリを使用しますが、その量はアプリケーションによって異なります。)

現在のマシンは多くのメガバイトのメインメモリを持っているため、63K はごくわずかに思えますが、電子レンジやロボットで Lua を使用しようとする人にとっては違いが生じる可能性があります。では、この 63K をさらに減らす方法を見てみましょう。(組み込みシステムで Lua を使用していなくても、以下の説明から何かを学ぶことができるかもしれません。)

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

text    %core   %whole   filename
   0     0%      0%      ltests.o
 225     1%      0%      lmem.o
 336     1%      1%      lzio.o
 574     1%      1%      lfunc.o
 598     1%      1%      lstate.o
 734     2%      1%      lobject.o
 953     2%      1%      lstring.o
1495     4%      2%      ltm.o
1651     4%      3%      ltable.o
1874     4%      3%      lgc.o
2372     6%      4%      ldo.o
2491     6%      4%      lundump.o
3031     7%      5%      ldebug.o
3328     8%      5%      lapi.o
4054    10%      6%      lcode.o
4909    12%      8%      llex.o
5487    13%      9%      lvm.o
7634    18%     12%      lparser.o
このリストは、解析モジュール、つまり字句解析器 llex.o、パーサー lparser.o、およびコードジェネレーター lcode.o がコアの 40% (全体では 26%) を占めていることを示しています。したがって、これらが削除の主な候補です。実行時に Lua コードをコンパイルする必要がないアプリケーションは、解析モジュールを必要としません。

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

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

void luaX_init(lua_State *L) {
  UNUSED(L);
}

Proto *luaY_parser(lua_State *L, ZIO *z) {
  UNUSED(z);
  lua_error(L,"parser not loaded");
  return NULL;
}
コードジェネレーターも削除するには、#include "lcode.h" を追加し、lcode.c から luaK_opproperties をこのコードにコピーする必要があります。

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

lua_dofile および dofile はプリコンパイルされたチャンクを自動的に検出しますが、埋め込みシステムにはファイルシステムさえも存在しないため、プリコンパイルされたチャンクをアプリケーションに静的にリンクして lua_dobuffer を使用するのが便利な方法の1つです (このためには lua/etc/bin2c.c が役立ちます)。(これは簡単な解決策ですが、アプリケーションのサイズが増加し、柔軟性に欠ける可能性があります。)

解析モジュールを削除すると、コアはわずか 25296 バイト、つまり 24K 強になります。これは、Lua のような強力な言語にとってはまさに微々たるものです!また、この削減は、言語機能を犠牲にしたり、ソースコードに触れたりすることなく行われたことに注意してください。リンカーからの少しの助けが必要なだけです。

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


最終更新日: 2001 年 8 月 20 日月曜日 14:35:00 EST