percpu

package module
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2021 License: MIT Imports: 3 Imported by: 0

README

percpu

Go Reference

Percpu is a Go package to support best-effort CPU-local sharded values.

This package is something of an experiment. See Go issue #18802 for discussion about adding this functionality into the Go standard library. I used an API suggested by Bryan Mills (@bcmills) on that issue.

IMPORTANT CAVEATS

  • This package uses go:linkname to access unexported functions from inside the Go runtime. Those could be changed or removed in a future Go version, breaking this package.
  • The code in this package assumes that GOMAXPROCS does not change. If the value of GOMAXPROCS changes (via a call to runtime.GOMAXPROCS) after creating a Values, then Values.Get may panic.
  • It may be tempting to use this package to solve problems for which there are better solutions that do not break key abstractions of the runtime.

See When to use percpu for a discussion about when this package may or may not be appropriate.

Benchmarks

A best-case scenario for percpu is a shared counter being incremented as fast as possible. This is exercised by the benchmark for percpu.Counter, which compares the performance of Counter against a mutex-guarded integer and a single atomically-incremented integer.

Below are the results (limiting the code to use 1, 2, 4, ..., 96 cores on a 96-core machine) plotted as increments/sec.

benchmark image

With the mutex and the single atomic, adding more CPUs increases cache contention and the total number of increments/sec goes down. By contrast, the percpu.Counter scales up linearly in the number of CPUs. With all 96 CPUs, percpu.Counter runs several orders of magnitude faster than the other counters:

total incs/sec 1-goroutine inc latency slowdown vs. percpu.Counter
mutex 1.9M 50 μs 3727×
atomic 49M 2.0 μs 145×
percpu 7.1B 13.5 ns

Documentation

Overview

Package percpu provides best-effort CPU-local sharded values.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Counter

type Counter struct {
	// contains filtered or unexported fields
}

A Counter is an int64 counter which may be efficiently incremented by many goroutines concurrently.

The counter is sharded into several CPU-local values which are written and read independently. Thus, the Load and Reset methods do not observe a consistent view of the total if they are called concurrently to Add.

For example, suppose goroutine G1 runs

counter.Add(1)
counter.Add(2)

and, concurrently, G2 runs

t0 := counter.Reset()
// wait for G1 to finish executing
t1 := counter.Load()

The value of t0 may be any of 0, 1, 2, or 3. The value of t1 may be any of 0, 1, 2, or 3 as well. However, t0+t1 must equal 3.

func NewCounter

func NewCounter() *Counter

NewCounter returns a fresh Counter initialized to zero.

func (*Counter) Add

func (c *Counter) Add(n int64)

Add adds n to the total count.

func (*Counter) Load

func (c *Counter) Load() int64

Load computes the total counter value.

func (*Counter) Reset added in v0.0.2

func (c *Counter) Reset() int64

Reset sets the counter to zero and reports the old value.

type Values

type Values struct {
	// contains filtered or unexported fields
}

Values is a sharded set of values which have an affinity for a particular processor. This can be used to avoid cache contention when updating a shared value simultaneously from many goroutines.

func NewValues

func NewValues(newVal func() interface{}) *Values

NewValues constructs a Values using the provided constructor function to create each shard value.

func (*Values) Do

func (vs *Values) Do(fn func(interface{}))

Do runs fn on all of the values in vs.

func (*Values) Get

func (vs *Values) Get() interface{}

Get returns one of the values in vs.

The value tends to be the one associated with the current processor. However, goroutines can migrate at any time, and it may be the case that a different goroutine is accessing the same value concurrently. All access of the returned value must use further synchronization mechanisms.

BUG(cespare): If GOMAXPROCS has changed since a Values was created with NewValues, Get may panic.

Notes

Bugs

  • If GOMAXPROCS has changed since a Values was created with NewValues, Get may panic.

Directories

Path Synopsis
Package clrand implements CPU-local random number generators.
Package clrand implements CPU-local random number generators.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL