Using C(++) in a Go application for performance

丶灬走出姿态 提交于 2019-12-09 10:01:58

问题


I've started studying Go a couple of days ago and came by its CGO thing and the gccgo compiler. From my understanding this allows a Go program to compile using the Go compiler and compile C libraries using a C compiler and reference those libraries from inside a Go program. This is really interesting to me because this allows us to leverage C's performance (if needed) from our main program with little overhead.

However I'm not sure how little that is, so I'm asking here:

Are there cases where you would create a C library just to use it from inside your Go application? Or is this feature only to facilitate re-usability of existing C code?

P.S: I think at the moment CGO doesn't support C++ but there was a post here of someone that was able to wrap C++ code using C functions and call them successfully.


回答1:


Cgo is fairly slow, because Go has to mess with its runtime and calling conventions in certain ways to call C functions. The only place it's really worth it is cases where the compute time significantly dwarfs this cost. It's similar to parallel, distributed, GPU and so on programming, albeit with slightly lower startup costs.

Assembly is much better, because you can write assembly that uses Go's calling convention, and is otherwise treated like native Go code, but assembly is far less portable, harder to read, and more maintenance heavy. In fact, the Go standard library writes some of the math and big packages in Plan 9-style assembly.

Gonum is an example of both of these. It uses common assembly for some functions that can be done more quickly that way, but it also leverages blas and lapack engines. It does provide a Go-blas implementation, but C-blas (which is usually ultimately Fortran-blas) is faster, and for large matrix computations almost always dwarfs the cost of leaving Go.

Generally, you want to avoid cgo when possible. Only use it when significant computation time is needed, or you need to interact with things that would be non-trivial to interact with in pure Go, such as graphics or audio drivers, or accessing common libraries like OpenCV. Even then, if you really care about performance, where possible it may be worth it to implement some sort of "call pooling" where you can schedule multiple calls from the Go side and execute them all at once with a single context switch to C.

Edit: As for C++, there are some significant issues. It can be difficult to wrap certain libraries without several layers of abstraction (since cgo cannot handle included C++ headers properly). In addition, C++ classes with destructors can't really be returned by value and have to be allocated on the heap. Since Go doesn't allow for deterministic finalization of resources, you must provide a function to explicitly free memory, and the Go user must remember to free the resource. (There is a function you may read about in the documentation called runtime.SetFinalizer but I can't say I've ever seen anyone use it, and the documentation itself comes with a bunch of caveats)

Functionality such as defer makes this more manageable, but it ruins a lot of things like RAII which make modern C++ practices safer.




回答2:


Unless a C library does a lot of work in one call I wouldn't write C code just for performance. I consider cgo to only be for interfacing with old code.

The reason is the cgo overhead. Currently function calls into cgo functions are between 50 and 100 times slower than function calls to Go code. The overhead of cgo function calls is shocking.



来源:https://stackoverflow.com/questions/37960425/using-c-in-a-golang-application-for-performance

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!