LuaJIT PR: Add Support for RISC-V 64
146 points
29 days ago
| 4 comments
| github.com
| HN
fwsgonzo
29 days ago
[-]
Wow, that's an impressive PR with very well written and succinct code. Macro-fusion too! B-extension support!? I see some RORIWs in there.

Alright, time to run some LuaJIT in my RISC-V emulator.

reply
fwsgonzo
28 days ago
[-]

  function fib(n, acc, prev)
    if (n < 1) then
      return acc
    else
      return fib(n - 1, prev + acc, acc)
    end
  end
  print(fib(50, 0, 1))

  $ ./rvlinux -P ~/github/LuaRiscvJIT/src/luajit -- test.lua
  12586269025
  >>> Program exited, exit code = 0 (0x0)
  Runtime: 0.281ms   (Use --accurate for instruction counting)
  Pages in use: 429 (1716 kB virtual memory, total 2674 kB)
It's definitely working!
reply
xeonmc
28 days ago
[-]
Can this be embedded into a game engine to enable performant Lua scripting?
reply
_cogg
28 days ago
[-]
You used to have to be extremely careful to keep the JIT happy, but I think this has been partially solved in LuaJIT 2.1.

Calling C functions using the old stack API would cause the JIT to abort. In Garrysmod's case, that includes such simple operations as constructing and performing arithmetic on vectors.

So when I was building a high-performance voxel library for Garrysmod, I ended up splitting my hot code into chunks that the JIT compiler would usually be happy with. One fast loop to generate a mesh, then a slow loop to convert that into a mesh structure the engine wants. Very carefully designed methods for bit-packing trees of 12-bit integer voxel data into flat tables of floats.

reply
no_time
28 days ago
[-]
Any video/blogpost of your voxel library in action? Sounds interesting.
reply
mardifoufs
28 days ago
[-]
It it still true that generating bindings for luajit is easier than with plain Lua? When I used it for a toy project that was the main reason I chose luajit, especially since the project was written in c++.
reply
_cogg
28 days ago
[-]
Writing bindings isn't something I have a lot of experience with. The main difference I'm aware of is the FFI system, which creates bindings from C headers, and will result in faster calls with good JIT support. I assume it introduces some extra security challenges if you care about that. You'll still probably need to write some wrappers, either C-side or Lua-side if you want a nice API. I know there are other tools for creating bindings, but again, not my area of expertise.
reply
krapp
28 days ago
[-]
In my experience it very much is. Most of the LuaJIT code I write is just metatable classes around C libraries like SDL. Just being able to write C structs and lua functions is a dream. Having to manually deal with the stack from C-side is a PITA.
reply
vvanders
28 days ago
[-]
Can? It always has been :).

We ran Lua for the entire core of a game in a 400kb preallocated on the PSP about 20 years ago. I know of many places that used it long before us.

reply
fwip
28 days ago
[-]
I think parent is asking specifically about luajit, not just Lua the language.
reply
krapp
28 days ago
[-]
Yes, Luajit.
reply
extrememacaroni
28 days ago
[-]
That's literally one of the main uses of luajit.
reply
snvzz
28 days ago
[-]
RISC-V is rapidly growing the strongest ecosystem.
reply
akira2501
28 days ago
[-]
It's the newest ecosystem. They all seem strong when they are uncomplicated. So far that has never lasted.
reply
snvzz
28 days ago
[-]
>They all seem strong when they are uncomplicated.

RISC-V, as of current state of specs (RVA23/RVB23) has already caught up with x86-64 and arm64.

Still, It remains an order of magnitude simpler. And this is unlikely to change.

>So far that has never lasted.

There hasn't been that much innovation in the ISA space since the 80s. There's nothing to suggest there'll suddenly be.

In the first place, the way RISC-V specifications are developed does not invite experiments finding their way into ratified specifications. They can instead live in the encoding space reserved for custom extensions.

This is, of course, in direct contrast to what has been the norm in proprietary ISAs, where the vendor that controls the ISA typically adds "features" to it with abandon.

reply
akira2501
28 days ago
[-]
> state of specs (RVA23/RVB23)

One of which doesn't require vector. I mean..

> has already caught up with x86-64 and arm64.

What's your actual measure for this?

> And this is unlikely to change.

Is anything is being manufactured in volume with actual specs I can look at?

> much innovation in the ISA space since the 80s. There's nothing to suggest there'll suddenly be.

If what you're suggesting is true then that's what suggests there would be. My pessimism exists for both.

> in direct contrast to what has been the norm in proprietary ISAs

That's because they have actual customers in volume.

reply
brucehoult
27 days ago
[-]
> What's your actual measure for this?

Features e.g. hypervisor, cache control, security ...

> Is anything is being manufactured in volume with actual specs I can look at?

RVA23 was just ( I assume) ratified a few days ago on August 29, RVB23 is due December 26th, so actual chips in production, on boards you can buy, will be some time away.

There are several SoCs already out implementing RVA22+V. The CanMV-K230 board is a bit limited with only single core and 512 MB RAM and is only slightly cheaper than an 8 core, 256 bit vectors, 4 GB board with the K1 SoC such as the Banana Pi BPI-F3, which is also available with 8 or 16 GB RAM.

There are also already quite a number of other options to get the same SoC: Sipeed Lichee Pi 3A (or compute module 3A), Milk-V Jupiter (mini-ITX) or laptops including the MuseBook and DC-Roma II.

Those are all just a bit faster than a Raspberry Pi 3 or Zero 2 -- other than having more than 4 cores and much more than 0.5 or 1 GB RAM -- but several faster SoCs are coming soon. First the Eswin EIC7700 with 4 faster (~A75) cores but no V extension, coming on several boards Real Soon Now, then next year the SG2380 with 16 RVA22+V cores that should come in faster than the A76 in the Pi 5, Rock 5, Orange Pi 5.

reply
a1o
28 days ago
[-]
Uhm, I remember LuaJIT used to be frozen in Lua 5.1, is it still the case or is it now synced to the latest Lua release?
reply
mardifoufs
28 days ago
[-]
I think the LuaJIT maintainers have some issues with recent additions to the language, and with the direction that the Lua team has taken. So yes, frozen to 5.1 for the foreseeable future except for some features from more recent versions.
reply
matheusmoreira
28 days ago
[-]
I can't seem to find any information about this. What issues did LuaJIT maintainers have with upstream Lua?
reply
mardifoufs
28 days ago
[-]
The issue linked in the sibling comment is the main one, but for a specific example of them having reservations about a feature in a more recent version, there's this:

https://github.com/LuaJIT/LuaJIT/issues/1013#issuecomment-16...

reply
bjconlan
28 days ago
[-]
Oh wow, from Mike Pall himself (I know he "retired" from the maintainer position but glad he is still providing guidance (and then some id imagine))

Seeing a project and a community functioning like this is simply inspiring.

reply
matheusmoreira
28 days ago
[-]
That's an awesome example, thank you. I'm making my own language and it's hard to overstate how thorny the evaluator and call stack code can get once seemingly neat features are added. I'll try to avoid making the same mistakes. I agree with him that implicit scopes for resource management serve no purpose in a dynamic language.
reply
edflsafoiewq
28 days ago
[-]
reply
matheusmoreira
27 days ago
[-]
> the real issues of the language

> irrelevant or not-well-thought-out features

Looking for specific examples of these. The scoped finalization construct cited in a sibling comments is a great example of this. Are there more?

reply
upofadown
28 days ago
[-]
I think we can concede that there is a legitimate language fork here. I personally was not all that happy with the extent of the changes in 5.3. I would be just as happy at 5.1.
reply
bawolff
28 days ago
[-]
It seems like each version of lua is kind of a separate language.

Wikipedia is also sticking to lua 5.1 with no plans to change (they do not use luajit but normal lua)

reply
pansa2
28 days ago
[-]
> It seems like each version of lua is kind of a separate language.

In Lua's versioning scheme, each 0.1 increment is a new major version. That means Lua 5.1 => 5.2 => 5.3 => 5.4 is similar to Python 2 => 3 => 4 => 5.

reply
tristan957
28 days ago
[-]
I believe it is mostly still the case, but some features from newer Lua revisions have been added.
reply
Alifatisk
28 days ago
[-]
What's the deal with LuaJit? Why is it celebrated so much? I searched around a bit and they all talked about it being very fast, is that it? Performance?

Also, adding support for risc-v is good news, well done!

reply
haberman
28 days ago
[-]
LuaJIT completely upended my view of what a JIT compiler could be. I always thought that JVM-like overheads were inevitable for high-performing JIT compilers. When I saw how small and low-overhead LuaJIT is, I was blown away.

Here are some numbers:

Lines of code: OpenJDK HotSpot (1.4M), LuaJIT: (92k)

Binary size: OpenJDK HotSpot server/libjvm.so (24MB), LuaJIT: (576KB)

Time to run "Hello, World": OpenJDK HotSpot (64ms), LuaJIT (3ms) (the JVM has improved here, it used to take hundreds of milliseconds)

For me personally, LuaJIT's small size and low overheads set a new standard for what I expect from JIT compiled runtimes.

I also find its small code base makes it approachable to learn from. I won't say that reading the code is easy, but I at least have confidence that whenever I have a question about fast interpreters or JIT compiling techniques, I can find the relevant part of the LuaJIT code and study it. Larger code bases can feel so sprawling that it's hard to ever find the snippet of code that will answer a question.

reply
pjmlp
28 days ago
[-]
Comparing apples to oranges, given what Lua and Java offer in features.
reply
wavemode
28 days ago
[-]
It's widely regarded as a highly performant and very well-engineered runtime for a popular language. For a long time it was the go-to implementation you would reach for if you a) wanted lua scripting (common in game development) and b) wanted high performance.

I think nowadays though, the landscape has changed quite a bit since when luajit was at its peak of popularity.

a) Lua is not necessarily the language one would always choose for scripting, in the first place. There's lots and lots of scripting languages to choose from these days. (It's also increasingly common nowadays for indie gamedev to happen entirely within a game editor, like Unity or Unreal, which provide their own scripting systems. That fact alone has killed a lot of interest in lua.)

b) If you do want to use lua, the features of the official implementation have progressed a lot since v5.1 (which luajit is pinned to), and its performance has improved over the years.

c) There are other competing lua and lua-adjacent implementations to consider as well, like OpenResty's luajit2 or Roblox's Luau.

reply
wruza
28 days ago
[-]
b)

You don’t really need these features cause Luas 5.x are mostly rehashes of the ideas rather than successive versions.

The team should have frozen it at 5.1, backport everything useful (yield across * basically) from 5.2 and call it done, only fixing bugs and tuning performance. That’s essentially what LuaJIT did/does.

Instead the “upstream” has 4 versions of the same thing with ecosystem and codebases fragmented as a UK flag, for no good reason. LuaJIT fixes that by being awesome, but lives under the shadow of n+1 stereotype, despite being a true engineering project rather than a chain of experiments. Tbh I’m glad I left Lua world many years ago.

reply
synergy20
28 days ago
[-]
The integer and bitwise addition are pretty nice, lua5.2+ adds more complexity for luajit to upgrade and sync with, but for scripting I feel the new lua versions are great, still small, flexible and more powerful. other than games, lua is very important to embedded systems.
reply
wruza
28 days ago
[-]
Genuinely, what’s nice about integers and bitops? Lua always had integers: 1, 16, 42, -8. All you have to do is to floor division. Bitops and full 64-bit ops are so rare and fringe that a library would do (and it did).

for scripting I feel the new lua versions are great, still small, flexible and more powerful

It sounds so strange to me. Great in what? _ENV is the same setfenv() just in the other hand. Yielding across meta and C is nice, but should have been done in 5.1.6 regardless. __{pairs,ipairs} was just dancing around the same old tree as well. GC and interpreter improvements were independent of 5.x flavor and could be backported. Integers are pointless, sorry for the pun. 5.(n+1) may seem “more powerful”, but only because authors of Lua consciously leave 5.(n) undercooked. It’s adhd-rewrite-based development.

other than games, lua is very important to embedded systems

If you mean nodemcu, it stuck in 5.1 too. Everyone who did anything practical stuck in it, because they had shit to maintain. It’s very hard to explain to an innocent user why they have to periodically rewrite their scripts and bump fragile deps for this new “elle yu aeh” thing.

reply
synergy20
28 days ago
[-]
I use it for embedded boards, to run scripts and cgi, and sometimes do bitops too. based on what you described, it looks like someone should backport whatever makes sense and keep 5.1.x as a new language, and sync luajit with that? I have yet to use luajit.
reply
mardifoufs
28 days ago
[-]
I'm more familiar with luajit than Lua itself (as a project I mean). I'd be curious to know more about the fragmentation that vanilla Lua has. I know the issues that the luajit devs have with the features themselves but I wonder how and why those are decided and implemented. Is there an article or blog that goes into more details? Google isn't helping me here haha.
reply
wruza
28 days ago
[-]
It’s from a simple fact that there are rocks that were not maintained seriously (as in “business”), and there are big embedders that work as version anchors. As a result, rocks were full of 5.?-specific at the times of 5.2/3, cause people have no time nor desire to reimplement things. Idk how it is now, but my bet is on nothing changed, some popular libs became multi-headed. Lua-http doesn’t even list 5.4 as a target. Maybe 5.4=5.3, can’t remember. But if daurnimator decided to ignore it, oh my.

As of motivation, I guess the best source is their mailing list around release dates. It was hot every time. Idk if anyone blogged about it, maybe just ask there.

reply
daurnimator
27 days ago
[-]
reply
wruza
27 days ago
[-]
Ah, visited this first, sorry for the noise https://daurnimator.github.io/lua-http/0.4/
reply
nxobject
27 days ago
[-]
Re (b) – yes, 5.4's VM introduces a generational garbage collector and special-case instructions for numeric types which consistently improve performance, at least even in the general-purpose programs that I run (gamedev and the VM as a compilation target.)

That being said, I use Lua on an architecture that LuaJIT doesn't support anyway – 68k.

reply
anonymoushn
28 days ago
[-]
openresty/luajit2 is a small number of extensions. Picking or not picking it won't make a huge difference. It's interesting that Roblox has become interested in making Luau usable outside of Roblox and shipped appropriate changes and docs for this in the last few years.
reply
wsc981
28 days ago
[-]
It's used in LÖVE [0] (and LÖVR [1] as well, I think) for this very reason. The Lua code for a game will be quite performant.

---

[0]: https://love2d.org

[1]: https://lovr.org

reply
3eb7988a1663
28 days ago
[-]
Also NeoVIM
reply
pansa2
28 days ago
[-]
> is that it? Performance?

Performance, size and compatibility. It's essentially a drop-in replacement for the stock Lua 5.1 implementation, with the same small size but with much higher performance. About the only downside compared to stock Lua 5.1 is that it's less portable.

However, development of LuaJIT almost stopped ~10 years ago, and only seems to be picking up again recently. In terms of the language it hasn't kept up with all the changes in Lua 5.2, let alone 5.3 or 5.4. And in terms of implementation, its performance is still impressive but no longer best-in-class compared to other dynamic-language JITs (e.g. for JavaScript).

reply
CyberDildonics
28 days ago
[-]
Where are you seeing benchmarks that javascript can beat luajit?
reply
pansa2
28 days ago
[-]
Here, for example: https://www.quora.com/Is-LuaJIT-still-faster-than-JavaScript...

LuaJIT's speed is very impressive, but the optimizations it can use are limited by its desire to remain lightweight.

It's understandable that JavaScript implementations, which don't have that restriction, can use different techniques and work out faster overall.

reply
imtringued
27 days ago
[-]
I would like to say that something that doesn't get used, doesn't work out faster overall.
reply
pansa2
27 days ago
[-]
> something that doesn't get used

Sorry, you've lost me. What doesn't get used?

reply
sroussey
28 days ago
[-]
It’s small size and fast performance means it can be implemented in a webserver (OpenResty’s luajit2.1) where you can write code that would tap into the TLS handshake and write a custom implementation (like connecting to a database of certificates because you serve 10s of millions of domains).
reply
matheusmoreira
28 days ago
[-]
Yes, performance. It got to the point that there are languages out there that compile to Lua or LuaJIT VM bytecode directly just to take advantage of the LuaJIT implementation. Apparently it's so good it spawned a separate language when the people at PUC-Rio started taking Lua in a direction that LuaJIT didn't want to follow.
reply
edflsafoiewq
28 days ago
[-]
It's also tiny (like half a meg compiled) and has some nice extensions, like one of the best FFIs in any language.
reply