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 }