ILP32
繁體中文

效能數據

同樣的編法下比較 ILP32 和 LP64:省下的是記憶體,代價是幾個百分點的速度。

OpenWrt One 實機

OpenWrt One(MT7981B,雙核 Cortex-A53,最高 1.3 GHz,1 GB)。兩個 image 來自同一份原始碼, 套件(LuCI、python3-light、dnsmasq)和 kernel 設定都相同,也都用 GCC 14.3 編譯,只差使用者空間的 ABI (兩個 kernel 是用同一份原始碼、分別建立的 toolchain 編出來的)。負載:200 條防火牆規則、50 筆固定 DHCP、 15 萬筆網域的 dnsmasq 封鎖清單、LuCI 請求,以及一個持有 10 萬筆 dict 的 Python 程式。每種開機 3 次,取中位數。

記憶體LP64ILP32差異
使用者空間記憶體(所有程式的 PSS 合計)38.3 MB28.9 MB-24.6%
匿名記憶體30.3 MB20.9 MB-31%
可用記憶體(MemAvailable)863.6 MB872.2 MB+8.6 MB
python3(10 萬筆 dict)17.9 MB12.4 MB-31%
dnsmasq(15 萬筆封鎖清單)12.0 MB8.8 MB-26%
hostapd / wpa_supplicant-11% / -9%
kernel(Slab)28.0 MB27.9 MB-0.6%
時間(秒,越低越好;用 GCC 編譯)LP64ILP32差異
重新載入 200 條防火牆規則2.582.84+10%
dnsmasq 載入 15 萬筆2.963.03+2%
LuCI 登入頁 20 次請求1.731.81+5%
python3 建立 10 萬筆 dict0.380.42+11%

兩個 image 的 kernel 都是 LP64,所以 kernel 記憶體不變;省下的是程式本身的記憶體,資料越多省越多。 閒置的路由器只省幾百 KB。多花的時間主要來自在 64 位元程式碼裡處理 32 位元指標,而在為 64 位元 long 寫了快速路徑的程式碼裡會慢更多。把最常用的套件(ucode、lucihttp、json-c)改用 clang 編譯後, 重新載入防火牆只要 2.63 秒(+2%),LuCI 請求 1.76 秒(+2%),記憶體不變(同一台 OpenWrt One,各開機 3 次取中位數)。只有 ILP32 映像的這些套件改用 clang;LP64 映像只用 GCC 編譯, LP64 用 clang 編譯的版本還沒量過,所以部分改善可能來自 clang 本身。 同樣的測試在 QEMU(armsr,256 MB)上的結果:使用者空間記憶體 -26.0%,可用記憶體 +9.6 MB。

Cortex-A35 與 Cortex-A53 板子上的 CPython

LP64 和 ILP32 用同樣的 CPython 編譯方式:ILP32 少用約 30% 的記憶體, 在 Cortex-A53 上慢 2.6%,在 Cortex-A35 上慢 5.7%。 編譯方式、參數和各項目的數據:llvm-ilp32 docs/benchmarks.md。

我們怎麼比較