6 ms·
This was posted before and I still have no idea what the rationale is. No desktop PC or game console is RISC-V, so if I'm going to all the trouble to use a scri
by dataangel 3y ago
This was posted before and I still have no idea what the rationale is. No desktop PC or game console is RISC-V, so if I'm going to all the trouble to use a scripting solution that requires me to compile my scripts to machine language, why would I target RISC-V? Why wouldn't I just compile to x86-64 directly?
Like, what is the vision here, a LuaJIT that targets RISC-V, running inside my x86-64 game, where the emulator translates the RISC-V back into x86-64... for reasons? Just isolation?
- nagisa 3y agoThe answer lies in the reason why you would use an embedded scripting language/environment at all, over just loading native code plugins – sandboxing, fault isolation and such. RISC-V seems to be used here more as a bytecode format of sorts, and at least compared to x86_64 it should be much easier to implement (first of all because all of the opcodes have the same size.)
- MobiusHorizons 3y agoI mean sure, but virtualization is a very robust (and much lower overhead) technology that is readily available (and supported by the processor). If you just want isolation, why wouldn't you use that? You still have to ship a compiled binary after all.
- eru 3y agoIf you just want to run some CPU bound code as fast as possible, virtualisation has low overhead. But if you are doing a lot of communication between the script and the host system, I'm not sure virtualisation does so well?
- fwsgonzo 3y agoNo, as the author of TinyKVM, the overheads of entering and leaving KVM is not the same order of magnitude as SFI. TinyKVM requires 2-3 microseconds to enter and leave, which is the lowest I ever managed to get while it still being robust and dependable sandbox. For some, that might seem really low, but keep in mind that libriscv which is the backbone of RVScript has 3 nanoseconds overhead.
- eru 3y agoThanks!
- yjftsjthsd-h 3y agoUsing a sandboxed bytecode VM has merit, but I would naively expect wasm to be far better at it since RISC-V was designed for hardware and wasm was designed for exactly this usecase (sandboxed code running in another application with good performance and isolation). (Although... I do see value in having a second option. I guess it might be worth seeing if it can actually be better, even though it's not the thing I would have written)
- fwsgonzo 3y agoThe sandbox is interpreting RISC-V, just very quickly. It's platform independent. I am actually making a game with a derivative of this repo, and in the server I am building the programs at the same time as the server. Once the server starts, it loads all the programs, and then sends compressed programs to each client, so that everyone who connects has the same scripts. Easy and convenient, but most likely just that because I did it from the start.
- speps 3y agoThis is an interesting concept, getting the gameplay logic sent to the client this way. I guess it only works for simpler games so far, do you have any code examples?
- fwsgonzo 3y agoThe game is quite complex actually, but the script is not doing overmuch right now. The script is doing things that makes sense for a growing modding API, while the engine still does the brunt of the work. That said, there are functions that end up being called billions of times simply because you want that flexibility, and that's where the low latency script pays off.
- adastra22 3y agoOk… so why not send llvm bytecode? Or JVM? Or JavaScript? Or WebAssembly? Any of those would be better supported and have a faster, battle tested JIT engine.
- deleted 3y ago[deleted]
- mort96 3y agoMan it's so frustrating as an author to explain you you didn't just use existing technology X in the linked article but then be met by a flood of HN comments from people asking "but why didn't you just use existing technology X?"
- saagarjha 3y agoYeah, it seems like WASM would be a better choice?
- MaxBarraclough 3y agoOr transpiling to C/C++, like Nim.
- h0l0cube 3y agoRationale from the README: > Lua, Luau and even LuaJIT have fairly substantial overheads when making function calls into the script, especially when many arguments are involved. The same is true for WebAssembly emulators that I have measured, eg. wasmtime.
- doctorpangloss 3y ago> ...for reasons? Yes. When something's intellectually stimulating you work on it more, that's it. Most game development is a grind. These huge distractions, like a scripting backend, well if you spend 100h working on the scripting engine only to spend 1h authoring actual scripts, you still spent 1h authoring scripts those 2 weeks instead of 0h. The game gets delivered sooner even if you spend 10x as long working on it. It's a quintessential misunderstanding about indie game development. HN readers think Jonathan Blow is wasting his time writing a whole new programming language and engine, and that's why his games take 6 years to make. No: his games would take 20 years to make if they weren't intellectually engaging to make. They wouldn't be made at all! It's the same energy as rewriting everything in another programming language. I think this happens at giant companies too, all the time. So called Not Invented Here syndrome: it's as much about laundering open source code as it is about keeping things interesting enough to make the extreme boredom and grind worth it for otherwise smart and healthy people.
- zozbot234 3y agoRISC-V is quite fast as far as whole-platform emulation goes, but yes using it for plugin code is a bit weird, WASM would seem to be preferable for that use case. The interfacing story of WASM is not quite perfect (you're limited to a C-like baseline API/ABI, since the WASM components standards is not finished yet) but it's not like RISC-V is any better.
- snvzz 3y agoI wonder whether they've accounted for running it on actual RISC-V hardware. It could definitely still emulate itself, but it'd be far higher performing to run the code directly in some sort of sandbox.
- crq-yml 3y agoAt large scale, game engines have relatively unsatisfying answers to "what's the best way to iterate quickly on the game while supporting all the features we need". If the scope is small, the answer is easy: write some naive code, incrementally profile. The project isn't big so full rebuild times can stay light, and your team isn't large so you really can "do whatever" and get somewhere, especially if you take the route of writing in a native language that compiles fast - a Pascal or something more "new and hip" like Beef. But when you are asked to do it on a AAA project you end up with every imaginable kind of feature: it needs to support a team of hundreds, it needs to be fast on console hardware, it needs to be straightforward to debug, it needs to support modding, it needs to be fast to iterate on, it needs to be flexible about the memory layouts of save data or assets. So you do end up in this kind of space where you're like, "we'll target a VM that is really low level, and that'll reduce the friction and granularity of switching between debug and release profiles, and that lets us stay in control of when we want to sandbox and when we want to go fast and we'll still be able to control every byte". That it happens to be RISC-V is not super relevant - it could be WASM or a custom bytecode like the Hashlink target in Haxe. It just needs to be a thing to compile to, that you can reasonably expect to implement and maintain. It's not the only approach that could be taken. Downscoping the ambition by 50% and hardcoding a little more of your spec is a good way to get through the technical stuff 10x faster.
- azakai 3y agoThe project explains that the reason is latency. It is indeed true that most VMs, including JavaScript, WebAssembly, the JVM, etc., have significant latency on the boundary. For example, many wasm VMs will install a signal handler, and that needs to be enabled/disabled on each entry/exit from the VM. But the latency can be fixed. You can sandbox WebAssembly without a signal handler, in particular (at the cost of a few % throughput overhead for bounds checks). I'm not sure if the author benchmarked that, but it should be very fast. (As for "why RISC-V" in the project, it looks like that's because it's easy to write an interpreter for, but it could have been any compiler target, it seems.)
- fwsgonzo 3y agoThere's also latencies for arguments into and out from the emulators. I'm not sure the custom signal handling alone can account for that. I agree that it could as well have been MIPS or ARM.
- sspiff 3y agoI think there are a couple of reasons for picking RISC-V over others. It is the youngest of the lot, meaning it is carrying around the least legacy compatibility stuff while still incorporating a lot of modern design lessons. Additionally, modern ARM and MIPS are not free and (potentially?) patent encumbered as well. You could go with some old, free MIPS or ARM, but then how good is performance, and how good is compiler support for these nowadays?
- azakai 3y agoThere is no reason I can think of why a Wasm interpreter would have higher overhead for arguments in and out. Maybe I'm missing something? Wasm was designed to have very fast calls, both internally and externally. That's why the basic types correspond directly to machine types. The goal is to have 0 overhead, except for sandboxing. Regarding sandboxing, there is the stack overflow check that happens in Wasm on each call. But you can disable that check if you don't want it. Btw, you can see that Wasm has no extra overhead on calls in a simple way: compile Wasm using wasm2c and inspect the C output. That C is what a Wasm VM would run. Some details: https://kripken.github.io/blog/wasm/2020/07/27/wasmboxc.html https://kripken.github.io/blog/wasm/2020/07/27/wasmboxc.html Note the section there about LTO: The Wasm can even be inlined into the code calling into it, which means there is zero call overhead. (But even without LTO, it's just another C function to call.)
- mort96 3y agoThe readme literally explains why the author doesn't want to use LuaJIT though?
- deleted 3y ago[deleted]