Skip to content

runtime/pprof: "bytes" tag value may fluctuate between runs as it's computed off unsampled values #26638

@aalexand

Description

@aalexand
$ go version
go version go1.10.3 linux/amd64

See a test program and test output below. The block size allocated by the program is 32768 bytes, but the profiles contain values like 32778, 32885 and 32868. This is not quite expected - I would expect to see as the block size the exact block size I know I am allocating in the program. Looking at how the legacy profiles are handled in github.com/google/pprof (which come in sampled, so pprof has to unsample them), it looks like the block size is computed prior to unsampling the values, see https://github.com/google/pprof/blob/403a828189bee34b4b9fea51ece1af8400ccef30/profile/legacy_profile.go#L606 and https://github.com/google/pprof/blob/403a828189bee34b4b9fea51ece1af8400ccef30/profile/legacy_java_profile.go#L218.

So it looks like

blockSize = values[1] / values[0]
needs to be fixed to compute the block size before unsampling.

$ go test -v -memprofile mprof.out mprof_blocksize_test.go && pprof -alloc_space -tags -unit=bytes mprof.out
=== RUN   TestMprof_1
total allocated: 0.015 GiB
--- PASS: TestMprof_1 (0.00s)
PASS
ok      command-line-arguments  0.008s
 bytes: Total 8653482.0B
        8653482.0B (  100%): 32778B

$ go test -v -memprofile mprof.out mprof_blocksize_test.go && pprof -alloc_space -tags -unit=bytes mprof.out
=== RUN   TestMprof_1
total allocated: 0.015 GiB
--- PASS: TestMprof_1 (0.00s)
PASS
ok      command-line-arguments  0.007s
 bytes: Total 11357695.0B
        11357695.0B (  100%): 32825B

$ go test -v -memprofile mprof.out mprof_blocksize_test.go && pprof -alloc_space -tags -unit=bytes mprof.out
=== RUN   TestMprof_1
total allocated: 0.015 GiB
--- PASS: TestMprof_1 (0.00s)
PASS
ok      command-line-arguments  0.008s
 bytes: Total 5949269.0B
        5949269.0B (  100%): 32868B
package main

import (
        "fmt"
        "testing"
)

func alloc(iter, size int) int {
        var a []byte
        for i := 0; i < iter; i++ {
                a = make([]byte, size)
        }
        return len(a) * iter
}

func TestMprof_1(t *testing.T) {
        fmt.Printf("total allocated: %.3f GiB\n", float64(alloc(500, 32768))/(1<<30))
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions