Lua 5.4.0
lua.org
lua.org
When both were on version 5.1, there didn't seem to be any downsides to LuaJIT. Many Lua projects could benefit from it as long as they weren't trying to run on a platform that disallows JIT compilation (e.g. iOS or a game console).
However, now that LuaJIT is 2-3 language versions out-of-date, and has different best-practices (e.g. around FFI), it's almost like the two are different languages.
LuaJIT has (had?) weird memory limits due to its GC implementation. This matters if you're running scripts on a server.
It's unfortunate that LuaJIT fell behind so much, but as far as game engines who need a scripting language goes: You are either safe with Lua, or you have other alternatives: JavaScript, WASM, dynamic libraries and so on.
I'm not surprised the JIT isn't that good, but this is crazy almost! Did you compare against the latest version of Lua?
https://gist.github.com/fwsGonzo/f874ba58f2bab1bf502cad47a9b...
In my microbenchmarks LuaJIT was always faster than Lua, but not so much that I wouldn't stop using Lua. In my mind once you stop developing a language it stops being interesting, because you are always looking for ways to simplify and remove whole classes of bugs.
EDIT: I just built lua5.4 from sources and ran my benchmarks again, and it's markedly worse than LuaJIT still, but it's better than before for sure. My conclusion is that Lua5.4 is the fastest PUC-Lua yet.
https://gist.github.com/fwsGonzo/2f4518b66b147ee657d64496811...
local n = 0
local t = {}
-- to do an insert
n = n + 1
t[n] = blorp
-- to delegate some inserts to another function
n = insert_some_stuff(t,n)
A less messy thing you could do is local table_insert = table.insert
but this is not as great, because lua will still do a binary search to find the end of the array each time you insert something.I don't want to write local table_insert = ... I'd rather drop Lua for something else then. That said, it's cool that there are things you can do to speed things up if you really have to.
I actually started poking around at a language design over the past month that tries to leverage Lua as the compiler for something that can run in its own separate bytecode interpreter, with more of an emphasis on low level primitives. It started off as a simple adaptation of Forth ideas, but yesterday I started playing with a revision that shifts the data structure from plain old stack towards growable arrays containing three cursors(thus, "tricursor array") which can be purposed to describe bounds, destinations, insertion points, read and write, top of stack, etc. In Forth the top three values of the stack tend to get dedicated words for their manipulation because they are used quite often; this model runs with that idea plus methods I've often used for array data(text edits, sound sample loops, blotting sprites) and tries to extrapolate that into a language that can ease certain forms of array programming, while falling back on using the array as a data stack. Still just sketching it now.
1. Lua embeds well on a small system and gives us a higher level language than C. lua or luajit is ok
2. Lua isn't being used for performant code. If we have performance issues use C.
3. LuaJit is looking for a maintainer and is stagnant. This isn't desirable.
Not sure if this is "best practice" but it summarized how we worked through it.
Lua 5.4 has some appealing benefits for us, we'll give it a few patch releases, but I look forward to moving to it.
Re Performance: We're actually running from 50Hz code in Lua on an old embedded CPU. We haven't re-written that in C yet since it runs just fine. We're been constantly surprised at how well it runs and works for us.
+ Super easy FFI to C
+ Very fast (although profile to make sure this matters)
PUC Lua:
+ Possible to run untrusted code (e.g. user scripts) in a sandbox
+ Will run on a huge variety of platforms, including many microcontrollers (only limiting factor is a C compiler and a mostly-complete libc)
+ Has some additional language features (although some features, including integers, are controversial)
+ Actively maintained, expected to receive new releases and updates
In terms of language features, the biggest new feature are the "to be closed" variables. They can be used to ensure that cleanup routines are always called, similarly to RAII in C++ or try-finally blocks.
Some users presented separate complaints about resources kept in to-be-closed locals in coroutines not necessarily being closed. You can do something to try to solve this, like setting the __gc and __close metamethods of coroutines to call coroutine.close. A "real" solution would look more like dynamic-wind. Notably golang doesn't attempt to solve this one, so maybe not solving it is fine.
Does that mean it’s the same as C#'s `using` and Python's `with`?
<close> differs from `with` in at least the sense that it doesn't have any equivalent to __enter__ and doesn't create its own block. It creates a local variable whose __close metamethod will be called when it goes out of scope. Since Lua has lexical scope at the block level rather than the function level, this works similarly to the way Python calls __exit__.
These snippets of Python and Lua are roughly equivalent. They both open a file, read one line, and close it, or do nothing if there was some error opening the file.
try:
with open("foo.txt") as f:
print(f.readline())
# f is now closed.
except:
pass
local f,err = io.open("foo.txt")
if not err then
local f <close> = f
print(f:read("*l"))
end
-- f is now closed.
C#'s `using`[1] seems much closer, except that it handles nulls by not trying to close them and lua's <close> does not include any such handling.[0]: https://docs.python.org/3/reference/compound_stmts.html#the-...
[1]: https://docs.microsoft.com/en-us/dotnet/csharp/language-refe...
Is this just inertia, or is there a technical reason for new projects to embed Lua rather than a different language?
[0] https://insights.stackoverflow.com/survey/2018#technology-_-...
[0] http://www.squirrel-lang.org/
[1] https://en.wikipedia.org/wiki/Squirrel_(programming_language...
Sure, we are talking 2.5mb of library and about the same amount object code. Quite a bit larger than Lua. But that also gives you object code for working with texinfo (and quite a lot of completely unused, undocumented modules). I wonder how much could be stripped without anyone actually boticing
Almost trivial to add functions or calls in both directions.
- Header only project, with modern c++. Able to compile with and without mutex. Multiple context can run in parallel.
- Awesome integration and binding with c++ bars and functions.
There are two drawbacks. One is the maintenance and some performance quirks with returns and type conversions.
The other drawback, maintenance only [2]. the project accepts pull requests, but no recent activity on lenguaje or performance.
[2] https://github.com/ChaiScript/ChaiScript/commits?author=RobL...
And I would say that this argument still holds true. For extending a game or application, I'd feel pretty bad forcing people to use JS, for example (unless it's EE, where the gloves are off). Wren might be an option, but it's certainly a lot less proven.
Also, there's LuaJIT, if you really need some performance in a small package.
StackOverflow might not be the best source for end-user scripting. (Never mind that I have my doubts about any statistic where Rust ends up winning the popularity contest.)
I think it depends heavily on the person. Tcl has this problem, too, where lots of people love it and lots of people are completely put off by it.
The embedding API explicitly exposes a stack, so I assumed that it was implemented that way.
Lua 5.4 adds a new function, lua_setcstacklimit, but this merely exposes what was a compile-time constant, LUAI_MAXCCALLS, in earlier versions. Lua can't avoid making some use of the C stack as it supports intermingling of lua_call's from C code with in-language VM calls, which necessarily will use some amount of C stack. Lua has lua_callk for yield/resuming across C code invocations, but not everybody makes use of this and in any event it's only for coroutine semantics, not for recursion.
The limits for recursion have undertaken a significant change. (Though it might not be that concerning, if you see my sibling answer).
> As already discussed, Lua 5.4 is using a "non stackless" implementation. That means that it uses the C stack for recursion in Lua functions. Because of that, the maximum depth of recursion is much lower in 5.4 than it was in 5.3. - Roberto Ierusalimschy [0]
So instead of speculating on why the change happened, I've found a few bits of information around the limits that make me feel like it often simply won't be a problem.
There's some interesting discussion around the limits across various platforms here [0].
Whilst I'm not entirely clear on the motivation, even Lua running inside a browser under emcripten has a stack limit of over 4000, which is somewhat decent even for recursive functions.
Whereas on Linux you seem to be able to tweak a config when building and safely have it in the region of 20,000, and quite possibly more.
Even under a tight restriction, Lua seems to cope fairly well with it when recursing (the example crashed at 1758 recursions for a ulimit of 400).
Whilst Python has a terrible limit of 1000 for the default recursion limit which is somewhat comparable to this aggressive test, Python also has no tail call elimination - but Lua does.
I have a somewhat large Lua project (6000 lines of C, 10,000 lines of Lua) that is a recursive parser for a format that I passionately hate (think self-modifying LaTeX). With the default 5.4 limits it never hits a point where it crashes, though I had expected it to.
I have a few of those badly behaved recursive functions in the parser I mentioned at the end of my comment, and expected them to overflow, but they didn't hit the default limit.
It was libc's random, which is... Trash.
Now it use's xoshiro256 [a], which I hadn't heard of. (Not my area). [0] It seems somewhat similar to the MT, as it isn't cryptographically safe, but should give you a fast and fairly random set of integers back. It's also significantly faster than the MT.
[a] Followed by two asterisks. I give up trying to make them appear in HN's formatting.
Not my area either, but a little surprised why a PCG-family non-CSPRNG algorithm wasn’t used: https://www.pcg-random.org/posts/a-quick-look-at-xoshiro256....
PCG XSL RR 128/64 (MCG) could be used for 64-bit values (albeit with period 2^126 compared to xoroshiro256’s 2^256 − 1) with 128 bits. Half the state size than xoshiro256, and the performance might be comparable (would need benchmarking). LCG version if you want to trade PRNG quality for even more speed.
"Note: this provides only partial compatibility with Lua 5.2 at the language and Lua library level. moonjit is API+ABI-compatible with Lua 5.1, which prevents implementing features that would otherwise break the Lua/C API and ABI (e.g. _ENV)."
Some internal language changes in 5.3, like the new integer type, would require deep surgery in the JIT. This also seems to be the main (but not only) reason why Mike Pall doesn't have plans to ever support Lua 5.3. (https://www.reddit.com/r/lua/comments/2zutj8/mike_pall_luaji...)
LuaJIT had a beta release 3 years ago and hasn't been updated since.
The last commit is from 5 days ago.
That's what this is, this is the next major version of Lua.