3 ms·
I'm curious, what other reasons did you have to switch from Clojure to Go? I love coding in Clojure, so I wonder what would make someone "like me" switch.
by Synroc 12y ago
I'm curious, what other reasons did you have to switch from Clojure to Go? I love coding in Clojure, so I wonder what would make someone "like me" switch.
- stcredzero 12y agoWhen going for parallelism, it's helpful to be able to lay out what goes where in memory to avoid false sharing. This is quite hard to do in Clojure. The JVM has better GC, but Go also allows one to avoid GC. Also, to write fast code, I don't have to decompile bytecodes or do obscure things to make sure arithmetic is what I meant it to be. Int64 addition is int64 addition. Some things are definitely more powerful in Clojure. But that isn't where my priorities lie right now.
- pcwalton 12y ago> The JVM has better GC, but Go also allows one to avoid GC. I don't see that Go allows you to avoid GC any more than Java does, really. You can (and Java programmers do, with regularity) use things like sync.Pool in Java as well.
- vardump 12y agoGolang tends to need far fewer allocated objects than Java. You can allocate arrays (and slices) of struct in golang. Just one allocated object irregardless of how many items there are. In Java, you need array of objects and an instance of each object. Array of 100 objects needs 101 allocations in Java. So one could say golang avoided gc for those 100 objects it didn't need in the first place. In Java, you're otherwise limited to arrays of elementary types.
- pcwalton 12y ago> So one could say golang avoided gc for those 100 objects it didn't need in the first place. That's a reduction of the number of allocations, not of GC. In a generational copying GC like that of Java, the GC runs a minor collection when you've allocated enough bytes in the nursery to fill it up; it doesn't matter whether those bytes came from 1 object or from 101 objects. From reading Go's documentation [1] it's unclear whether its GC collection cycle is triggered based on the number of objects or whether it's triggered based on memory usage, but I assume the latter as that's how most GCs work. The pressure on the GC during the mark phase is based on the number of total pointers. You may be able to reduce the total number of pointers by packing pointer-free structs together, but I would be surprised if this helps mark performance that much in practice. The main way to really reduce GC pressure in a fully GC'd system, short of improving the GC itself, is to use pooling. Which both Java and Go programmers do regularly. [1]: http://golang.org/pkg/runtime/debug/#SetGCPercent http://golang.org/pkg/runtime/debug/#SetGCPercent
- Intermernet 12y agoHere's an explanation from Russ Cox (in the form of an SO answer) into how Go and Java differ in terms of object allocations and control of memory layout. http://stackoverflow.com/a/22214673/1567738 http://stackoverflow.com/a/22214673/1567738 I'm sure there's more info in the golang-dev group (https://groups.google.com/forum/#!forum/golang-dev https://groups.google.com/forum/#!forum/golang-dev) related to the GC specifics, but it's a moving target and may change substantially in the next few versions.
- stcredzero 12y agoThe main way to really reduce GC pressure in a fully GC'd system, short of improving the GC itself, is to use pooling. It occurs to me, that I don't understand how pooling helps a non generational GC like golang's. In a generational collector, the contents of the pool would be promoted to regions of GC memory that are copied less. Go's GC isn't generational, so what is going on?
- pcwalton 12y agoIf you use a pool, you can explicitly return memory to it without going through the GC. This causes mark/sweep cycles to occur less often. (Of course, using pools opens you up to use-after-free and memory leaks, albeit without the type- and memory-safety consequences of use-after-free in C/C++.)
- stcredzero 12y agoIf you use a pool, you can explicitly return memory to it without going through the GC. This causes mark/sweep cycles to occur less often. In a non-generational collector, why less often? Is it that the GC "sees" less garbage, and this figures into the frequency of mark/sweep cycles? EDIT: Okay, I just got it. If you assume it's a bump allocator, it's easiest to picture. So Go does have another big advantage with regards to reducing GC pressure, in that one can stack allocate structs and arrays. (One would be passing slices on those arrays most often, and stack allocated would be slightly less flexible, of course.)
- plam 12y agoI did a piece on using Clojure with Go recently. For me, it wasn't a switch but using them along side each other to tackle different problems more efficiently. Here's the link -- http://www.quantisan.com/simple-easy-quick-using-go-along-with-clojure http://www.quantisan.com/simple-easy-quick-using-go-along-wi...