github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/metric/metric_unsafe.go (about)

     1  // Copyright 2022 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package metric
    16  
    17  import (
    18  	"unsafe"
    19  
    20  	"github.com/nicocha30/gvisor-ligolo/pkg/atomicbitops"
    21  	"github.com/nicocha30/gvisor-ligolo/pkg/gohacks"
    22  	"github.com/nicocha30/gvisor-ligolo/pkg/sync"
    23  )
    24  
    25  // snapshotDistribution snapshots the sample data of distribution metrics in
    26  // a non-consistent manner.
    27  // Distribution metrics don't need to be read consistently, because any
    28  // inconsistency (i.e. increments that race with the snapshot) will simply be
    29  // detected during the next snapshot instead. Reading them consistently would
    30  // require more synchronization during increments, which we need to be cheap.
    31  func snapshotDistribution(samples []atomicbitops.Uint64) []uint64 {
    32  	// The number of buckets within a distribution never changes, so there is
    33  	// no race condition from getting the number of buckets upfront.
    34  	numBuckets := len(samples)
    35  	snapshot := make([]uint64, numBuckets)
    36  	if sync.RaceEnabled {
    37  		// runtime.RaceDisable() doesn't actually stop the race detector, so it
    38  		// can't help us here. Instead, call runtime.memmove directly, which is
    39  		// not instrumented by the race detector.
    40  		gohacks.Memmove(unsafe.Pointer(&snapshot[0]), unsafe.Pointer(&samples[0]), unsafe.Sizeof(uint64(0))*uintptr(numBuckets))
    41  	} else {
    42  		for i := range samples {
    43  			snapshot[i] = samples[i].RacyLoad()
    44  		}
    45  	}
    46  	return snapshot
    47  }
    48  
    49  // CheapNowNano returns the current unix timestamp in nanoseconds.
    50  //
    51  //go:nosplit
    52  func CheapNowNano() int64 {
    53  	return gohacks.Nanotime()
    54  }