Remix.run Logo
qcnguy 4 days ago

Kubernetes services are one of the places where you don't care about startup time. Likewise for Docker itself. These are the things that do the scaling, normally.

Go is not particularly fast. People often see that Java gets faster as it runs and thinks, oh, it must be slow at the start then. But when you compare like with like, Go ends up being stuck at the bottom of the curve that Java then sharply climbs. The difference in GC quality is big, or at least, used to be? The only place where you really notice the difference is command line tools, and Java has GraalVM for that.

tsimionescu 4 days ago | parent | next [-]

> Kubernetes services are one of the places where you don't care about startup time.

There are some kubernetes services that scale up and down. And even for those that don't normally, if they have some kind of failure, the difference between taking a millisecond to get back up and taking a second can actually matter for a web host.

> Go is not particularly fast. People often see that Java gets faster as it runs and thinks, oh, it must be slow at the start then. But when you compare like with like, Go ends up being stuck at the bottom of the curve that Java then sharply climbs.

Go starts up much faster than Java. And Go code runs measurably faster than interpreted Java code, even though it's slower than the JITed code you'll eventually have if your JVM runs long enpigh. But un-JITed Java code is very slow, more comparable to Python than JITed Java or with Go . This has nothing to do with the GC - where I do agree Go is mediocre at best.

zozbot234 4 days ago | parent [-]

I wouldn't call the Go GC mediocre, it's one of the few fully concurrent GC's in common use. It probably has significantly lower memory demand than Java/NET for comparable workloads.

tsimionescu 3 days ago | parent | next [-]

Go's GC is not compacting, it has significant mutator overhead on every pointer write, it has an expensive allocator (it has to search through free lists, since it can't compact), and the free pahse has to do work proportional to the amount of garbage the program produces. It also produces no debugging information for ownership, for some bizarre reason (you can't tell from a Go heap dump with any standard Go tool which object is keeping another object around).

The fact that it can do this mostly concurrently (it's not fully concurrent, actually) is not that special - Java's latest GC is also mostly concurrent, without having any of the other previous drawbacks.

Go's big advantage in terms of memory management is that it doesn't produce as much garbage as most GC languages. The fact that it natively supports value types, and actually uses them extensively in the standard library (unlike C#, which also supports these), and it's excellent stack escape analysis which allows many allocations to stay on the stack and outside the GC heap entirely, is what makes Go have such little memory overhead.

pebal 4 days ago | parent | prev [-]

This isn't fully concurrent GC. It pauses mutators threads and delegates them to perform some of the work for the GC.

atombender 4 days ago | parent | prev [-]

When using HPAs to quickly ramp replica sets up and down based on load, startup time is absolutely an important factor. You want services to start within hundreds of milliseconds at most.