rcrowley/go-metrics — pull request #14 by rcrowley (2013-08-12 14:03:45+00:00)
Title: Reduced lock contention in CaptureRuntimeMemStats and faster implementations of most of the metrics

Nick's experiment implied a different direction than I had been going (which is good because I was getting nowhere) and that led me to discover a busy lock-and-unlock pattern going on inside `CaptureRuntimeMemStats` which is the only thing he re-enabled when we once again observed failures. So first, this pull request rewrites the `runtime.MemStats` metrics and the `debug.GCStats` metrics to avoid lock contention by holding pointers to the metrics themselves. They're globals, which is of course fine because they actually are global.

This pull request also circles back to the metric implementations themselves and replaces the `arbiter` goroutine in `EWMA`, `ExpDecaySample`, `UniformSample`, and `Histogram` with locks. This proves to be both faster (an unexpected result; see enclosed benchmarks) and produces far fewer goroutines. It was especially important to me to replace the `arbiter` goroutine in `EWMA` because there are three of those with every `Meter`. `ExpDecaySample` and `UniformSample` are likewise used within `Histogram` so their replacement also reduces the goroutine count in an important way. I haven't found a way to remove the `arbiter` goroutine from `Meter` because it relies on a `time.Ticker` channel.