Skip to content

Consider migrating from sol2 to LuaBridge3 for better performance (requires significant architecture refactor) #52

Description

@e-gleba

Why

sol2 is deeply woven into the Lua binding layer of this project. It works, but it carries real overhead — compile times are brutal, the header is massive, and runtime performance leaves headroom on the table.

LuaBridge3 is a serious alternative worth evaluating. It's header-only, dependency-free, MIT-licensed, and actively maintained. Per official docs:

"LuaBridge3 has been heavily optimized and now competes directly with sol2 — one of the fastest C++/Lua binding libraries — across most workloads. In fact, LuaBridge3 outperforms sol2 in certain scenarios such as member function calls from Lua and global table writes, while remaining more compact and faster to compile."

Benchmarks

Alterise/lua-benchmarks — sol2 vs LuaBridge3 head-to-head

Operation sol2 LuaBridge3 Winner
Increment (Lua→C++) 225 ms 85 ms LuaBridge3 (2.6× faster)
String Argument 188 ms 188 ms Tie
String View Argument 149 ms 149 ms Tie
String Iterator 255 ms 256 ms Tie

The Lua→C++ call path — the hot path in any modding/scripting integration — is where LuaBridge3 pulls ahead significantly.

Official LuaBridge3 benchmarks (in-repo, commit 0ca8ef4)

LuaBridge3 ships its own benchmark suite (benchmark_luabridge3.cpp vs benchmark_sol3.cpp) covering:

  • Table read/write access
  • Member function calls from Lua
  • Global table writes
  • Chained table access (sol2 still holds an edge here)

Per the LuaBridge3 Manual, the performance gap is "negligible for most use cases" — but compile times and binary size favor LuaBridge3 meaningfully.

StackOverflow discussion — real-world observations

With -O3: sol2 Increment drops to 32ms / C++ calls to 56ms. Without aggressive optimization, sol2 is significantly slower. LuaBridge3 performs well even at -O2.

What LuaBridge3 Brings

Feature Detail
License MIT — no usage restrictions
Integration Header-only, single #include, zero dependencies
Lua compatibility PUC-Lua 5.1–5.5, LuaJIT 2.1, Luau, Ravi
C++ standard C++17 required, C++20/23 features supported
C++20 coroutines Native coroutine integrationCppCoroutine<R>
Type support Containers, smart pointers, std::optional, std::variant, std::string_view
Compile times Scales linearly with binding surface — sol2 is known for brutal compile times
Package managers Available on vcpkg
Class binding Multiple inheritance, property/function proxies, constructor factories, extensible classes

The Problem

sol2 is not a drop-in swap target. The binding layer relies on sol2's API surface throughout — type mapping, stack manipulation, state management, error handling, lifetime semantics. A naive replacement would produce a tangled mess.

This needs a proper architecture refactor:

  • Abstract the binding layer behind a thin internal interface so the underlying library becomes an implementation detail
  • Define clear ownership semantics — sol2's sol::object / sol::table / sol::reference patterns differ from LuaBridge3's luabridge::LuaRef
  • Re-evaluate error handling — sol2 uses exceptions heavily; LuaBridge3 supports both exception and noexcept modes
  • Audit compile-time cost — sol2's template metaprogramming is heavy; LuaBridge3 is leaner but the migration itself must not regress build times

Prior Art

Worth studying how other RE/modding projects structure their Lua integrations:

Proposed Approach

  1. Profile current sol2 integration — identify hot paths, measure compile times, catalog all sol2 API surface in use
  2. Build an abstraction layerILuaBridge interface wrapping calls, table access, type conversion, error handling
  3. Implement LuaBridge3 backend behind that interface — compare perf, compile time, binary size
  4. Gradual migration — module-by-module, keeping sol2 as fallback until parity is verified
  5. Benchmark parity — run the same workload suite against both backends before cutting over

Acceptance Criteria

  • Binding abstraction layer designed and documented
  • LuaBridge3 backend implemented and passing all existing Lua script tests
  • Compile time comparison documented (sol2 vs LuaBridge3 vs abstraction overhead)
  • Runtime benchmark parity on hot paths (Increment, function calls, table access)
  • No regression in existing modding/scripting functionality

Labels

enhancement (applied) — requesting creation of: lua, refactoring, performance

Milestone: Architecture Improvements (if/when created)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions