mirror of
https://github.com/golang/go.git
synced 2026-04-03 01:40:30 +09:00
cmd/go/internal/cache: update trim timestamp before trimming
This reduces the chance that multiple go commands running in CI will try to trim at the same time, causing contention and slowing things down. Fixes #76314 Change-Id: I3edf818fc9583795f3f51b715fdbe75b6a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/753240 Reviewed-by: Michael Matloob <matloob@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Michael Matloob <matloob@google.com> Reviewed-by: Alan Donovan <adonovan@google.com>
This commit is contained in:
committed by
Gopher Robot
parent
e2ce40125f
commit
2a5890cd46
41
src/cmd/go/internal/cache/cache.go
vendored
41
src/cmd/go/internal/cache/cache.go
vendored
@@ -385,13 +385,42 @@ func (c *DiskCache) Trim() error {
|
||||
// trim time is too far in the future, attempt the trim anyway. It's possible that
|
||||
// the cache was full when the corruption happened. Attempting a trim on
|
||||
// an empty cache is cheap, so there wouldn't be a big performance hit in that case.
|
||||
if data, err := lockedfile.Read(filepath.Join(c.dir, "trim.txt")); err == nil {
|
||||
skipTrim := func(data []byte) bool {
|
||||
if t, err := strconv.ParseInt(strings.TrimSpace(string(data)), 10, 64); err == nil {
|
||||
lastTrim := time.Unix(t, 0)
|
||||
if d := now.Sub(lastTrim); d < trimInterval && d > -mtimeInterval {
|
||||
return nil
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
// Check to see if we need a trim. Do this check separately from the lockedfile.Transform
|
||||
// so that we can skip getting an exclusive lock in the common case.
|
||||
if data, err := lockedfile.Read(filepath.Join(c.dir, "trim.txt")); err == nil {
|
||||
if skipTrim(data) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
errFileChanged := errors.New("file changed")
|
||||
|
||||
// Write the new timestamp before we start trimming to reduce the chance that multiple invocations
|
||||
// try to trim at the same time, causing contention in CI (#76314).
|
||||
err := lockedfile.Transform(filepath.Join(c.dir, "trim.txt"), func(data []byte) ([]byte, error) {
|
||||
if skipTrim(data) {
|
||||
// The timestamp in the file no longer meets the criteria for us to
|
||||
// do a trim. It must have been updated by another go command invocation
|
||||
// since we last read it. Skip the trim.
|
||||
return nil, errFileChanged
|
||||
}
|
||||
return fmt.Appendf(nil, "%d", now.Unix()), nil
|
||||
})
|
||||
if errors.Is(err, errors.ErrUnsupported) {
|
||||
return err
|
||||
}
|
||||
if errors.Is(err, errFileChanged) {
|
||||
// Skip the trim because we don't need it anymore.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Trim each of the 256 subdirectories.
|
||||
@@ -403,14 +432,6 @@ func (c *DiskCache) Trim() error {
|
||||
c.trimSubdir(subdir, cutoff)
|
||||
}
|
||||
|
||||
// Ignore errors from here: if we don't write the complete timestamp, the
|
||||
// cache will appear older than it is, and we'll trim it again next time.
|
||||
var b bytes.Buffer
|
||||
fmt.Fprintf(&b, "%d", now.Unix())
|
||||
if err := lockedfile.Write(filepath.Join(c.dir, "trim.txt"), &b, 0o666); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user