mirror of
https://github.com/golang/go
synced 2024-11-13 16:00:21 -07:00
ca8354843e
Using Once.Do is now extremely cheap because the fast path is just an inlined atomic load of a variable that is written only once and a conditional jump. This is very beneficial for Once.Do because, due to its nature, the fast path will be used for every call after the first one. In a attempt to mimize code size increase, reorder the fields so that the pointer to Once is also the pointer to Once.done, that is the only field used in the hot path. This allows to use more compact instruction encodings or less instructions in the hot path (that is inlined at every callsite). name old time/op new time/op delta Once 4.54ns ± 0% 2.06ns ± 0% -54.59% (p=0.000 n=19+16) Once-4 1.18ns ± 0% 0.55ns ± 0% -53.39% (p=0.000 n=15+16) Once-16 0.53ns ± 0% 0.17ns ± 0% -67.92% (p=0.000 n=18+17) linux/amd64 bin/go 14675861 (previous commit 14663387, +12474/+0.09%) Change-Id: Ie2708103ab473787875d66746d2f20f1d90a6916 Reviewed-on: https://go-review.googlesource.com/c/go/+/152697 Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Reviewed-by: Austin Clements <austin@google.com>
41 lines
1.2 KiB
Go
41 lines
1.2 KiB
Go
// +build !nacl,!386,!wasm,!arm,!gcflags_noopt
|
|
// errorcheck -0 -m
|
|
|
|
// Copyright 2019 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Test, using compiler diagnostic flags, that inlining of functions
|
|
// imported from the sync package is working.
|
|
// Compiles but does not run.
|
|
|
|
// FIXME: This test is disabled on architectures where atomic operations
|
|
// are function calls rather than intrinsics, since this prevents inlining
|
|
// of the sync fast paths. This test should be re-enabled once the problem
|
|
// is solved.
|
|
|
|
package foo
|
|
|
|
import (
|
|
"sync"
|
|
)
|
|
|
|
var mutex *sync.Mutex
|
|
|
|
func small5() { // ERROR "can inline small5"
|
|
// the Unlock fast path should be inlined
|
|
mutex.Unlock() // ERROR "inlining call to sync\.\(\*Mutex\)\.Unlock" "&sync\.m\.state escapes to heap"
|
|
}
|
|
|
|
func small6() { // ERROR "can inline small6"
|
|
// the Lock fast path should be inlined
|
|
mutex.Lock() // ERROR "inlining call to sync\.\(\*Mutex\)\.Lock" "&sync\.m\.state escapes to heap"
|
|
}
|
|
|
|
var once *sync.Once
|
|
|
|
func small7() { // ERROR "can inline small7"
|
|
// the Do fast path should be inlined
|
|
once.Do(small5) // ERROR "inlining call to sync\.\(\*Once\)\.Do" "&sync\.o\.done escapes to heap"
|
|
}
|