5 ms·
So why isn't C the baseline (and zig and rust being pretty close to it quite expected), but both luajit and julia are significantly faster??
by throw827474737 4y ago
So why isn't C the baseline (and zig and rust being pretty close to it quite expected), but both luajit and julia are significantly faster??
- gallexme 4y agohttps://nullprogram.com/blog/2018/05/27/ https://nullprogram.com/blog/2018/05/27/
- qalmakka 4y agoI'm always pretty surprised when I find out most people writing C or C++ have no idea that PLTs exist. They have a small but not negligible cost.
- eatonphil 4y ago> For the C “FFI” he used standard dynamic linking, not dlopen(). This distinction is important, since it really makes a difference in the benchmark. There’s a potential argument about whether or not this is a fair comparison to an actual FFI, but, regardless, it’s still interesting to measure
- arinlen 4y ago> There’s a potential argument about whether or not this is a fair comparison to an actual FFI, but, regardless, it’s still interesting to measure (...) If there's interest in measuring dynamic linking then wouldn't there be an interest in measuring it on all languages that support dynamic linking?
- jcelerier 4y agoWith clang, just compiling with -fno-plt gives me: jit: 1.003483 ns/call plt: 1.254158 ns/call ind: 1.254616 ns/call GCC does not seem to support it though, even if it accepts the flag and gives me: jit: 1.003483 ns/call plt: 1.502089 ns/call ind: 1.254616 ns/call (tried everything I could think of that would have a chance to make the PLT disappear: cc -fno-plt -Bsymbolic -fno-semantic-interposition -flto -std=c99 -Wall -Wextra -O3 -g3 -Wl,-z,relro,-z,now -o benchmark benchmark.c ./empty.so -ldl without any change on GCC)
- miohtama 4y agoIs there anything akin FFI but with static linking for any foreign (non C) language?
- junon 4y agoThe question as it stands makes a few assumptions I don't think one can make, and as such is a bit tricky to answer cleanly, but I'll try. Yes it's just called linking. The language needs to be aware of calling conventions and perhaps side effects and be prepared for no additional intrinsic support for higher level features. It probably also needs to be able to read C headers, because C symbols do not contain type signatures like many C++ compilers add. There's no "library" or some out of the box solution for this, if that's what you're asking. This boils down to how programs are constructed and, moreso, how CPUs work. In most (all?) cases, anything higher level than straight-up linking is headed toward FFI territory.
- tlb 4y agoCalling WebAssembly from Javascript, sort of? In the early Python 2 era there was an option to build an interpreter binary with statically linked C stubs, and it was noticeably faster and let you access Python data structures from C. I used it for robotics code for speed. It was inconvenient because you had to link in all the modules you needed.
- samatman 4y agoLuaJIT can use the FFI against statically linked object code just fine, I'm not sure if that answers your question since in this context it must be embedded in a C program. It's a hard requirement of static linking that you have just one binary so it might, answer your question that is.
- fweimer 4y agoFor OpenJDK, there is JEP 178: https://openjdk.java.net/jeps/178 https://openjdk.java.net/jeps/178 I haven't seen it used in practice. Ocaml's C-implemented functions are linked statically. But like JNI, the C functions have special names and type signatures, so it is slightly different from, say, ctypes in Python. CGO for Go is statically linked, too. Its overhead stems from significant differences between the Go and C world. The example uses dynamic linking, but it would not have to do that.
- deleted 4y ago[deleted]
- bachmeier 4y agoC, C++, Zig, Rust, D, and Haskell are all similar because they're basically doing the same thing. Someone else linked to the blog post, but Lua and Julia aren't doing the same thing, so they get different results. > both luajit and julia are significantly faster I would be interested if anyone has an example where the difference matters in practice. As soon as you move to the more realistic scenario where you're writing a program that does something other than what is measured by these benchmarks, that's not going to be your biggest concern.
- vvanders 4y agoOh it totally matters, any sort of chatty interface over FFI you will pay for it. There's a reason a lot of gamedev uses luajit, I've personally had to refactor many interfaces to avoid JNI calls as much as possible as there was significant overhead(both in the call and from the VM not being able to optimize around it).
- kllrnohj 4y agoThe reason a lot of gamedev uses luajit is the ease at which it can be embedded. And that's not really even true anymore as the majority of gamedev is using Unreal or Unity, neither of which use luajit.
- vvanders 4y agoIt's not just how easy it is to embed, it's also really small in both code + runtime size. I've shipped it on systems with sub 8mb of total system memory(we used a preallocated 400kb block), until quickjs came along there really wasn't anything comparable. It was also much faster than anything else at the time and regularly beat v8 in the benchmarks I ran. Unity+Unreal are the public engines out there but there's plenty of in-house engines and tool chains you don't really hear about. I wouldn't be surprised if it's still deployed in quite a few contexts.
- kllrnohj 4y ago> I would be interested if anyone has an example where the difference matters in practice. Vulkan. Any sort of binding to Vulkan over a non-trivial FFI (so like, not from C++, Rust, etc...) is going to be murdered by this FFI overhead cost. Especially since for bindings from something like Java you're either paying FFI on every field set on a struct, or you're paying non-trivial marshalling costs to convert from a Java class to a C struct to then finally call the corresponding Vulkan function.