Lua 技術備忘錄 2

極簡 Lua 4.0 安裝

此備忘錄說明如何為記憶體不足的環境(例如嵌入式系統)建置 Lua。這是針對 Lua 4.0 更新的 技術備忘錄 1 版本。

正如 「關於」頁面 中明確說明的,我們的 Lua 實作目標之一是低嵌入成本。這表示兩件事:首先,Lua 應易於嵌入應用程式中;其次,Lua 的額外程式碼不應過大。

第一個需求由 Lua 的 C API 簡單性達成。第二個需求則由以下示範達成。

以下列出幾個 Lua 4.0 的數字,這些數字是在執行 Linux 的 Intel 電腦中使用預設選項編譯的(其他平台的數字會不同,但相對而言可能大致相同)

% 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 程式碼的應用程式不需要解析模組。

我們設計程式碼,以便輕鬆移除這三個模組。只有一個模組(ldo.o)呼叫解析器,而解析器只有一個公開函式(luaY_parser)。除了 lua_open 中使用的初始化函式(luaX_init)之外,呼叫詞法分析器的唯一模組是解析器。除了 ldebug.o 使用 lcode.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" 並將 luaK_oppropertieslcode.c 複製到此程式碼中。

包含上述程式碼的應用程式將不會連結解析模組,而嘗試載入 Lua 原始碼會產生錯誤。但是,您可能會問,應用程式如何載入 Lua 程式碼?答案是:載入預編譯的區塊,而不是原始碼。預編譯的區塊是用 luac 建立的,它包含解析模組,但它是一個外部應用程式。載入預編譯區塊的模組是 lundump.o,它夠小。

雖然 lua_dofiledofile 會自動偵測預編譯的區塊,但一個方便的方法是將預編譯的區塊與您的應用程式靜態連結,使用 lua_dobuffer(您會發現 lua/etc/bin2c.c 對此很有用),因為嵌入式系統甚至沒有檔案系統。(這是一個快速的解決方案,但會增加應用程式的規模,而且對您來說可能太過死板。)

移除解析模組後,我們只剩下一個核心,只有 25296 位元組,比 24K 稍大一點。對於像 Lua 這樣強大的語言來說,這的確很小!另外請注意,這個縮減是在不犧牲任何語言功能和不修改原始碼的情況下完成的;我們只需要連結器的協助。

此說明重點在於減少 Lua 函式庫新增到應用程式的程式碼量。需要這樣做的應用程式可能也會偏好使用整數,而不是浮點數,作為 Lua 中的數字。(微波爐需要浮點數嗎?)這應該很容易做到,如 lua/config 中所述,但詳細資訊可能會在另一份 LTN 中討論。


最後更新時間:2001 年 8 月 20 日星期一下午 2:35:00 美東時間