Skip to content

Commit cebe9d0

Browse files
authored
perf: avoid syncing directories when they already existed (#107)
When doing a Put, the containing directory is always created. If it already exist, no error bubbles up from makeDirNoSync and later this directy is always synched on disk in makeDir. This generate FS operations which are almost always unnecessary as the supporting folders are quickly all created.
1 parent cb01d7b commit cebe9d0

File tree

1 file changed

+11
-10
lines changed

1 file changed

+11
-10
lines changed

flatfs.go

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -326,35 +326,36 @@ func (fs *Datastore) decode(file string) (key datastore.Key, ok bool) {
326326
}
327327

328328
func (fs *Datastore) makeDir(dir string) error {
329-
if err := fs.makeDirNoSync(dir); err != nil {
329+
created, err := fs.makeDirNoSync(dir)
330+
if err != nil {
330331
return err
331332
}
332333

333334
// In theory, if we create a new prefix dir and add a file to
334335
// it, the creation of the prefix dir itself might not be
335336
// durable yet. Sync the root dir after a successful mkdir of
336337
// a prefix dir, just to be paranoid.
337-
if fs.sync {
338+
if fs.sync && created {
338339
if err := syncDir(fs.path); err != nil {
339340
return err
340341
}
341342
}
342343
return nil
343344
}
344345

345-
func (fs *Datastore) makeDirNoSync(dir string) error {
346+
// makeDirNoSync create a directory on disk and report if it was created or
347+
// already existed.
348+
func (fs *Datastore) makeDirNoSync(dir string) (created bool, err error) {
346349
if err := os.Mkdir(dir, 0755); err != nil {
347-
// EEXIST is safe to ignore here, that just means the prefix
348-
// directory already existed.
349-
if !os.IsExist(err) {
350-
return err
350+
if os.IsExist(err) {
351+
return false, nil
351352
}
352-
return nil
353+
return false, err
353354
}
354355

355356
// Track DiskUsage of this NEW folder
356357
fs.updateDiskUsage(dir, true)
357-
return nil
358+
return true, nil
358359
}
359360

360361
// This function always runs under an opLock. Therefore, only one thread is
@@ -575,7 +576,7 @@ func (fs *Datastore) putMany(data map[datastore.Key][]byte) error {
575576

576577
for key, value := range data {
577578
dir, path := fs.encode(key)
578-
if err := fs.makeDirNoSync(dir); err != nil {
579+
if _, err := fs.makeDirNoSync(dir); err != nil {
579580
return err
580581
}
581582
dirsToSync[dir] = struct{}{}

0 commit comments

Comments
 (0)