I optimized the Go JSON serialization in Go 1.2. See https://code.google.com/p/go/source/detail?r=5a51d54e34bb ... it went from 30% to 500% faster. It uses much less stack space now, so the hot stack splits are no longer an issue (also Go defaults to 8KB stacks for new goroutines now).
Roughly: a GC has to look at the pointers in use to see what objects are still reachable. But it doesn't have to look at the contents of strings, byte slices, int arrays, etc., because, by definition, those don't contain pointers.
For dl.google.com, the first user of groupcache, it sounds like the Go runtime was working with relatively few, relatively large chunks of memory (think 2MB chunks of a Chrome binary). Since that doesn't have so many pointer-containing objects, just big chunks of inert data that don't need scanned, it's easyish. On the other hand, something like throwaway2424's case could be a GC stress test--many gigs of RAM holding a network of small, pointer-filled objects.
Really, the tl;dr may be to prototype/measure if you need to know how a GC will do. Assumptions are easy; data is hard.
Ahh got it. Also, the reason Brad specifically mentions big arrays of bytes/strings is that they don't look like pointers. Soo.... I'm guessing you still want to stay away from huge arrays of ints (or whatever type has the same size as pointers on your platform). Right ?
And as for measuring... it's not cheap (developer time wise) to build a realistic enough model of your application and put realistic enough loads on it for long periods of time to test out each of your hypotheses (and GC theories do require long periods of load). So you have to narrow the space of choices informed by past experiences and sometimes by gathering semi-reliable folk lore. I'm currently engaging in the latter activity :-)
++ablankst that byte isn't special here. Brad singled out byte/string because those are the types stored in groupcache (see ByteView in the groupcache code for his sneaky tricks to make them look the same to other code).
And yes, unfair to ask someone to test every guess they have. But if you do want to know a bit more about what effect GC and Go would have, experimenting with toy programs isn't a bad way to get a feel.
In Go, and other type-safe languages, the compiler usually knows exactly which ints are being used as pointers. This is the difference between "precise" and "conservative" GC and is one of the reasons that comparing GC performance in C++ to GC performance in other languages is difficult.
Atom also says 1.0's was more conservative, but, as Brad also said, still didn't scan "objects such as byte" (meaning all plain-old-data arrays? who knows). The Go 1.1 Release Notes mention the collector becoming more precise, which was a particular issue on 32-bit because big heaps could span a lot of the address space.
It wasn't a dig on nodejs. It was a dig at event-based programming, on which I've wasted years of my life in many languages. Node.js isn't unique in that regard.
As I mentioned in my talk, that code looks like fine Node.js code.
Websocket support doesn't matter. In Go, you can also just io.Copy(websocket, src).
Have you by any chance seen the async keyword in C# 5.0? It allows one to write event-based code without callbacks obscuring the control flow. From what I've heard Python is in the process of copying this feature. Iced Coffescrip does something similar also.
> I haven't yet tried Go, but I don't see how it could match the performance of C# API with a single function. C#'s async methods offload any IO to the process IO completion port threads, thus freeing the current thread to do more work.
Go generally uses synchronous functions, but a function in Go can be the subject of a "go" statement (sharing the name of the language should give an importance of how central this feature is), which causes the function to be executed as a goroutine (that is, asynchronously using an M:N threading model.)
I haven't yet tried Go, but I don't see how it could match the performance of C# API with a single function. C#'s async methods offload any IO to the process IO completion port threads, thus freeing the current thread to do more work.
Sorry, wasn't my intention. But it's only 4 more lines. In my defense, I only showed three pages of C++, and not all of it, which would've been longer than the whole presentation. So I cut less from the Go snippets than the C++ snippets.
Additionally, I think that this comparison would only be valid after the Go version experiences an equivalent amount of developer turnover, features added in a rush by developers inexperienced with the software, external infrastructure changes, and the other pressures that the C++ implementation was apparently subjected to over the years.
The Go code may look good in 2012 and 2013, while it's still fresh. But I'd be very curious to see how it looks in 2017 or 2018, assuming it's still even being used then.