Lua vs JavaScript (V8): Benchmark Results
I ran a small benchmark on Ubuntu to compare the performance of Lua and JavaScript running on V8 using identical workloads.
Important: This benchmark was performed outside FiveM, directly against a Lua runtime and Node.js/V8. Therefore, these results show the runtime-level performance difference, but they are not a direct FiveM Lua vs JavaScript benchmark.
1. Arithmetic Benchmark
Both runtimes executed exactly the same algorithm:
N = 100,000,000
x = 1
for i = 1 .. N:
x = (x * 1.000001 + i) % 1000003
Results
| Runtime | Execution Time | Iterations/sec |
|---|---|---|
| Lua | ~3.19 s | ~31.3 million/s |
| JavaScript / V8 | ~1.44 s | ~69.3 million/s |
JavaScript/V8 was approximately 2.2× faster.
The final calculation result was effectively identical:
Lua: 39790.495829925
V8: 39790.49582992494
The tiny difference in the final decimal digits is due to floating-point representation/rounding.
2. Arrays and Objects Benchmark
A second benchmark tested three different workloads:
-
Pure arithmetic
-
Writing and reading 10 million array elements
-
Creating 10 million objects, modifying their properties, and reading those properties
The objects had the same structure in both languages:
{
id,
x,
y,
z,
health
}
Total execution time
| Runtime | Wall-clock Time |
|---|---|
| Lua | 11.84 s |
| JavaScript / V8 | 3.50 s |
In this combined benchmark, V8 completed the workload approximately 3.4× faster.
3. Memory Usage
Memory consumption was measured using:
/usr/bin/time -v
The primary metric here is:
Maximum resident set size
which represents the maximum resident memory (RSS) used by the process.
Maximum RSS
| Runtime | Maximum RSS |
|---|---|
| Lua | 3,545,492 KB ≈ 3.38 GB |
| JavaScript / V8 | 837,080 KB ≈ 818 MB |
For this particular workload, the Lua process used approximately 4.1× more resident memory than the Node.js/V8 process.
Why did Lua use so much memory?
The main contributor was the object benchmark, which created 10 million Lua tables:
{
id = i,
x = i * 2,
y = i * 3,
z = i * 4,
health = 100
}
Each table has its own internal representation, keys, values, and associated memory/GC metadata.
V8 has a highly optimized object model. For objects with the same structure, V8 can use mechanisms such as Hidden Classes / Shapes, allowing it to represent large numbers of structurally identical objects efficiently.
This makes the object-heavy workload particularly interesting from both a performance and memory-management perspective.
Why was V8 faster?
One major factor is the architecture of V8.
Modern V8 uses multiple execution tiers and JIT compilation.
A simplified model looks like this:
JavaScript
↓
V8
↓
Ignition
↓
Profiling / hot code detection
↓
JIT optimization
↓
Optimized machine code
↓
CPU
The arithmetic benchmark executes the same loop 100 million times, making it an ideal workload for JIT optimization.
The runtime can identify frequently executed code and optimize it for the observed types and operations.
Does this mean JavaScript is faster than Lua in FiveM?
Not necessarily.
This is the most important limitation of the benchmark.
We compared:
Lua runtime
vs
Node.js + V8
We did not compare:
FiveM Lua
vs
FiveM JavaScript
In real FiveM scripts, a significant amount of work often happens outside the scripting language itself:
Lua:
Lua → CitizenFX → C++ → GTA
JavaScript:
V8 → CitizenFX → C++ → GTA
For example:
GetEntityCoords(vehicle)
and:
GetEntityCoords(vehicle)
ultimately interact with the same game engine/native layer.
Therefore, a large advantage for V8 on pure computation does not automatically translate into the same advantage for real FiveM scripts.
Preliminary Conclusion
For the workloads tested:
-
V8 was ~2.2× faster than Lua on the pure arithmetic benchmark.
-
V8 was approximately 3.4× faster on the combined arithmetic/array/object benchmark.
-
On the object-heavy workload, Lua used approximately 4.1× more RSS memory than Node.js/V8.
-
V8’s JIT compilation and optimized object representation are likely major factors behind these results.
-
These results should not be interpreted as proof that JavaScript is faster than Lua inside FiveM.
The next step would be to run the same benchmarks inside the actual FiveM runtime, and separately benchmark native calls such as:
PlayerPedId()
GetEntityCoords()
GetEntityHealth()
GetVehiclePedIsIn()
That would provide a much more meaningful comparison of Lua vs JavaScript performance in real FiveM workloads.
Has anyone else run actual benchmarks? I’m just curious. I realize LuaJIT would likely be faster, but that’s not the case here; I was always told Lua was faster, yet in the ten-plus tests I ran, Lua 5.4 consistently turned out to be slower. This was using Node.js version 22.