
Sub-millisecond GC pauses in Go 1.8 - geodel
https://groups.google.com/forum/?fromgroups#!topic/golang-dev/Ab1sFeoZg_8
======
enneff
The proposal document for this change is a good read:
[https://github.com/golang/proposal/blob/master/design/17503-...](https://github.com/golang/proposal/blob/master/design/17503-eliminate-
rescan.md)

~~~
4ad
The canonical URL is: [https://golang.org/design/17503-eliminate-
rescan](https://golang.org/design/17503-eliminate-rescan)

------
gok
"typical worst-case"

So... not worst-case. :)

Regardless, very impressive achievement, especially given that they've been
able to do it without a JIT or exotic tricks like Azul.

~~~
dpark
Of course not. You can't put absolute worst case times on code in practice.
Worst case might be that someone managed to load 80PB of RAM on a CPU
underclocked to 50 MHz. Or that the OS suspended the process in the middle of
GC and was promptly frozen for a week while VMs were migrated across the
country in the cup holder of someone's Toyota.

Worst case in absolute time always requires ignoring pathological cases.

~~~
taeric
This feels very wrong to me. Qualifying it with some sort of analysis is fine.
Just saying "typical" is borderline negligent and is why nobody just uses
naive quicksort in production systems where runtime can actually matter.

~~~
klodolph
What's the alternative?

We don't care about worst-case latency in practice, and average case is often
ignored as well. We look at 99.9% latency numbers or things like that. Worst-
case is for people designing pacemakers or rockets, that's not what we are
doing here.

~~~
kuschku
> that's not what we are doing here.

Considering this code will likely be used in IoT, yes, this is what we’re
doing here.

~~~
grogenaut
Pretty sure web enabled cameras are NOT pacemakers NOR rockets... heck they
can't even put a different password on each device by printing on a sticker.

Nor is my sous vide machine or anything else I've seen as an IoT device. I
wouldn't call say my oscilliscope an IoT device even if it can connect to
wifi. It's a scientific device with cloud upload.

~~~
kuschku
You do realize pacemakers nowadays have WiFi and Bluetooth and run on the same
platform as other IoT devices?

There was an interesting talk at the Chaos Communications Congress a few years
back.

~~~
grogenaut
I'm well aware of this. I'm also aware that people are hacking these devices
left and right. But a cow is a mammal and a mammal isn't a cow.

Gp post was not talking about security we're talking about Real time
computing. If it's running on IoT hardware, eg rpi running linux, it's likely
not doing real time os stuff because linux isn't really a real time os.

And I still don't classify pacemakers as IoT. Just because you want to slap a
vague acyronym on any and every "connected" embedded device doesn't mean I
agree.

~~~
kuschku
But that's the thing, there's now a trial for implanted, smart, insulin pumps,
running on node.js, connecting to its app via WiFi.

That stuff is IoT in every definition of the word.

~~~
kpil
I know a few software developers that have diabetes, and they seem to be
reluctant to automatic pumps.

Monitoring might be fine, but installing something in the body that can kill
you and then running it on node.js doesn't seem like a good idea.

------
rayiner
Very impressive. I wonder how Go manages to even stop all threads in 100
microseconds, much less do any work in that time.

~~~
johncolanduoni
Other systems I'm aware of that are capable of similar feats (I know .NET's
collector can, not sure about Hotspot's) use page poisoning. Basically the
compiler/JIT puts a bunch of extraneous memory accesses to a known address at
key points where the GC can track what all variables and registers hold
(called "safepoints"), in a fairly liberal pattern around the code. When the
GC wants to stop all the threads in their tracks, it unmaps the page holding
that address, causing segfaults in every thread it it hits one of the
safepoints. The GC hooks the segfault handler, and simply waits for all
threads to stop.

I'm not sure that's what Go does, but I'm not aware of a faster way on
standard hardware.

~~~
pcwalton
That's basically what Go does; it folds the preemption points into the stack
checks during function prologs.

~~~
menzoic
Where did you learn that? (curious to learn more)

~~~
ci5er
I haven't seen it written up, but it's discussed some here:

    
    
      - https://github.com/golang/go/issues/10958

------
morecoffee
I like faster latency as much as the next person, but these improvements
aren't free. On my own servers I notice approximately 20% of CPU time spent in
GC.

~~~
jemfinch
I'm a C++ programmer who hates garbage collection on general principle, but I
have to say: 20% of CPU time spent in memory management isn't all that unusual
(especially in software that hasn't been optimized), whether or not that
memory management is automatic garbage collection or manual.

~~~
jblow
It's not unusual _in completely terrible code_.

The difference is if the memory management is manual, you have the ability to
clean it up and reduce that overhead toward 0%.

If it's a system-enforced GC, you are limited in what you can do.

~~~
kasey_junk
In the code I write where it matters the issue is allocation & deallocation
time. Thus you don't do those things on the hot path in either gc'd or manual
memory management environments.

Given that the overhead become 0 in either.

Is it sometimes harder to write zero alloc code in GC'd languages? Sure but
its not impossible.

In Java for instance the difference in performance compared to C++ comes from
memory layout ability not memory management.

~~~
pjmlp
> In Java for instance the difference in performance compared to C++ comes
> from memory layout ability not memory management.

We need more modern languages with AOT compilation, ability to allocate on the
stack and use value types.

I like C++ and have spent quite a few years using it, before settling on
memory safe languages for my work.

Many C++ presentations seem to forget on purpose that there are memory safe
programming languages, which offer similar capabilities for controlling memory
layouts, thus presenting the language as the only capable of doing it.

Modula-3 is an example, or Swift and D for something more actual.

~~~
CyberDildonics
The reality is that there aren't any straight replacements though since C++
has such mature tools, move semantics take away significant amounts of memory
management pain, D without a gc is still exotic, and rust is still in its
early stages.

~~~
pjmlp
It is a matter of which market is relevant for a developer.

There are many use cases where C++ is still used where the use case at hand
actually didn't any a real need for it.

For example, on my area of work, C++ has been out of the picture since around
2006. We only use it when Java or .NET need an helping hand, which happens
very seldom.

On the mobile OSes for example, C++ is only relevant as possible language to
write portable code across platforms, but not so much for those that decide to
focus on just one.

There Swift, Java and C# are much better options.

For those in HPC, languages like Chapel and X10 are gaining adepts.

Also as an C++ early adopter (1993) I remember being told by C developers
something similar to what you are saying in regards to tool maturity.

Now around 30 years later, their compilers are written in C++.

~~~
CyberDildonics
I'm not trying to claim C++ is the only language anyone will ever need. I've
tried hard to find alternatives but until the D community really goes full
force on getting the garbage collection out and starts to care about the tools
for the language instead of just the language, it seems like rust will be the
only contender (and future C++ and maybe even jai). I wish a language called
clay had taken off, it was pretty well put together as a better C.

~~~
pjmlp
Actually I would rather like they would improve the GC to more modern
algorithms, instead of the basic one it uses.

------
psyc
If someone could do this for Unity, it would change my life.

~~~
pcwalton
.NET already has concurrent garbage collection:
[https://msdn.microsoft.com/library/ee787088(v=vs.110).aspx#b...](https://msdn.microsoft.com/library/ee787088\(v=vs.110\).aspx#background_garbage_collection)

See the "SustainedLowLatency" mode for something very similar to what Go does
(although .NET's GC, unlike Go's GC, is generational, which is a significant
difference).

~~~
squeaky-clean
Unfortunately, Unity still uses .NET 2, and their next planned upgraded (to
4.6) is still listed as an undetermined eta. That's good to know for the
future though.

~~~
ijk
They're beta-testing .NET 4.6 in Unity 5.5:
[https://forum.unity3d.com/threads/upgraded-mono-net-in-
edito...](https://forum.unity3d.com/threads/upgraded-mono-net-in-editor-
on-5-5-0b9.438359/)

------
yelnatz
Does anyone have any write ups for GC algorithm comparisons?

E.g. Java vs Go vs C# vs Actionscript vs Javascript?

------
mangeletti
Does this mean Go could be more suitable for robotics and drones now?

~~~
TheCrott
For IoT there's a package for that

------
bishop_mandible
Wow, makes me want to develop a AAA game in Go.

~~~
Narishma
What makes a game AAA is the resources (human and financial) that were used
making and marketing it, not the language used to write it.

~~~
pjmlp
And the culture.

AAA game developers only moved from Assembly to C, Pascal when forced to do
it.

A few years after they moved from C to C++ when the SDKs started to be C++
only.

Similarly they will only move from C++ when forced to do so, and they only
major complaint is related to build times.

I bet most are willing to wait until C++20 for modules than switching to
another language, even if some studios manage to have some hits developed in
safer languages.

~~~
zubat
Very good point here The outlook of gamedevs to new tooling tends to be
pessimistic because so little is actually geared towards what they work on, or
want to work on.

On the other hand, Web and mobile games have lived with the consequences of a
managed runtime for many years now. There are limits in how much processing
power is available there, but it ultimately just diverts developer attention
towards other things like a more robust backend, faster turnarounds, and other
general workflow improvements independent of scene fidelity.

------
jgalt212
Can one write an HFT application in Go now?

~~~
cheepin
If you are measuring response in nanoseconds, 100 microseconds is still a lot.

However, it may be good enough for games at well below 1% of your time budget
for a 60 fps game assuming cache locality is good enough so you don't waste
too much time fetching from main memory.

~~~
Matthias247
Besides games it would be interesting how good Go would now work for things
like low-latency audio processing (single-digit-millisecond-latency). That's
some kind of classic domain where performance is not a problem but once you
miss the target timeframe you are pretty fucked up (producing and hearing
glitches).

~~~
chillydawg
I write a fair amount of low latency code in go, but none of it is hard real
time. Average throughput of a few microseconds (for my simple workloads) with
spikes of milliseconds here and there is what I tend to find. Fine for a lot
of things but I'd be hesitant to use it for high fi audio apps that are very
sensitive to latency. Humans may only be able to notice 50ms, but if you're
chaining DSP you can end up with a fair bit of variance in your processing
pipeline.

------
bitmapbrother
.1 of a millisecond is very impressive. Does this mean Go can finally be
considered a systems programming language?

~~~
aikah
> .1 of a millisecond is very impressive. Does this mean Go can finally be
> considered a systems programming language?

Can you write an OS kernel in Go ? no Go's runtime still depends on a OS. And
whoever talked about Go as a system language didn't have kernels in mind, but
"network infrastructure".

~~~
Someone
Go needs a runtime, but it need not be a full OS; it could be a not too big
library that gets linked to a kernel written in go.

Similarly, can you write an OS kernel in ISO C? No, you still need some
assembly or runtime support. For example, ISO C doesn't have any notion of
making syscalls or returning from the kernel to a caller or for setting up
page tables.

Any argument why go isn't suitable for systems programming along these lines
should be about how much and what kind of runtime is acceptable for a systems
programming language.

A (fairly popular, I think, but certainly not universally agreed upon)
argument could be that systems programming languages cannot have garbage
collection because it should be possible to implement a garbage collector in
them, and doing that in a language that already has one is possible but silly.

~~~
4ad
Go's garbage collector is implemented in Go.

~~~
Someone
I can't find it in the documentation, but I would think that must be
_implemented in ProtoGo_ , where _ProtoGo_ is a Go-like language that doesn't
use Go's garbage collector or a library that does (Enforcing not using
anything that uses the garbage collector may be left to the programmer)

That is necessary even with a concurrent garbage collector because a garbage
collector that allocates in its own heap may hang itself (propaganda
allocates; gc triggered; gc allocates; gc triggered to satisfy the allocation;
new gc triggered; etc.) . Or do Go's developers accept this risk and live with
it?

~~~
4ad
> Enforcing not using anything that uses the garbage collector may be left to
> the programmer

It's left to the compiler actually. Programmers can't be trusted.

The runtime does not implicitly generate garbage (like arbitrary Go code). It
is compiled with a mode that fails compilation if something can't be stack-
allocated. When heap allocation is necessary, it is requested manually.
However, the memory returned is garbage collected, as usual, there is no free.

------
bitmapbrother
Brief synopsis:

Go 1.8 is moving to a hybrid write barrier in order to eliminate stack
rescanning. The hybrid write barrier is equivalent to the "double write
barrier" used in the adaptation of Metronome used in the IBM real-time Java
implementation.

Some benchmarks:

[https://github.com/golang/go/commit/bd640c882a8dcb88a0497770...](https://github.com/golang/go/commit/bd640c882a8dcb88a0497770f881bce48ab83102)

------
bluejekyll
If only there were generics, and no nulls, oh and strongly typed errors...
regardless, this is Very impressive.

~~~
polymathist
What about the way Go handles errors today makes them not "strongly typed"?

~~~
PeCaN
The compiler provides you no help at all with them, and no syntax that makes
error conditions and handling separate. It also mixes application logic and
recovery logic.

Basically everything that's problematic with returning a status int in C, but
all new, hip, and backed up by Rob Pike's pseudointellectual bullshit and a
bunch of Silicon Valley 20somethings.

They could at least, you know, have an Either type or something. Anything?

~~~
leaveyou
>It also mixes application logic and recovery logic.

When did this separation become law ? What if the "application logic" requires
recovery ?

>They could at least, you know, have an Either type or something

(int64, error) in func ParseInt() (int64, error) is your Either type. And
checking if you got the "left or the right side of the Either" is IMHO much
shorter and clearer than in Scala.

[https://golang.org/pkg/strconv/#ParseInt](https://golang.org/pkg/strconv/#ParseInt)

[http://www.scala-lang.org/api/rc2/scala/Either.html](http://www.scala-
lang.org/api/rc2/scala/Either.html)

>backed up by Rob Pike's pseudointellectual bullshit and a bunch of Silicon
Valley 20somethings

Why the ad hominems ?

~~~
premium-concern
_cringe_.

How ecactly is having to check twice the amount of cases an improvement (note
btw, that checking for Left/Right is doing it wrong)?

~~~
weberc2
You only have to check 1 case in Go (`if err != nil { ... }`). What language
lets you check half a case?

~~~
premium-concern

      (int64, error)
    

gives you exactly four possibilities.

Either gives you exactly the two you want.

~~~
weberc2
Please feel free to enumerate them.

~~~
premium-concern

      (value, no error)
      (value, error)
      (no value, error)
      (no value, no error)

~~~
leaveyou
The convention is that if the err == nil then the value is not nil. The
exceptions to this rule are very few and usually specified in the
documentation. Normally you only have to check for error.

~~~
bluejekyll
The fact that it's a convention, and not a compiler error is the entire issue
at debate here.

