diff --git a/benchmarks/closures.exs b/benchmarks/closures.exs index b78a209..f282707 100644 --- a/benchmarks/closures.exs +++ b/benchmarks/closures.exs @@ -9,10 +9,13 @@ # - Luerl (Erlang-based Lua 5.3 implementation) # - C Lua 5.4 via luaport (port-based; results include IPC overhead) # -# NOTE: luaport requires C Lua development headers. On macOS with Homebrew: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix deps.compile luaport -# Then run: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix run benchmarks/closures.exs +# NOTE: luaport requires C Lua 5.4 development headers and a small in-tree +# patch (its 1.6.3 release defaults to LuaJIT and uses LUA_GLOBALSINDEX which +# was removed in Lua 5.2). On macOS: +# brew install lua@5.4 +# ./benchmarks/setup_luaport.sh # idempotent; patches + builds +# MIX_ENV=benchmark mix run benchmarks/closures.exs +# If luaport fails to start, the benchmark prints a notice and skips it. Application.ensure_all_started(:luerl) diff --git a/benchmarks/fibonacci.exs b/benchmarks/fibonacci.exs index 2de4a3c..6ba154f 100644 --- a/benchmarks/fibonacci.exs +++ b/benchmarks/fibonacci.exs @@ -5,10 +5,13 @@ # - Luerl (Erlang-based Lua 5.3 implementation) # - C Lua 5.4 via luaport (port-based; results include IPC overhead) # -# NOTE: luaport requires C Lua development headers. On macOS with Homebrew: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix deps.compile luaport -# Then run: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix run benchmarks/fibonacci.exs +# NOTE: luaport requires C Lua 5.4 development headers and a small in-tree +# patch (its 1.6.3 release defaults to LuaJIT and uses LUA_GLOBALSINDEX which +# was removed in Lua 5.2). On macOS: +# brew install lua@5.4 +# ./benchmarks/setup_luaport.sh # idempotent; patches + builds +# MIX_ENV=benchmark mix run benchmarks/fibonacci.exs +# If luaport fails to start, the benchmark prints a notice and skips it. Application.ensure_all_started(:luerl) diff --git a/benchmarks/oop.exs b/benchmarks/oop.exs index 0158c11..25ac5a3 100644 --- a/benchmarks/oop.exs +++ b/benchmarks/oop.exs @@ -15,10 +15,13 @@ # - Luerl (Erlang-based Lua 5.3 implementation) # - C Lua 5.4 via luaport (port-based; results include IPC overhead) # -# NOTE: luaport requires C Lua development headers. On macOS with Homebrew: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix deps.compile luaport -# Then run: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix run benchmarks/oop.exs +# NOTE: luaport requires C Lua 5.4 development headers and a small in-tree +# patch (its 1.6.3 release defaults to LuaJIT and uses LUA_GLOBALSINDEX which +# was removed in Lua 5.2). On macOS: +# brew install lua@5.4 +# ./benchmarks/setup_luaport.sh # idempotent; patches + builds +# MIX_ENV=benchmark mix run benchmarks/oop.exs +# If luaport fails to start, the benchmark prints a notice and skips it. Application.ensure_all_started(:luerl) diff --git a/benchmarks/setup_luaport.sh b/benchmarks/setup_luaport.sh new file mode 100755 index 0000000..925a811 --- /dev/null +++ b/benchmarks/setup_luaport.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# +# Idempotently patch and build the optional `luaport` benchmark dep against +# Homebrew's lua@5.4 on macOS. +# +# luaport 1.6.3 ships a Makefile that hardcodes LuaJIT, and its C source uses +# `LUA_GLOBALSINDEX` which was removed in Lua 5.2. Neither is overridable via +# env vars without editing files in deps/, so this script applies two small +# in-place patches after `mix deps.get`: +# +# 1. deps/luaport/Makefile — pkg-config against lua-5.4, drop LuaJIT flags +# 2. deps/luaport/c_src/luaport.c — replace LUA_GLOBALSINDEX with the +# globals table from the registry +# +# Run this after every `mix deps.get` or `mix deps.clean luaport`. Re-running +# on an already-patched tree is a no-op. +# +# Requires: brew install lua@5.4 + +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +MAKEFILE="$ROOT/deps/luaport/Makefile" +SRC="$ROOT/deps/luaport/c_src/luaport.c" + +if [ ! -f "$MAKEFILE" ] || [ ! -f "$SRC" ]; then + echo "luaport sources not found under deps/luaport. Run 'MIX_ENV=benchmark mix deps.get' first." >&2 + exit 1 +fi + +LUA_PREFIX="$(brew --prefix lua@5.4 2>/dev/null || true)" +if [ -z "$LUA_PREFIX" ] || [ ! -d "$LUA_PREFIX/lib/pkgconfig" ]; then + echo "Homebrew lua@5.4 not found. Install it with: brew install lua@5.4" >&2 + exit 1 +fi + +PKG_CONFIG_PATH="$LUA_PREFIX/lib/pkgconfig:${PKG_CONFIG_PATH:-}" +export PKG_CONFIG_PATH + +# Patch 1: Makefile — switch from luajit to lua-5.4, drop LuaJIT-only defines. +if grep -q "DLUAP_JIT" "$MAKEFILE"; then + echo "Patching $MAKEFILE for lua-5.4..." + # Build a fresh Makefile via sed; idempotent because the next run finds no DLUAP_JIT. + sed -i.bak \ + -e 's|^LUA_CFLAGS ?= -DLUAP_JIT \$(shell pkg-config --cflags luajit)|LUA_CFLAGS ?= $(shell pkg-config --cflags lua-5.4)|' \ + -e 's|^LUA_LDFLAGS ?= \$(shell pkg-config --libs luajit)|LUA_LDFLAGS ?= $(shell pkg-config --libs lua-5.4)|' \ + -e '/^DEFINES += -DLUAP_BIT/d' \ + -e '/^DEFINES += -DLUAP_FFI/d' \ + "$MAKEFILE" + rm -f "$MAKEFILE.bak" +else + echo "$MAKEFILE already patched." +fi + +# Patch 2: luaport.c — replace LUA_GLOBALSINDEX (removed in Lua 5.2). +# Match the actual use site, not the explanatory comment left by the patch. +if grep -q "lua_rawset(L, LUA_GLOBALSINDEX)" "$SRC"; then + echo "Patching $SRC for Lua >= 5.2 globals handling..." + python3 - "$SRC" <<'PY' +import sys, pathlib + +path = pathlib.Path(sys.argv[1]) +src = path.read_text() + +old = """ for (int i = 0; i < arity; i++) + { + if (e2l_any(buf, index, L) || e2l_any(buf, index, L)) + { + exit(EXIT_BAD_ANY); + } + + lua_rawset(L, LUA_GLOBALSINDEX); + } +""" + +new = """ /* Patched for tv-labs/lua benchmarks: LUA_GLOBALSINDEX was removed in + * Lua 5.2. Push the globals table from the registry, then rawset against + * it for each key/value pair. */ + lua_pushglobaltable(L); + + for (int i = 0; i < arity; i++) + { + if (e2l_any(buf, index, L) || e2l_any(buf, index, L)) + { + exit(EXIT_BAD_ANY); + } + + lua_rawset(L, -3); + } + + lua_pop(L, 1); +""" + +if old not in src: + sys.stderr.write("Expected LUA_GLOBALSINDEX block not found; aborting.\n") + sys.exit(1) + +path.write_text(src.replace(old, new, 1)) +PY +else + echo "$SRC already patched." +fi + +echo "Compiling luaport against $LUA_PREFIX..." +cd "$ROOT" +MIX_ENV=benchmark mix deps.compile luaport --force + +echo +echo "luaport built successfully. Run benchmarks with:" +echo " MIX_ENV=benchmark mix run benchmarks/fibonacci.exs" diff --git a/benchmarks/string_ops.exs b/benchmarks/string_ops.exs index 716afb4..cbdc3aa 100644 --- a/benchmarks/string_ops.exs +++ b/benchmarks/string_ops.exs @@ -9,10 +9,13 @@ # - Luerl (Erlang-based Lua 5.3 implementation) # - C Lua 5.4 via luaport (port-based; results include IPC overhead) # -# NOTE: luaport requires C Lua development headers. On macOS with Homebrew: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix deps.compile luaport -# Then run: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix run benchmarks/string_ops.exs +# NOTE: luaport requires C Lua 5.4 development headers and a small in-tree +# patch (its 1.6.3 release defaults to LuaJIT and uses LUA_GLOBALSINDEX which +# was removed in Lua 5.2). On macOS: +# brew install lua@5.4 +# ./benchmarks/setup_luaport.sh # idempotent; patches + builds +# MIX_ENV=benchmark mix run benchmarks/string_ops.exs +# If luaport fails to start, the benchmark prints a notice and skips it. Application.ensure_all_started(:luerl) diff --git a/benchmarks/table_ops.exs b/benchmarks/table_ops.exs index 671d8e8..dd93659 100644 --- a/benchmarks/table_ops.exs +++ b/benchmarks/table_ops.exs @@ -11,10 +11,13 @@ # - Luerl (Erlang-based Lua 5.3 implementation) # - C Lua 5.4 via luaport (port-based; results include IPC overhead) # -# NOTE: luaport requires C Lua development headers. On macOS with Homebrew: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix deps.compile luaport -# Then run: -# PKG_CONFIG_PATH=/opt/homebrew/lib/pkgconfig mix run benchmarks/table_ops.exs +# NOTE: luaport requires C Lua 5.4 development headers and a small in-tree +# patch (its 1.6.3 release defaults to LuaJIT and uses LUA_GLOBALSINDEX which +# was removed in Lua 5.2). On macOS: +# brew install lua@5.4 +# ./benchmarks/setup_luaport.sh # idempotent; patches + builds +# MIX_ENV=benchmark mix run benchmarks/table_ops.exs +# If luaport fails to start, the benchmark prints a notice and skips it. Application.ensure_all_started(:luerl)