golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.84k stars 17.51k forks source link

proposal: runtime/local: new package to provide transparent access to Per-P Local Storage #68952

Open lemon-mint opened 3 weeks ago

lemon-mint commented 3 weeks ago

Proposal Details

This proposal introduces a new package, runtime/local, providing an API for per-P local storage in Go. This enables efficient and race-free access to shared yet locally scoped data, like random number generator states or per-P Logger, without the overhead of locks or cas loop.

Several packages within the standard library, including runtime.fastrand and sync.Pool, already utilize per-P or per-M storage internally for performance optimization. This proposal aims to expose a similar mechanism through a public API, enables developers to leverage this approach for their own concurrency needs.

This proposal introduces the runtime/local package with the following API:

package local

// Key represents a unique identifier for accessing local storage.
type Key uint32

// AllocateKey reserves a new Key for local storage access.
func AllocateKey() Key

// ReleaseKey releases a previously allocated Key.
func ReleaseKey(k Key)

// Storage provides access to the per-P local storage.
type Storage struct {
    // pid represents the logical processor ID associated with this Storage.
    pid int

    // values holds the actual stored data, indexed by Key.
    values []any
}

// ID returns the logical processor ID associated with this Storage.
func (s *Storage) ID() int

// Load retrieves the value associated with the given Key.
// The second return value indicates whether a value was found.
func (s *Storage) Load(k Key) (any, bool)

// Store associates the given value with the specified Key.
// It returns true if the operation was successful, false otherwise.
func (s *Storage) Store(k Key, v any) bool

// OpenFunc executes the provided function f with the Storage
// instance associated with the calling goroutine's current P.
// It returns the logical processor ID associated with the Storage.
func OpenFunc(f func(*Storage)) (id int)

The proposed package name candidates are following:


Open Issues:

ianlancetaylor commented 3 weeks ago

CC @golang/runtime

thediveo commented 3 weeks ago

I'm confused: what use case does this proposal address? Is handling thread-local storage on a locked Go routine in order to interface with non-Go code using thread-local storage? Or does it try to tackle Go routine local storage, then it appears to be wrongly using PIDs (it's probably using PIDs wrongly anyway)?