Skip to content

Commit 2eb726b

Browse files
committed
gopls/internal/lsp/filecache: touch only files older than 1h
This change implements an optimization similar to one in the go command's cache: we skip the chtimes(2) call to update the file access times unless it would change by at least one hour. This avoids turning every read into a write. It makes quite a difference to the Get benchmark: 330MB/s before, 430MB/s after. Change-Id: I5b5b6e99a1968c73bf1032b410bec989961c4a90 Reviewed-on: https://go-review.googlesource.com/c/tools/+/496438 Reviewed-by: Robert Findley <[email protected]> Run-TryBot: Alan Donovan <[email protected]> TryBot-Result: Gopher Robot <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent b742cb9 commit 2eb726b

File tree

1 file changed

+11
-11
lines changed

1 file changed

+11
-11
lines changed

gopls/internal/lsp/filecache/filecache.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,24 +110,24 @@ func Get(kind string, key [32]byte) ([]byte, error) {
110110

111111
// Update file times used by LRU eviction.
112112
//
113-
// This turns every read into a write operation.
114-
// If this is a performance problem, we should
115-
// touch the files asynchronously, or, follow
116-
// the approach used in the go command's cache
117-
// and update only if the existing timestamp is
118-
// older than, say, one hour.
113+
// Because this turns a read into a write operation,
114+
// we follow the approach used in the go command's
115+
// cache and update the access time only if the
116+
// existing timestamp is older than one hour.
119117
//
120118
// (Traditionally the access time would be updated
121119
// automatically, but for efficiency most POSIX systems have
122120
// for many years set the noatime mount option to avoid every
123121
// open or read operation entailing a metadata write.)
124122
now := time.Now()
125-
if err := os.Chtimes(indexName, now, now); err != nil {
126-
return nil, fmt.Errorf("failed to update access time of index file: %w", err)
127-
}
128-
if err := os.Chtimes(casName, now, now); err != nil {
129-
return nil, fmt.Errorf("failed to update access time of CAS file: %w", err)
123+
touch := func(filename string) {
124+
st, err := os.Stat(filename)
125+
if err == nil && now.Sub(st.ModTime()) > time.Hour {
126+
os.Chtimes(filename, now, now) // ignore error
127+
}
130128
}
129+
touch(indexName)
130+
touch(casName)
131131

132132
if useMemCache {
133133
memCache.Set(memKey{kind, key}, value, len(value))

0 commit comments

Comments
 (0)