Commit 8e11cb3f authored by Giovanni Bajo's avatar Giovanni Bajo Committed by Austin Clements

runtime: improve comments for nextSample

The previous comment of nextSample didn't mention Poisson processes,
which is the reason why it needed to create an exponential
distribution, so it was hard to follow the reasoning for people
not highly familiar with statistics.

Since we're at it, we also make it clear that we are just creating
a random number with exponential distribution by moving the
bulk of the function into a new fastexprand().

No functional changes.

Change-Id: I9c275e87edb3418ee0974257af64c73465028ad7
Reviewed-on: https://go-review.googlesource.com/65657Reviewed-by: default avatarAustin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent 3f04db41
...@@ -865,11 +865,13 @@ func profilealloc(mp *m, x unsafe.Pointer, size uintptr) { ...@@ -865,11 +865,13 @@ func profilealloc(mp *m, x unsafe.Pointer, size uintptr) {
mProf_Malloc(x, size) mProf_Malloc(x, size)
} }
// nextSample returns the next sampling point for heap profiling. // nextSample returns the next sampling point for heap profiling. The goal is
// It produces a random variable with a geometric distribution and // to sample allocations on average every MemProfileRate bytes, but with a
// mean MemProfileRate. This is done by generating a uniformly // completely random distribution over the allocation timeline; this
// distributed random number and applying the cumulative distribution // corresponds to a Poisson process with parameter MemProfileRate. In Poisson
// function for an exponential. // processes, the distance between two samples follows the exponential
// distribution (exp(MemProfileRate)), so the best return value is a random
// number taken from an exponential distribution whose mean is MemProfileRate.
func nextSample() int32 { func nextSample() int32 {
if GOOS == "plan9" { if GOOS == "plan9" {
// Plan 9 doesn't support floating point in note handler. // Plan 9 doesn't support floating point in note handler.
...@@ -878,25 +880,29 @@ func nextSample() int32 { ...@@ -878,25 +880,29 @@ func nextSample() int32 {
} }
} }
period := MemProfileRate return fastexprand(MemProfileRate)
}
// make nextSample not overflow. Maximum possible step is // fastexprand returns a random number from an exponential distribution with
// -ln(1/(1<<kRandomBitCount)) * period, approximately 20 * period. // the specified mean.
func fastexprand(mean int) int32 {
// Avoid overflow. Maximum possible step is
// -ln(1/(1<<randomBitCount)) * mean, approximately 20 * mean.
switch { switch {
case period > 0x7000000: case mean > 0x7000000:
period = 0x7000000 mean = 0x7000000
case period == 0: case mean == 0:
return 0 return 0
} }
// Let m be the sample rate, // Take a random sample of the exponential distribution exp(-mean*x).
// the probability distribution function is m*exp(-mx), so the CDF is // The probability distribution function is mean*exp(-mean*x), so the CDF is
// p = 1 - exp(-mx), so // p = 1 - exp(-mean*x), so
// q = 1 - p == exp(-mx) // q = 1 - p == exp(-mean*x)
// log_e(q) = -mx // log_e(q) = -mean*x
// -log_e(q)/m = x // -log_e(q)/mean = x
// x = -log_e(q) * period // x = -log_e(q) * mean
// x = log_2(q) * (-log_e(2)) * period ; Using log_2 for efficiency // x = log_2(q) * (-log_e(2)) * mean ; Using log_2 for efficiency
const randomBitCount = 26 const randomBitCount = 26
q := fastrand()%(1<<randomBitCount) + 1 q := fastrand()%(1<<randomBitCount) + 1
qlog := fastlog2(float64(q)) - randomBitCount qlog := fastlog2(float64(q)) - randomBitCount
...@@ -904,7 +910,7 @@ func nextSample() int32 { ...@@ -904,7 +910,7 @@ func nextSample() int32 {
qlog = 0 qlog = 0
} }
const minusLog2 = -0.6931471805599453 // -ln(2) const minusLog2 = -0.6931471805599453 // -ln(2)
return int32(qlog*(minusLog2*float64(period))) + 1 return int32(qlog*(minusLog2*float64(mean))) + 1
} }
// nextSampleNoFP is similar to nextSample, but uses older, // nextSampleNoFP is similar to nextSample, but uses older,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment