Use semaphore to limit number of goroutines stuck in Sync syscall

It is rising number of running threads of go-ipfs from 12 to 200+ when
the flatfs datastore works on slowish HDDs.
parent b3dac15a
......@@ -151,7 +151,7 @@ func (fs *Datastore) doPut(key datastore.Key, val []byte) error {
return err
}
if fs.sync {
if err := tmp.Sync(); err != nil {
if err := syncFile(tmp); err != nil {
return err
}
}
......@@ -220,7 +220,7 @@ func (fs *Datastore) putMany(data map[datastore.Key]interface{}) error {
// sync and close files
for fi, _ := range files {
if fs.sync {
if err := fi.Sync(); err != nil {
if err := syncFile(fi); err != nil {
return err
}
}
......
package flatfs
import (
"os"
"runtime"
)
// don't block more than 16 threads on sync opearation
// 16 should be able to sataurate most RAIDs
// in case of two used disks per write (RAID 1, 5) and queue depth of 2,
// 16 concurrent Sync calls should be able to saturate 16 HDDs RAID
//TODO: benchmark it out, maybe provide tweak parmeter
var syncSemaphore chan struct{} = make(chan struct{}, 16)
func syncDir(dir string) error {
if runtime.GOOS == "windows" {
// dir sync on windows doesn't work: https://git.io/vPnCI
return nil
}
dirF, err := os.Open(dir)
if err != nil {
return err
}
defer dirF.Close()
syncSemaphore <- struct{}{}
defer func() { <-syncSemaphore }()
if err := dirF.Sync(); err != nil {
return err
}
return nil
}
func syncFile(file *os.File) error {
syncSemaphore <- struct{}{}
defer func() { <-syncSemaphore }()
return file.Sync()
}
// +build !windows
package flatfs
import "os"
func syncDir(dir string) error {
dirF, err := os.Open(dir)
if err != nil {
return err
}
defer dirF.Close()
if err := dirF.Sync(); err != nil {
return err
}
return nil
}
package flatfs
func syncDir(dir string) error {
return nil
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment