Skip to content

Commit

Permalink
grunning: add library for precise on-CPU time measurement
Browse files Browse the repository at this point in the history
Package grunning is a library that's able to retrieve on-CPU running
time for individual goroutines. It relies on using a patched Go and
provides a primitive for fine-grained CPU attribution and control
through a single API:

    package grunning

    // Time returns the time spent by the current goroutine in the
    // running state.
    func Time() time.Duration

The motivating RFC is over at cockroachdb#82356. Informs cockroachdb#82625.

We build CRDB using use the patched Go runtime for all officially
supported platforms when built using Bazel (cockroachdb#84867). Engineers commonly
building CRDB also use happen to use two platforms we don't use a
patched Go for:
- FreeBSD (we don't have cross-compilers setup), and
- M1/M2 Macs (we don't have a code-signing pipeline, yet).
We use '(darwin && arm64) || freebsd || !bazel' as the build tag to
exclude such platforms. See cockroachdb#84867 for more details.

This package tests various properties we should expect over the running time
value. It does not make assertions given the CI environments we run these
under (CPU-starved, lot of OS thread pre-emption, dissimilar to healthy
CRDB deployments). This is also why they're skipped under stress. Still,
these tests are useful to understand the properties we expect running
time to have:

    === RUN   TestEquivalentGoroutines
        thread=03 expected≈10.00% got= 9.98% of on-cpu time
        thread=06 expected≈10.00% got=10.00% of on-cpu time
        thread=02 expected≈10.00% got=10.01% of on-cpu time
        thread=10 expected≈10.00% got=10.01% of on-cpu time
        thread=07 expected≈10.00% got= 9.99% of on-cpu time
        thread=04 expected≈10.00% got= 9.99% of on-cpu time
        thread=09 expected≈10.00% got=10.00% of on-cpu time
        thread=01 expected≈10.00% got= 9.99% of on-cpu time
        thread=08 expected≈10.00% got=10.02% of on-cpu time
        thread=05 expected≈10.00% got=10.02% of on-cpu time
    --- PASS: TestEquivalentGoroutines (0.56s)

    === RUN   TestProportionalGoroutines
        thread=01 got  1.82% of on-cpu time: expected≈ 1.00x got=1.00x
        thread=02 got  3.64% of on-cpu time: expected≈ 2.00x got=2.00x
        thread=03 got  5.47% of on-cpu time: expected≈ 3.00x got=3.00x
        thread=04 got  7.28% of on-cpu time: expected≈ 4.00x got=4.00x
        thread=05 got  9.09% of on-cpu time: expected≈ 5.00x got=4.99x
        thread=06 got 10.91% of on-cpu time: expected≈ 6.00x got=5.99x
        thread=07 got 12.73% of on-cpu time: expected≈ 7.00x got=6.99x
        thread=08 got 14.54% of on-cpu time: expected≈ 8.00x got=7.99x
        thread=09 got 16.36% of on-cpu time: expected≈ 9.00x got=8.99x
        thread=10 got 18.16% of on-cpu time: expected≈10.00x got=9.97x
    --- PASS: TestProportionalGoroutines (1.72s)

    === RUN   TestPingPongHog
        pinger/ponger expected≈1.00x got=0.96x
    --- PASS: TestPingPongHog (0.91s)

Release note: None
  • Loading branch information
irfansharif committed Aug 12, 2022
1 parent 0ad97e4 commit 5b0982e
Show file tree
Hide file tree
Showing 8 changed files with 612 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@
/pkg/util/addr/ @cockroachdb/cli-prs @cockroachdb/obs-inf-prs
/pkg/util/metric/ @cockroachdb/obs-inf-prs
/pkg/util/stop/ @cockroachdb/kv-prs
/pkg/util/grunning/ @cockroachdb/kv-prs
/pkg/util/admission/ @cockroachdb/kv-prs
/pkg/util/tracing @cockroachdb/obs-inf-prs
/pkg/workload/ @cockroachdb/sql-experience-noreview
/pkg/obsservice/ @cockroachdb/obs-inf-prs
Expand Down
4 changes: 4 additions & 0 deletions pkg/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ ALL_TESTS = [
"//pkg/util/fuzzystrmatch:fuzzystrmatch_test",
"//pkg/util/goschedstats:goschedstats_test",
"//pkg/util/grpcutil:grpcutil_test",
"//pkg/util/grunning:grunning_test",
"//pkg/util/hlc:hlc_test",
"//pkg/util/httputil:httputil_test",
"//pkg/util/humanizeutil:humanizeutil_test",
Expand Down Expand Up @@ -1866,6 +1867,8 @@ GO_TARGETS = [
"//pkg/util/growstack:growstack",
"//pkg/util/grpcutil:grpcutil",
"//pkg/util/grpcutil:grpcutil_test",
"//pkg/util/grunning:grunning",
"//pkg/util/grunning:grunning_test",
"//pkg/util/hlc:hlc",
"//pkg/util/hlc:hlc_test",
"//pkg/util/httputil:httputil",
Expand Down Expand Up @@ -2821,6 +2824,7 @@ GET_X_DATA_TARGETS = [
"//pkg/util/goschedstats:get_x_data",
"//pkg/util/growstack:get_x_data",
"//pkg/util/grpcutil:get_x_data",
"//pkg/util/grunning:get_x_data",
"//pkg/util/hlc:get_x_data",
"//pkg/util/httputil:get_x_data",
"//pkg/util/humanizeutil:get_x_data",
Expand Down
284 changes: 284 additions & 0 deletions pkg/util/grunning/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
load("//build/bazelutil/unused_checker:unused.bzl", "get_x_data")
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "grunning",
srcs = [
"disabled.go",
"enabled.go",
"grunning.go",
],
importpath = "github.com/cockroachdb/cockroach/pkg/util/grunning",
visibility = ["//visibility:public"],
)

go_test(
name = "grunning_test",
srcs = [
"disabled_test.go",
"enabled_test.go",
],
deps = select({
"@io_bazel_rules_go//go/platform:aix_ppc64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:android_386": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:android_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:android_arm": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:android_arm64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:darwin_386": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:darwin_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:darwin_arm": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:darwin_arm64": [
":grunning",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:dragonfly_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:freebsd_386": [
":grunning",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:freebsd_amd64": [
":grunning",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:freebsd_arm": [
":grunning",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:freebsd_arm64": [
":grunning",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:illumos_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:ios_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:ios_arm64": [
":grunning",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:js_wasm": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_386": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_arm": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_arm64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_mips": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_mips64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_mips64le": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_mipsle": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_ppc64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_ppc64le": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_riscv64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:linux_s390x": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:netbsd_386": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:netbsd_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:netbsd_arm": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:netbsd_arm64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:openbsd_386": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:openbsd_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:openbsd_arm": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:openbsd_arm64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:plan9_386": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:plan9_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:plan9_arm": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:solaris_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:windows_386": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:windows_amd64": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"@io_bazel_rules_go//go/platform:windows_arm": [
":grunning",
"//pkg/testutils/skip",
"//pkg/util/syncutil",
"@com_github_stretchr_testify//require",
],
"//conditions:default": [],
}),
)

get_x_data(name = "get_x_data")
20 changes: 20 additions & 0 deletions pkg/util/grunning/disabled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2022 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

// See grunning.Supported() for an explanation behind this build tag.
//
//go:build (darwin && arm64) || freebsd || !bazel
// +build darwin,arm64 freebsd !bazel

package grunning

func grunningnanos() int64 { return 0 }

func supported() bool { return false }
29 changes: 29 additions & 0 deletions pkg/util/grunning/disabled_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright 2022 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

// See grunning.Supported() for an explanation behind this build tag.
//
//go:build (darwin && arm64) || freebsd || !bazel
// +build darwin,arm64 freebsd !bazel

package grunning_test

import (
"testing"

"github.com/cockroachdb/cockroach/pkg/util/grunning"
"github.com/stretchr/testify/require"
)

func TestDisabled(t *testing.T) {
require.False(t, grunning.Supported())
require.Zero(t, grunning.Time())
require.Zero(t, grunning.Subtract(grunning.Time(), grunning.Time()))
}
28 changes: 28 additions & 0 deletions pkg/util/grunning/enabled.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright 2022 The Cockroach Authors.
//
// Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0, included in the file
// licenses/APL.txt.

// See grunning.Supported() for an explanation behind this build tag.
//
//go:build !((darwin && arm64) || freebsd || !bazel)
// +build !darwin !arm64
// +build !freebsd
// +build bazel

package grunning

import _ "unsafe" // for go:linkname

// grunningnanos returns the running time observed by the current goroutine by
// linking to a private symbol in the (patched) runtime package.
//
//go:linkname grunningnanos runtime.grunningnanos
func grunningnanos() int64

func supported() bool { return true }
Loading

0 comments on commit 5b0982e

Please sign in to comment.