3 ms·
The reason that Go can't handle dynamic library dependencies, for the most part, isn't a strength--it's a weakness. I guarantee you that if it could call out t
by Jweb_Guru 12y ago
The reason that Go can't handle dynamic library dependencies, for the most part, isn't a strength--it's a weakness. I guarantee you that if it could call out to C efficiently, it would. Part of the price it pays for its goroutines is that its relocatable stacks do not play nicely with C calling conventions, meaning it can be extremely expensive to call out to a C routine. For that reason, Go essentially reimplements libc in its own standard library. All the other languages you named don't do that, because they don't have to.
Anyway, Go can't produce dynamically linked libraries yet even for Go applications. It really has no choice but to bundle them into one application.
- frik 12y agoGo's goroutines as I understand are the same or very similar to Lua's coroutines and WinAPI's Fibers. Right? For the later two can calling C functions is cheap. I would assume if you run Go with its default one thread option, it's cheap too. (Switching threads or even processes means context switching is what is usually expensive).
- unassuming_rat 12y agoNo, Go routines are not the same as coroutines in other languages. In order to provide efficient lightweight threads, Go allocates only a small amount of memory for each stack, growing it as function calls require it by appending another segment in a linked list. This makes thread creation very cheap. The problem with segmented stacks is that they can cause "stack thrashing." Suppose a goroutine is right at the boundary between two stacks. It calls a function that exhausts the available segment, forcing the allocation of a new segment, which is then added to the linked list. The function runs, and then frees the segment upon return. If this boundary happens to fall within a tight loop, you'll see a severe drop in performance, to the point that it's completely unacceptable. Recognizing this, Go relatively recently switched away from segmented stacks. It now uses a strategy called relocatable stacks, or contiguous stacks. See https://docs.google.com/document/d/1wAaf1rYoM4S4gtnPh0zOlGzWtrZFQ5suE8qr2sD8uWQ/pub https://docs.google.com/document/d/1wAaf1rYoM4S4gtnPh0zOlGzW... for details. Similar concerns prompted Rust to move away from segmented stacks, but as relocatable stacks require a garbage collector that was not a viable way forward for Rust, so it just dropped the idea completely. The problem with both approaches is that C has no knowledge or support of either segmented or relocatable stacks. This means that calling out to C in Go involves a completely different calling convention that involves switching to a larger stack, running there, and then switching back--which is very expensive, especially compared to languages like Lua where the C FFI is basically free. That's why Go reimplements glibc by performing its own system calls--to avoid the C FFI. In conclusion, every language feature--no matter how enticing--has a cost.
- deleted 12y ago[deleted]
- andmarios 12y agoI agree that this limits Go's use scope. But when you accept that Go is most suited for web apps and some console tools, it is nice and works well for the users and the application packager. The only package manager (pm) I like, is the pm of the distro I am using. If I am on Fedora, I like yum. When I am on Gentoo I like portage etc. The problem with most web apps is that they have dependencies that don't exist in your distro's pm. I'll take a static binary over a 3rd party pm any day. Let's not forget that one of the most important reasons for the existence of docker is to not have to set up an app in many different systems.