lib/fs, lib/model: Reduce lock contention on NewCaseFilesystem (fixes #7268) (#7269)

This commit is contained in:
Jakob Borg
2021-01-12 16:22:21 +01:00
committed by GitHub
parent f6fac3e949
commit 8f199e12b3
2 changed files with 33 additions and 20 deletions
+23 -13
View File
@@ -48,25 +48,35 @@ type fskey struct {
// their cache every now and then.
type caseFilesystemRegistry struct {
fss map[fskey]*caseFilesystem
mut sync.Mutex
mut sync.RWMutex
startCleaner sync.Once
}
func (r *caseFilesystemRegistry) get(fs Filesystem) Filesystem {
r.mut.Lock()
defer r.mut.Unlock()
k := fskey{fs.Type(), fs.URI()}
// Use double locking when getting a caseFs. In the common case it will
// already exist and we take the read lock fast path. If it doesn't, we
// take a write lock and try again.
r.mut.RLock()
caseFs, ok := r.fss[k]
r.mut.RUnlock()
if !ok {
caseFs = &caseFilesystem{
Filesystem: fs,
realCaser: newDefaultRealCaser(fs),
r.mut.Lock()
caseFs, ok = r.fss[k]
if !ok {
caseFs = &caseFilesystem{
Filesystem: fs,
realCaser: newDefaultRealCaser(fs),
}
r.fss[k] = caseFs
r.startCleaner.Do(func() {
go r.cleaner()
})
}
r.fss[k] = caseFs
r.startCleaner.Do(func() {
go r.cleaner()
})
r.mut.Unlock()
}
return caseFs
@@ -74,11 +84,11 @@ func (r *caseFilesystemRegistry) get(fs Filesystem) Filesystem {
func (r *caseFilesystemRegistry) cleaner() {
for range time.NewTicker(time.Minute).C {
r.mut.Lock()
r.mut.RLock()
for _, caseFs := range r.fss {
caseFs.dropCache()
}
r.mut.Unlock()
r.mut.RUnlock()
}
}