Open CppCXY opened 2 months ago
Here are some old issues which suggested porting to luajit, maybe participants inside will be interested to test this out
How did you test with LuaJIT? Did you remove all <close>
variables?
How did you test with LuaJIT? Did you remove all
<close>
variables?
I replace close to defer :
I just did a preliminary benchmark here: https://github.com/LuaLS/lua-language-server/issues/2482#issuecomment-2385017356
40%
faster 🚀 textDocument/documentSymbol
of that file is 100%
slower 🐌 ... and currently I have no idea why 😕 I just did a preliminary benchmark here: #2482 (comment)
- The compile time of a large lua file (~8K lines) is
40%
faster 🚀- But the
textDocument/documentSymbol
of that file is100%
slower 🐌 ... and currently I have no idea why 😕
I have already fixed many issues related to the APIs. Please check the problems again
I have already fixed many issues related to the APIs. Please check the problems again
I checked out the latest commit https://github.com/LuaLS/lua-language-server-rust/commit/6c7bab8189cc6d9e18062e403d862cebbe05b1e2 and rebuilt the luals-rust, now textDocument/documentSymbol
is much faster than before 👍
[18:17:04.943][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [1.401]sec. {
[18:17:05.041][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.684]sec. {
[18:17:27.900][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.801]sec. {
[18:17:28.008][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.903]sec. {
[18:17:28.149][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.906]sec. {
[18:17:44.449][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.643]sec. {
[18:17:44.617][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.762]sec. {
[18:17:45.654][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.844]sec. {
[18:17:55.249][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.662]sec. {
[18:17:55.695][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.569]sec. {
[18:18:03.385][warn] [#0:resources/override_script/proto\proto.lua:189]: Method [textDocument/documentSymbol] takes [0.593]sec. {
0.789s
0.71s
🤔 (a little bit slower to be exact)
- but it's just on par with regular luals
0.71s
🤔 (a little bit slower to be exact)
Is there any comprehensive performance report, such as a comparison of memory usage and startup time for large codebases?
Is there any comprehensive performance report, such as a comparison of memory usage and startup time for large codebases?
I don't have that currently, I only tested it on a large file (the large_file.lua
generated by the python script mentioned in the above comment). Because with the compile time benchmark of a large file, we may directly see the performance gain (if any) by switching to luajit.
I might try to do a more comprehensive performance comparison on some of my team's projects later 🤔
By conducting startup tests on the luals project itself, the manually measured results are roughly as follows. It seems to be getting slower and slower, possibly due to my own limited skills. I look forward to others' tests. I will go back to working on my own language server. | language server | memory | start time |
---|---|---|---|
luals | 300mb | 10s | |
luals-rust-lua5.4 | 315mb | 10s | |
luals-rust-luajit | 330mb | 13.86s |
By conducting startup tests on the luals project itself
May I ask how did you conduct the start time test? By checking the timestamp in the log file? 😕
main.lua
the project to let luals startup in this workspace.[09:24:19.327][info] [#0:script\workspace\workspace.lua:38]: Workspace init root: file:///c%3A/Users/TomLau/lua-language-server
...
[09:24:21.968][warn] [#0:script\proto\proto.lua:189]: Method [textDocument/didOpen] takes [2.414]sec. {
Doing 5 runs on each server setup:
server | 1 | 2 | 3 | 4 | 5 | avg |
---|---|---|---|---|---|---|
luals-3.11 | 2.422 | 2.62 | 3.13 | 3.134 | 2.691 | 2.7994 |
luals-rust-luajit | 3.856 | 3.749 | 3.367 | 3.542 | 3.852 | 3.6732 |
luals-rust-luajit-jitoff | 2.3 | 2.456 | 2.95 | 2.114 | 2.404 | 2.4448 |
server | 1 | 2 | 3 | 4 | 5 | avg |
---|---|---|---|---|---|---|
luals-3.11 | 152 | 152 | 156 | 155 | 142 | 151.4 |
luals-rust-luajit | 175 | 173 | 179 | 179 | 185 | 178.2 |
luals-rust-luajit-jitoff | 129 | 127 | 127 | 131 | 128 | 128.4 |
jit.off()
as well. I added it in the main.lua
in luals-rust
project
require "luajitCompact"
local fs = require 'bee.filesystem'
local util = require 'utility'
local version = require 'version'
require 'config.env'
jit.off() jit.flush()
- ‼️ surprisingly it runs **FASTER** when `jit.off()` 🤔 maybe the startup logic of luals is not jit-friendly...
- ref for **turning off `jit` may improve performance**: https://www.cnblogs.com/zhaolaosan/p/16185249.html
amazing test result, I also got the same speed test results on luals-3.11: on luajit jit-off:
The speed improvement is about 40%. It might be faster if we can identify what is causing the JIT fail
The porting to LuaJIT has been completed, and the luajit branch has been merged into the main trunk. You can download it from the release, and I have already migrated to LuaLS version 3.11.
I just learnt that luajit has parameters for tuning:
The suggested params from these posts:
- maxtrace = 100'000 (instead of 1'000)
- maxrecord = 40'000 (instead of 4'000)
- maxside = 1'000 (instead of 100)
- sizemcode = 64 (instead of 32)
- maxmcode = 4'096 (instead of 512)
jit.opt.*
— JIT compiler optimization control:
So it maybe called like this in the code
jit.opt.start(
"maxtrace=100000",
"maxrecord=40000",
"maxside=1000",
"sizemcode=64",
"maxmcode=4096"
)
Maybe we can try fiddle them around and test the difference 🤔
Another test by performing full workspace diagnostic on luals project (for clarity I mean the lua-language-server
, but not lua-language-server-rust
). The measurement is just the time taken reported in this log:
[09:03:32.727][info] [#0:resources/override_script/provider\diagnostic.lua:566]: Diagnostics scope [file:///c%3A/Users/TomLau/lua-language-server], files count:[403]
...
[09:03:42.224][info] [#0:resources/override_script/provider\diagnostic.lua:583]: Diagnostics scope [file:///c%3A/Users/TomLau/lua-language-server] finished, takes [9.497] sec.
server | 1 | 2 | 3 | 4 | 5 | avg |
---|---|---|---|---|---|---|
luals-3.11 | 12.87 | 12.668 | 11.613 | 11.572 | 11.687 | 12.082 |
luajit-jitoff | 9.497 | 8.598 | 8.153 | 8.112 | 7.975 | 8.467 |
luajit-jiton | 21.27 | 18.919 | 19.036 | 19.036 | 19.025 | 19.4572 |
luajit-jiton-tune | 14.527 | 12.945 | 12.941 | 13.045 | 13.001 | 13.2918 |
luajit-jiton-tune
is using the jit.opt.start
params mentioned in the comment: https://github.com/LuaLS/lua-language-server/issues/2879#issuecomment-2387850765, I add it in the luajitCompact.lua
in luals-rust
projectjiton-tune
is still slower than regular luals-3.11
jitoff
is the fastest for codebase in current state, and jiton
with default params is the slowest.It would be interesting to know the OS & CPU architecture you both run those benchmarks on. This may be a case of: https://github.com/LuaJIT/LuaJIT/issues/285
my system spec:
Maybe we can use the jit.dump module to see the reasons for jit failure and then consider targeted optimizations. I see many traces about inspect and luadoc.
Try this version: https://github.com/openresty/luajit2
Just to note that calls into C code cannot be JIT compiled, so if LuaLS calls into C a lot (into bee.lua), then it's likely the JIT isn't able to do much.
Just to note that calls into C code cannot be JIT compiled, so if LuaLS calls into C a lot (into bee.lua), then it's likely the JIT isn't able to do much.
The current situation is that JIT has caused a significant performance drop. By analyzing the results of the JIT dump, I obtained this chart:
Just to note that calls into C code cannot be JIT compiled, so if LuaLS calls into C a lot (into bee.lua), then it's likely the JIT isn't able to do much.
Are you sure about this? I am pretty sure that it can be JIT compiled, the C calls become inlined
here are the simple:
File: luadoc.lua, Line: 939, Error: NYI: bytecode FNEW , Count: 405
File: compile.lua, Line: 604, Error: inner loop in root trace, Count: 280
File: guide.lua, Line: 748, Error: NYI: bytecode UCLO , Count: 233
File: compile.lua, Line: 409, Error: NYI: bytecode FNEW , Count: 182
File: variable.lua, Line: 55, Error: NYI: bytecode UCLO , Count: 141
File: scope.lua, Line: 214, Error: inner loop in root trace, Count: 107
File: compile.lua, Line: 604, Error: loop unroll limit reached, Count: 88
File: luadoc.lua, Line: 1822, Error: NYI: bytecode FNEW , Count: 78
File: compile.lua, Line: 606, Error: leaving loop in root trace, Count: 55
File: compile.lua, Line: 2759, Error: leaving loop in root trace, Count: 37
File: await.lua, Line: 65, Error: leaving loop in root trace, Count: 33
File: global.lua, Line: 167, Error: NYI: bytecode FNEW , Count: 33
File: files.lua, Line: 981, Error: NYI: bytecode FNEW , Count: 32
File: luadoc.lua, Line: 824, Error: inner loop in root trace, Count: 29
File: luadoc.lua, Line: 1832, Error: NYI: bytecode UCLO , Count: 28
File: luadoc.lua, Line: 955, Error: NYI: bytecode UCLO , Count: 27
File: luadoc.lua, Line: 870, Error: inner loop in root trace, Count: 26
File: guide.lua, Line: 746, Error: NYI: bytecode FNEW , Count: 26
File: luadoc.lua, Line: 1854, Error: inner loop in root trace, Count: 25
File: luadoc.lua, Line: 830, Error: leaving loop in root trace, Count: 25
File: luadoc.lua, Line: 2091, Error: leaving loop in root trace, Count: 25
File: guide.lua, Line: 683, Error: loop unroll limit reached, Count: 25
File: guide.lua, Line: 779, Error: loop unroll limit reached, Count: 25
File: luadoc.lua, Line: 837, Error: leaving loop in root trace, Count: 23
File: compile.lua, Line: 2090, Error: leaving loop in root trace, Count: 23
File: luadoc.lua, Line: 568, Error: NYI: bytecode FNEW , Count: 22
File: loading.lua, Line: 39, Error: NYI: bytecode UCLO , Count: 22
File: luadoc.lua, Line: 1946, Error: leaving loop in root trace, Count: 22
File: compile.lua, Line: 1790, Error: inner loop in root trace, Count: 21
File: luadoc.lua, Line: 824, Error: loop unroll limit reached, Count: 20
File: luadoc.lua, Line: 2003, Error: leaving loop in root trace, Count: 20
File: 0x01d10bece3a0, Line: 4, Error: leaving loop in root trace, Count: 19
File: guide.lua, Line: 768, Error: leaving loop in root trace, Count: 18
File: compile.lua, Line: 1488, Error: inner loop in root trace, Count: 18
File: utility.lua, Line: 229, Error: NYI: bytecode FNEW , Count: 17
File: compile.lua, Line: 2161, Error: inner loop in root trace, Count: 17
File: log.lua, Line: 61, Error: leaving loop in root trace, Count: 16
File: luadoc.lua, Line: 2078, Error: leaving loop in root trace, Count: 16
File: luadoc.lua, Line: 1829, Error: NYI: bytecode FNEW , Count: 15
File: guide.lua, Line: 796, Error: inner loop in root trace, Count: 14
File: compile.lua, Line: 1993, Error: leaving loop in root trace, Count: 14
File: luadoc.lua, Line: 2016, Error: leaving loop in root trace, Count: 13
File: guide.lua, Line: 456, Error: inner loop in root trace, Count: 13
File: compile.lua, Line: 2727, Error: inner loop in root trace, Count: 13
File: diagnostic.lua, Line: 433, Error: NYI: bytecode UCLO , Count: 12
File: luadoc.lua, Line: 1832, Error: leaving loop in root trace, Count: 12
File: 0x01d1086d96a0, Line: 5, Error: leaving loop in root trace, Count: 12
File: guide.lua, Line: 808, Error: loop unroll limit reached, Count: 11
File: inspect.lua, Line: 296, Error: down-recursion, restarting, Count: 10
File: workspace.lua, Line: 92, Error: NYI: bytecode UCLO , Count: 10
File: compile.lua, Line: 2759, Error: down-recursion, restarting, Count: 10
File: guide.lua, Line: 796, Error: loop unroll limit reached, Count: 10
File: inspect.lua, Line: 148, Error: persistent type instability, Count: 9
File: library.lua, Line: 135, Error: leaving loop in root trace, Count: 9
File: diagnostic.lua, Line: 456, Error: NYI: bytecode UCLO , Count: 9
File: luadoc.lua, Line: 1152, Error: NYI: bytecode FNEW , Count: 9
File: 0x01d17ec3ab60, Line: 9, Error: leaving loop in root trace, Count: 9
File: compile.lua, Line: 978, Error: inner loop in root trace, Count: 9
File: compile.lua, Line: 2080, Error: inner loop in root trace, Count: 9
File: inspect.lua, Line: 148, Error: loop unroll limit reached, Count: 8
File: inspect.lua, Line: 255, Error: inner loop in root trace, Count: 8
File: net.lua, Line: 282, Error: leaving loop in root trace, Count: 8
File: utility.lua, Line: 652, Error: NYI: bytecode FNEW , Count: 8
File: 0x01d1090ab5a0, Line: 4, Error: leaving loop in root trace, Count: 8
File: luadoc.lua, Line: 2008, Error: leaving loop in root trace, Count: 8
File: compile.lua, Line: 3655, Error: leaving loop in root trace, Count: 8
File: luadoc.lua, Line: 2030, Error: inner loop in root trace, Count: 7
File: json.lua, Line: 180, Error: inner loop in root trace, Count: 7
File: 0x01d1090b85a0, Line: 4, Error: leaving loop in root trace, Count: 7
File: compile.lua, Line: 2279, Error: leaving loop in root trace, Count: 7
File: compile.lua, Line: 2185, Error: leaving loop in root trace, Count: 7
File: 0x01d10c8a9aa0, Line: 5, Error: leaving loop in root trace, Count: 7
File: pub.lua, Line: 193, Error: leaving loop in root trace, Count: 7
File: compile.lua, Line: 2161, Error: loop unroll limit reached, Count: 7
File: files.lua, Line: 939, Error: NYI: bytecode FNEW , Count: 7
File: inspect.lua, Line: 141, Error: call unroll limit reached, Count: 6
File: files.lua, Line: 983, Error: leaving loop in root trace, Count: 6
File: scope.lua, Line: 218, Error: leaving loop in root trace, Count: 6
File: json.lua, Line: 200, Error: leaving loop in root trace, Count: 6
File: global.lua, Line: 707, Error: NYI: bytecode FNEW , Count: 6
File: luadoc.lua, Line: 1972, Error: leaving loop in root trace, Count: 6
File: 0x01d10bed0010, Line: 4, Error: leaving loop in root trace, Count: 6
File: luadoc.lua, Line: 1853, Error: leaving loop in root trace, Count: 6
File: compile.lua, Line: 2011, Error: down-recursion, restarting, Count: 6
File: compile.lua, Line: 3471, Error: inner loop in root trace, Count: 6
File: inspect.lua, Line: 148, Error: inner loop in root trace, Count: 5
File: inspect.lua, Line: 137, Error: leaving loop in root trace, Count: 5
File: scope.lua, Line: 74, Error: inner loop in root trace, Count: 5
File: luadoc.lua, Line: 1095, Error: inner loop in root trace, Count: 5
File: compile.lua, Line: 1546, Error: leaving loop in root trace, Count: 5
File: 0x01d1090b8dc0, Line: 3, Error: loop unroll limit reached, Count: 5
File: compile.lua, Line: 3498, Error: leaving loop in root trace, Count: 5
File: compile.lua, Line: 3471, Error: loop unroll limit reached, Count: 5
File: compile.lua, Line: 2199, Error: loop unroll limit reached, Count: 5
File: provider.lua, Line: 80, Error: NYI: bytecode FNEW , Count: 4
File: inspect.lua, Line: 151, Error: leaving loop in root trace, Count: 4
File: scope.lua, Line: 232, Error: leaving loop in root trace, Count: 4
File: luadoc.lua, Line: 2023, Error: leaving loop in root trace, Count: 4
File: scope.lua, Line: 75, Error: inner loop in root trace, Count: 4
File: luadoc.lua, Line: 2009, Error: inner loop in root trace, Count: 4
File: compile.lua, Line: 2075, Error: inner loop in root trace, Count: 4
File: guide.lua, Line: 532, Error: loop unroll limit reached, Count: 4
File: compile.lua, Line: 721, Error: leaving loop in root trace, Count: 4
File: compile.lua, Line: 2080, Error: persistent type instability, Count: 4
File: 0x01d1090b9100, Line: 4, Error: leaving loop in root trace, Count: 4
File: guide.lua, Line: 337, Error: inner loop in root trace, Count: 4
File: 0x01d1086daf00, Line: 3, Error: loop unroll limit reached, Count: 4
File: variable.lua, Line: 392, Error: leaving loop in root trace, Count: 4
File: variable.lua, Line: 71, Error: leaving loop in root trace, Count: 4
File: compile.lua, Line: 1144, Error: leaving loop in root trace, Count: 4
File: compile.lua, Line: 3908, Error: loop unroll limit reached, Count: 4
File: compile.lua, Line: 3505, Error: down-recursion, restarting, Count: 4
File: guide.lua, Line: 532, Error: persistent type instability, Count: 4
File: compile.lua, Line: 1481, Error: leaving loop in root trace, Count: 4
File: compile.lua, Line: 1593, Error: inner loop in root trace, Count: 4
File: luadoc.lua, Line: 1911, Error: inner loop in root trace, Count: 4
File: guide.lua, Line: 783, Error: leaving loop in root trace, Count: 4
File: 0x01d1086d96a0, Line: 4, Error: loop unroll limit reached, Count: 4
File: luadoc.lua, Line: 1795, Error: inner loop in root trace, Count: 4
File: compile.lua, Line: 302, Error: loop unroll limit reached, Count: 4
File: luadoc.lua, Line: 2132, Error: NYI: bytecode FNEW , Count: 4
File: gitignore.lua, Line: 76, Error: leaving loop in root trace, Count: 3
File: workspace.lua, Line: 103, Error: NYI: bytecode FNEW , Count: 3
File: files.lua, Line: 979, Error: inner loop in root trace, Count: 3
File: json.lua, Line: 185, Error: leaving loop in root trace, Count: 3
File: json.lua, Line: 113, Error: leaving loop in root trace, Count: 3
File: compile.lua, Line: 2727, Error: loop unroll limit reached, Count: 3
File: compile.lua, Line: 978, Error: loop unroll limit reached, Count: 3
File: 0x01d10becdec0, Line: 4, Error: leaving loop in root trace, Count: 3
File: compile.lua, Line: 2095, Error: leaving loop in root trace, Count: 3
File: luadoc.lua, Line: 2089, Error: inner loop in root trace, Count: 3
File: global.lua, Line: 184, Error: inner loop in root trace, Count: 3
File: luadoc.lua, Line: 2163, Error: NYI: bytecode UCLO , Count: 3
File: 0x01d1086daf00, Line: 6, Error: leaving loop in root trace, Count: 3
File: compile.lua, Line: 658, Error: inner loop in root trace, Count: 3
File: compile.lua, Line: 3184, Error: leaving loop in root trace, Count: 3
File: 0x01d10b89bc90, Line: 8, Error: leaving loop in root trace, Count: 3
File: compile.lua, Line: 3920, Error: loop unroll limit reached, Count: 3
File: 0x01d10c8a98c0, Line: 5, Error: leaving loop in root trace, Count: 3
File: compile.lua, Line: 577, Error: leaving loop in root trace, Count: 3
File: compile.lua, Line: 414, Error: inner loop in root trace, Count: 3
File: inspect.lua, Line: 132, Error: inner loop in root trace, Count: 2
File: progress.lua, Line: 149, Error: leaving loop in root trace, Count: 2
File: files.lua, Line: 908, Error: leaving loop in root trace, Count: 2
File: language.lua, Line: 68, Error: NYI: bytecode FNEW , Count: 2
File: await.lua, Line: 185, Error: NYI: bytecode FNEW , Count: 2
File: 0x01d108c59670, Line: 7, Error: leaving loop in root trace, Count: 2
File: luadoc.lua, Line: 582, Error: NYI: bytecode UCLO , Count: 2
File: files.lua, Line: 169, Error: leaving loop in root trace, Count: 2
File: global.lua, Line: 735, Error: leaving loop in root trace, Count: 2
File: compile.lua, Line: 4084, Error: NYI: bytecode FNEW , Count: 2
File: luadoc.lua, Line: 583, Error: NYI: bytecode UCLO , Count: 2
File: luadoc.lua, Line: 590, Error: NYI: bytecode UCLO , Count: 2
File: guide.lua, Line: 775, Error: leaving loop in root trace, Count: 2
File: loading.lua, Line: 114, Error: NYI: bytecode FNEW , Count: 2
File: gitignore.lua, Line: 95, Error: error thrown or hook called during recording, Count: 2
File: compile.lua, Line: 3902, Error: loop unroll limit reached, Count: 2
File: variable.lua, Line: 220, Error: leaving loop in root trace, Count: 2
File: luadoc.lua, Line: 2011, Error: inner loop in root trace, Count: 2
File: guide.lua, Line: 523, Error: NYI: bytecode FNEW , Count: 2
File: utility.lua, Line: 727, Error: NYI: bytecode UCLO , Count: 2
File: compile.lua, Line: 3632, Error: leaving loop in root trace, Count: 2
File: luadoc.lua, Line: 1854, Error: loop unroll limit reached, Count: 2
File: compile.lua, Line: 2764, Error: inner loop in root trace, Count: 2
File: 0x01d1082d30b0, Line: 8, Error: leaving loop in root trace, Count: 2
File: 0x01d108f354e0, Line: 9, Error: leaving loop in root trace, Count: 2
File: 0x01d109b0b9d0, Line: 4, Error: leaving loop in root trace, Count: 2
File: luadoc.lua, Line: 2135, Error: NYI: bytecode FNEW , Count: 2
File: guide.lua, Line: 541, Error: NYI: bytecode UCLO , Count: 2
File: guide.lua, Line: 540, Error: leaving loop in root trace, Count: 2
File: await.lua, Line: 152, Error: NYI: bytecode VARG , Count: 2
File: 0x01d10bece3a0, Line: 3, Error: inner loop in root trace, Count: 2
File: compile.lua, Line: 2199, Error: inner loop in root trace, Count: 2
File: plugin.lua, Line: 51, Error: leaving loop in root trace, Count: 2
File: global.lua, Line: 710, Error: NYI: bytecode FNEW , Count: 2
File: 0x01d1090b8dc0, Line: 3, Error: inner loop in root trace, Count: 2
File: luadoc.lua, Line: 2251, Error: leaving loop in root trace, Count: 2
File: 0x01d1086d96a0, Line: 4, Error: inner loop in root trace, Count: 2
File: 0x01d108f351b0, Line: 6, Error: leaving loop in root trace, Count: 2
File: luadoc.lua, Line: 2186, Error: NYI: bytecode FNEW , Count: 2
File: capability.lua, Line: 18, Error: inner loop in root trace, Count: 1
File: capability.lua, Line: 42, Error: error thrown or hook called during recording, Count: 1
File: capability.lua, Line: 46, Error: leaving loop in root trace, Count: 1
File: inspect.lua, Line: 274, Error: inner loop in root trace, Count: 1
File: config.lua, Line: 209, Error: inner loop in root trace, Count: 1
File: template.lua, Line: 179, Error: inner loop in root trace, Count: 1
File: workspace.lua, Line: 34, Error: leaving loop in root trace, Count: 1
File: log.lua, Line: 59, Error: inner loop in root trace, Count: 1
File: compile.lua, Line: 3195, Error: leaving loop in root trace, Count: 1
File: luadoc.lua, Line: 2021, Error: inner loop in root trace, Count: 1
File: 0x01d108503440, Line: 16, Error: leaving loop in root trace, Count: 1
File: guide.lua, Line: 813, Error: leaving loop in root trace, Count: 1
File: guide.lua, Line: 807, Error: leaving loop in root trace, Count: 1
File: utility.lua, Line: 848, Error: NYI: bytecode FNEW , Count: 1
File: node.lua, Line: 67, Error: inner loop in root trace, Count: 1
File: luadoc.lua, Line: 1795, Error: loop unroll limit reached, Count: 1
File: guide.lua, Line: 204, Error: inner loop in root trace, Count: 1
File: timer.lua, Line: 96, Error: leaving loop in root trace, Count: 1
File: pub.lua, Line: 203, Error: error thrown or hook called during recording, Count: 1
File: loading.lua, Line: 31, Error: error thrown or hook called during recording, Count: 1
File: config.lua, Line: 189, Error: error thrown or hook called during recording, Count: 1
File: config.lua, Line: 161, Error: error thrown or hook called during recording, Count: 1
File: gitignore.lua, Line: 176, Error: error thrown or hook called during recording, Count: 1
File: service.lua, Line: 158, Error: error thrown or hook called during recording, Count: 1
File: workspace.lua, Line: 91, Error: error thrown or hook called during recording, Count: 1
File: files.lua, Line: 819, Error: error thrown or hook called during recording, Count: 1
File: loading.lua, Line: 70, Error: error thrown or hook called during recording, Count: 1
File: timer.lua, Line: 228, Error: error thrown or hook called during recording, Count: 1
File: config.lua, Line: 34, Error: error thrown or hook called during recording, Count: 1
File: workspace.lua, Line: 345, Error: error thrown or hook called during recording, Count: 1
File: guide.lua, Line: 776, Error: loop unroll limit reached, Count: 1
File: json.lua, Line: 179, Error: inner loop in root trace, Count: 1
File: utility.lua, Line: 220, Error: leaving loop in root trace, Count: 1
File: 0x01d1090b85a0, Line: 3, Error: loop unroll limit reached, Count: 1
File: progress.lua, Line: 143, Error: inner loop in root trace, Count: 1
File: 0x01d17e87c390, Line: 8, Error: leaving loop in root trace, Count: 1
File: luadoc.lua, Line: 1956, Error: inner loop in root trace, Count: 1
File: luadoc.lua, Line: 870, Error: loop unroll limit reached, Count: 1
File: compile.lua, Line: 2080, Error: loop unroll limit reached, Count: 1
File: 0x01d10bece3a0, Line: 3, Error: loop unroll limit reached, Count: 1
File: compile.lua, Line: 2568, Error: loop unroll limit reached, Count: 1
File: utility.lua, Line: 215, Error: leaving loop in root trace, Count: 1
File: compile.lua, Line: 2075, Error: loop unroll limit reached, Count: 1
File: 0x01d1090ab5a0, Line: 3, Error: inner loop in root trace, Count: 1
File: guide.lua, Line: 337, Error: loop unroll limit reached, Count: 1
File: compile.lua, Line: 4122, Error: leaving loop in root trace, Count: 1
File: scope.lua, Line: 87, Error: leaving loop in root trace, Count: 1
File: guide.lua, Line: 779, Error: inner loop in root trace, Count: 1
File: variable.lua, Line: 227, Error: leaving loop in root trace, Count: 1
File: 0x01d1086daf00, Line: 3, Error: inner loop in root trace, Count: 1
File: global.lua, Line: 187, Error: leaving loop in root trace, Count: 1
File: luadoc.lua, Line: 1656, Error: error thrown or hook called during recording, Count: 1
File: gitignore.lua, Line: 149, Error: leaving loop in root trace, Count: 1
File: 0x01d10becdec0, Line: 3, Error: loop unroll limit reached, Count: 1
File: compile.lua, Line: 1722, Error: down-recursion, restarting, Count: 1
File: compile.lua, Line: 2577, Error: loop unroll limit reached, Count: 1
File: compile.lua, Line: 1394, Error: error thrown or hook called during recording, Count: 1
File: compile.lua, Line: 571, Error: loop unroll limit reached, Count: 1
File: pub.lua, Line: 138, Error: NYI: bytecode FNEW , Count: 1
File: files.lua, Line: 722, Error: NYI: bytecode FNEW , Count: 1
File: luadoc.lua, Line: 1975, Error: loop unroll limit reached, Count: 1
File: compile.lua, Line: 4020, Error: inner loop in root trace, Count: 1
File: guide.lua, Line: 572, Error: inner loop in root trace, Count: 1
File: luadoc.lua, Line: 2138, Error: loop unroll limit reached, Count: 1
File: pub.lua, Line: 203, Error: inner loop in root trace, Count: 1
Just to note that calls into C code cannot be JIT compiled, so if LuaLS calls into C a lot (into bee.lua), then it's likely the JIT isn't able to do much.
Are you sure about this? I am pretty sure that it can be JIT compiled, the C calls become inlined
Pretty sure. Calls into C can't be JIT compiled, but calls into C via the FFI can.
Read the top of: https://luajit.org/ext_ffi.html
The FFI library is tightly integrated into LuaJIT (it's not available as a separate module). The code generated by the JIT-compiler for accesses to C data structures from Lua code is on par with the code a C compiler would generate. Calls to C functions can be inlined in JIT-compiled code, unlike calls to functions bound via the classic Lua/C API.
bee.lua uses the "classic Lua/C API".
bee.lua uses the "classic Lua/C API".
a bit mistaken; the luajit porting work was done on my rust version, not bee.lua. The entire bee API was implemented by me using rust. However, the conclusion remains unchanged: it is indeed a C API call. From the jit trace data, it appears that the significant performance degradation is due to too many jit failures, rather than an issue with the C API itself.
Ok, there is some space to rearrange the code a bit to work around the NYI (not yet implemented) bytecodes. The FNEW
stands for closure construction. Maybe the most offending closures can be made free functions instead? Particularly https://github.com/LuaLS/lua-language-server/blob/f6dcbcc08d8d07e4a4bb61dfd3c9b367078818f1/script/parser/luadoc.lua#L896C20-L896C30`pushResume`
Is this up-to-date?
Just to note that calls into C code cannot be JIT compiled, so if LuaLS calls into C a lot (into bee.lua), then it's likely the JIT isn't able to do much.
Are you sure about this? I am pretty sure that it can be JIT compiled, the C calls become inlined
From http://luajit.org/ext_ffi.html:
The FFI library allows calling external C functions and using C data structures from pure Lua code.
The FFI library largely obviates the need to write tedious manual Lua/C bindings in C. No need to learn a separate binding language — it parses plain C declarations! These can be cut-n-pasted from C header files or reference manuals. It's up to the task of binding large libraries without the need for dealing with fragile binding generators.
The FFI library is tightly integrated into LuaJIT (it's not available as a separate module). The code generated by the JIT-compiler for accesses to C data structures from Lua code is on par with the code a C compiler would generate. Calls to C functions can be inlined in JIT-compiled code, unlike calls to functions bound via the classic Lua/C API.
So it appears that to achieve best performance, you need to use the FFI to call non-Lua/pre-compiled functions. In that case, when the Lua is jit-compiled, the external calls to pre-compiled code will often be inlined and it will all get compiled as one binary/native (function).
Idk the finer details, but if I'm not mistaken, with the usual/classic Lua C api you are forced to use the Lua calling convention and Lua stack (for passing args, returns, etc.)? But with the FFI, you simply call regular C functions directly (which are not written to use the Lua stack at all), which forgoes the Lua stack entirely and uses the native calling convention/stack? So (for jit-compiled code) you not only get inlined calls, but you get to avoid the Lua stack completely (which is probably implemented in the heap) including all of the code which manages it. But the hard part (probably?) is taking advantage of all this and getting the jit settings just right, etc., in order to maximize your application's performance and offset the overhead of dynamic/runtime jit-compilation. Maybe some data structures need to be converted over to use native structs and arrays as well? (which may be managed/used/handled directly in Lua via luajit's builtin FFI)
My understanding is that C calls are inlined in jit-compiled Lua if calling C functions via the FFI. For best performance however, I believe you need to write "native" C functions (i.e. written without Lua in mind, written without using Lua's stack/calling convention, and written using native data types/structures) as much as possible. So perhaps taking full advantage of all of this would require a decent amount of the codebase to be rewritten? OTOH, I thought that simply switching to luajit runtime alone would have been enough to improve performance, but maybe I'm wrong.
Is this up-to-date?
That's someone's backup of the last time this page was on LuaJIT's wiki, which the uploader got from archive.org. That's as up-to-date as it can be. LuaJIT's master branch has recently had some development, but IIRC none pertaining to implementing any remaining NYI
bytecodes.
bee.lua uses the "classic Lua/C API".
whoops i thought you meant using FFI
OTOH, I thought that simply switching to luajit runtime alone would have been enough to improve performance, but maybe I'm wrong.
Same, I think its due to the frequency of the C api calls, and if its inlined with FFI (or fully rewritten to only use FFI) it could be truly unleashed
OTOH, I thought that simply switching to luajit runtime alone would have been enough to improve performance, but maybe I'm wrong.
Same, I think its due to the frequency of the C api calls, and if its inlined with FFI (or fully rewritten to only use FFI) it could be truly unleashed
From my benchmark above: https://github.com/LuaLS/lua-language-server/issues/2879#issuecomment-2385026553
jit.off()
) seems faster than regular lua: 🤔 script/parser/compile.lua
, which is written in pure lua without bee.lua
or other C api callsjit.off()
, I believe this performance gain is unrelated to frequency of c api calls / ffi
=> it's that the raw performance is fasterI think continuing to work on this doesn't seem promising. I plan to completely rewrite a language server in Rust, but it won't be LuaLS. If necessary, we can integrate the parser part into the luals_rust project later and see the results.
I just created this repository. If you're interested, please follow it: https://github.com/CppCXY/emmylua-analyzer-rust
Would you implement it in a way that supports LuaCATS? Although I am not a big fan of this annotation system, I think a unified annotation system (even if it comes from the community) would benefit the ecosystem.
Would you implement it in a way that supports LuaCATS? Although I am not a big fan of this annotation system, I think a unified annotation system (even if it comes from the community) would benefit the ecosystem.
Of course, I will support LuaCATS, but I will also add some of my own features. In fact, I have implemented this many times in different languages, so it's not very difficult for me.
The current LuaJIT porting is complete.
jit.on
is not enabled becausejit.off
performs better. Feel free to try it if you're interested.see: https://github.com/LuaLS/lua-language-server-rust