github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/fsmetric/fsmetric.go (about)

     1  // Copyright 2020 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 fsmetric defines filesystem metrics that are used by both VFS1 and
    16  // VFS2.
    17  //
    18  // TODO(github.com/SagerNet/issue/1624): Once VFS1 is deleted, inline these metrics into
    19  // VFS2.
    20  package fsmetric
    21  
    22  import (
    23  	"time"
    24  
    25  	"github.com/SagerNet/gvisor/pkg/metric"
    26  )
    27  
    28  // RecordWaitTime enables the ReadWait, GoferReadWait9P, GoferReadWaitHost, and
    29  // TmpfsReadWait metrics. Enabling this comes at a CPU cost due to performing
    30  // three clock reads per read call.
    31  //
    32  // Note that this is only performed in the direct read path, and may not be
    33  // consistently applied for other forms of reads, such as splice.
    34  var RecordWaitTime = false
    35  
    36  // Metrics that apply to all filesystems.
    37  var (
    38  	Opens    = metric.MustCreateNewUint64Metric("/fs/opens", false /* sync */, "Number of file opens.")
    39  	Reads    = metric.MustCreateNewUint64Metric("/fs/reads", false /* sync */, "Number of file reads.")
    40  	ReadWait = metric.MustCreateNewUint64NanosecondsMetric("/fs/read_wait", false /* sync */, "Time waiting on file reads, in nanoseconds.")
    41  )
    42  
    43  // Metrics that only apply to fs/gofer and fsimpl/gofer.
    44  var (
    45  	GoferOpens9P      = metric.MustCreateNewUint64Metric("/gofer/opens_9p", false /* sync */, "Number of times a file was opened from a gofer and did not have a host file descriptor.")
    46  	GoferOpensHost    = metric.MustCreateNewUint64Metric("/gofer/opens_host", false /* sync */, "Number of times a file was opened from a gofer and did have a host file descriptor.")
    47  	GoferReads9P      = metric.MustCreateNewUint64Metric("/gofer/reads_9p", false /* sync */, "Number of 9P file reads from a gofer.")
    48  	GoferReadWait9P   = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_9p", false /* sync */, "Time waiting on 9P file reads from a gofer, in nanoseconds.")
    49  	GoferReadsHost    = metric.MustCreateNewUint64Metric("/gofer/reads_host", false /* sync */, "Number of host file reads from a gofer.")
    50  	GoferReadWaitHost = metric.MustCreateNewUint64NanosecondsMetric("/gofer/read_wait_host", false /* sync */, "Time waiting on host file reads from a gofer, in nanoseconds.")
    51  )
    52  
    53  // Metrics that only apply to fs/tmpfs and fsimpl/tmpfs.
    54  var (
    55  	TmpfsOpensRO  = metric.MustCreateNewUint64Metric("/in_memory_file/opens_ro", false /* sync */, "Number of times an in-memory file was opened in read-only mode.")
    56  	TmpfsOpensW   = metric.MustCreateNewUint64Metric("/in_memory_file/opens_w", false /* sync */, "Number of times an in-memory file was opened in write mode.")
    57  	TmpfsReads    = metric.MustCreateNewUint64Metric("/in_memory_file/reads", false /* sync */, "Number of in-memory file reads.")
    58  	TmpfsReadWait = metric.MustCreateNewUint64NanosecondsMetric("/in_memory_file/read_wait", false /* sync */, "Time waiting on in-memory file reads, in nanoseconds.")
    59  )
    60  
    61  // StartReadWait indicates the beginning of a file read.
    62  func StartReadWait() time.Time {
    63  	if !RecordWaitTime {
    64  		return time.Time{}
    65  	}
    66  	return time.Now()
    67  }
    68  
    69  // FinishReadWait indicates the end of a file read whose time is accounted by
    70  // m. start must be the value returned by the corresponding call to
    71  // StartReadWait.
    72  //
    73  // FinishReadWait is marked nosplit for performance since it's often called
    74  // from defer statements, which prevents it from being inlined
    75  // (https://github.com/golang/go/issues/38471).
    76  //go:nosplit
    77  func FinishReadWait(m *metric.Uint64Metric, start time.Time) {
    78  	if !RecordWaitTime {
    79  		return
    80  	}
    81  	m.IncrementBy(uint64(time.Since(start).Nanoseconds()))
    82  }