3 ms·
From a systems perspective: Dealing with lots of communication and having lots of concurrency _where the concurrent actors are doing a lot of different stuff_
by dgacmu 13y ago
From a systems perspective: Dealing with lots of communication and having lots of concurrency _where the concurrent actors are doing a lot of different stuff_ is easier in Go.
Achieving high performance on a single machine and building reusable data structure libraries is easier in C++. Things like vectorization, cache-optimized layouts, etc., are all more easy here (or just in C).
- JulianMorrison 13y agoWhat were the general techniques you learned for optimizing Go?
- dgacmu 13y agoGood question. I'm not sure I have a great mental list that differs from the "go community conventional wisdom" (whatever that is), but it was basically: - Avoid creating garbage unnecessarily, but don't go too crazy. It's often enough to, e.g., statically size those things you know are static. We tried adding a structure cache to our RPC/marshaler to further reduce GC, but it didn't prove helpful and just complicated our interface. - Pre-size data structures when you can (maps, arrays): Reduces performance variation as they dynamically resize. - Be careful of using introspection for things like marshaling. It's easy to create a bottleneck. - Batching is just - or more - important as it is in C++. - When you're doing complex stuff, be deliberate with how you prioritize request handling (). More on (): We found it incredibly important for the performance of our system to prioritize processing of existing requests over processing new request arrivals - up to a point. Making progress on an existing request helps reduce the number of goroutines/objects/etc. that're processing, so that everything runs faster. But you don't want to go too far or you starve for work. The key here was to think about it instead of letting your design happen to you. The most important is already known: Profile, don't guess. The profiling Go article is a good start.
- eternalban 13y agohttp://blog.golang.org/profiling-go-programs http://blog.golang.org/profiling-go-programs Profile first, always.
- tomp 13y ago> building reusable data structure libraries > vectorization, cache-optimized layouts Could you explain a bit more about this features of C++? I believe that you're referring to templates for the first point, but I'm unsure about the rest - SIMD? stack-allocation/memory-pool-allocation?
- dgacmu 13y ago1) Templates 2) SIMD, but also auto-vectorization. gcc/g++ do an OK job of using SSE instructions when they can. If you have a loop like: for (int i = 0; i < 16; i++) { vec[i] *= 16; } gcc can sometimes emit SIMD code for you, without having to think about it. If you need to go farther, it's easy to use something like ispc to write vectorized code and link it into your program. It's more work to take advantage of hyper-optimized C from Go. Cache-optimized layouts: Not where it comes from, but things like forcing a structure to be aligned on a 64-byte (cache line) or 4096 (page) boundary, in order to, e.g., eliminate false sharing between threads. It's harder to micromanage the memory layout in Go while retaining its safety benefits and native datatypes. Finally, gcc havs more CPU-specific builtins such as __builtin_prefetch(), which let you have even more control over what data goes into what level of the cache (or doesn't).
- tomp 13y agoThanks! This helps a lot! I'm interested in compiler development, so this kind of information is really valuable for me... Do you think something similar was achievable in Go, if you had thing like vectors (i.e. fixed-length numerical arrays that would have math-like semantics, and which would compile to SIMD), prefetch attributes/instructions for heap-allocated variables, and memory-alignment attributes for structs or even for specific heap allocations?