4 ms·
So it's actually about the same situation in Go from what I can understand.
by aatd86 2y ago
So it's actually about the same situation in Go from what I can understand.
- neonsunset 2y agoNo, Go FFI is so slow it makes Python look fast which has great FFI performance, just being an interpreted language hurts. It needs to perform stack switching and worker thread pinning, and for some reason even that is slow. I don't know why. Note on tinygo as I've been put in the jail heh: Realistically no one runs TinyGo in production as in back-end workloads or larger user-facing applications. And when you do run it, at most you match pre-existing FFI performance of .NET which ranges at 0.5-2ns at throughput (which I assume how you are testing it) depending on flags and codegen around specific arguments. Up to 50 times difference with a standard Go, that is a lot, isn't it? All custom runtime flavours in Go usually come with significant performance issues or other tradeoffs. Something I never need to deal with when I solve the same problems with .NET, maybe occasionally addressing compatibility with AOT for libraries that have not been updated if it's a desired deployment mode.
- randomdata 2y ago> No, Go FFI is so slow it makes Python look fast Which Python and which Go? There are so many different implementations and different versions of those implementations that this broad statement is meaningless. From what I have installed on my machine, CPython 3.11.6 seems to take around 80ns to call a C function, gc 1.22.0 takes around 50ns to call the same C function, and tinygo 0.32.0 only takes around 1ns! Such benchmarking is always fraught with problems, so your milage may vary, but on my machine under this particular test Go wins in both cases, and tinygo is doing so at about the same speed as C itself.
- darby_nine 2y ago> CPython 3.11.6 seems to take around 80ns to call a C function, gc 1.22.0 takes around 50ns to call the same C function How does this make any sense? C shares a runtime with CPython. What is it doing where it manages to be slower than go?
- randomdata 2y agoI'm not familiar enough with the internals to say for sure, but I do know Python has a penchant for dicts. Perhaps it looks up the function each time, whereas Go can be made aware of the function at compile time? That wouldn't be without cost. Part and parcel with its love for dicts, Python data structures tend to not be shaped like C typically expects. Whereas Go data structures are, at most, lightweight wrappers around C-style structures, and are often even directly equivalent, making passing data about as simple as passing a pointer. Python may be getting bogged down in some kind of marshalling operation. That isn't cost-free either.
- aatd86 2y agoAre there some recent measurements? All I could find is somewhat old and I think there has been some work done since.
- gen2brain 2y agoMaybe it just looks slow to you, for example, check the raylib bindings benchmarks, Go is usually at the top, together with Rust, C#, etc. and Python is at the very bottom. Perhaps not the best way to benchmark FFI but it shows that Python is not even usable besides playing.
- jerf 2y agoIn Go, once you've FFI'd, you're likely to be able to use the Go data directly in C. In Python, you generally have to crawl over the Python-based data at Python speeds, converting it into data that your C library can understand, and then when C is done, convert it back into a Python data type at, again, effectively Python speeds. Unless you're willing for it to just be opaque data that Python effectively can route, but not manipulate. (This works, but is distinctly less useful. Of course sometimes, like for image data, it's the best option.) Combined with the sibling comment that actually times calls and finds Go is faster anyhow, even if it is a microbenchmark, I don't think your argument carries water. It sounds to me like you've latched on to some propaganda that you like and are happy to share but don't have any personal experience with. Go's FFI is relatively slow for a compiled language, but it isn't even remotely uniquely slow. Many languages have a C FFI with some sort of relatively expensive C conversion operation, and as I point out here, that actually includes Python in many, if not most, uses (it's pretty rare to want to write code to bind to C that just ships over two integers and returns another integer or something, usually we're doing something interesting). It is the languages like Rust or Zig that can do it for effectively free that are the exception, not the rule. Go's FFI costs are not all that expensive compared to programming languages in general, and if you're worried about the FFI performance, Go also generally needs FFI less in the first place than Python because it's a fast language (not the fastest by any means, but fast), and the higher proportion of Go code will generally smoke Python anyhow. Unless you foolishly write a very tight loop of C FFI code in Go, which is a bad idea in most langauges anyhow (again excepting the exceptions like Rust and Zig), Go's going to outpace a Python program that is mostly Python but uses a bit of FFI here and there by a lot anyhow. The idea that Go is brought to its knees by a single C call that takes 100ms or something reminds me of the people who think that as soon as you use a garbage collected language you've signed up for a guaranteed 250ms stop-the-world pause every three seconds or something. Is it free? No. Is it expensive? In relative terms maybe. In absolute terms, not really. Most programs, most of the time you won't notice, and if you are in a situation where Python is even a performance option virtually by definition you're in a situation where it won't be a problem for Go. This is not rah-rah for Go or slagging on Python. This is just stuff engineers need to know. Python is a very capable language, but you definitely pay for it. It is not free. Every greenfield project, you need to sit down and calculate the costs and pick a good tool, but you're going to make dumb, project-killing decisions if you're using costs that are multiple orders of magnitude off of reality. I've seen it kill projects, it's not just theory.
- kgeist 2y agoThe only significant conceptual difference between Go's and C#'s FFI mechanisms when it comes to call overhead that I can think of is the fact that Go has to switch the current stack to a special C stack. In C#, it runs on the same stack.
- deleted 2y ago[deleted]