If an application does heavy work with multiple file descriptors (for example, opening - writing data - synchronizing - closing), what actually happens when Go starts? Does it block all goroutines while expensive syscall happens (e.g. syscall.Fsync )? Or is it only the calling goroutine is blocked, and the rest are still working?
. Does it make sense to write programs with several workers that deal with a large amount of user space - switching the context of the kernel? Does it make sense to use multi-threaded templates for disk input?
package main import ( "log" "os" "sync" ) var data = []byte("some big data") func worker(filenamechan chan string, wg *sync.waitgroup) { defer wg.done() for { filename, ok := <-filenamechan if !ok { return } // open file is a quite expensive operation due to // the opening new descriptor f, err := os.openfile(filename, os.o_create|os.o_wronly, os.filemode(0644)) if err != nil { log.fatal(err) continue } // write is a cheap operation, // because it just moves data from user space to the kernel space if _, err := f.write(data); err != nil { log.fatal(err) continue } // syscall.fsync is a disk-bound expensive operation if err := f.sync(); err != nil { log.fatal(err) continue } if err := f.close(); err != nil { log.fatal(err) } } } func main() { // launch workers filenamechan := make(chan string) wg := &sync.waitgroup{} for i := 0; i < 2; i++ { wg.add(1) go worker(filenamechan, wg) } // send tasks to workers filenames := []string{ "1.txt", "2.txt", "3.txt", "4.txt", "5.txt", } for i := range filenames { filenamechan <- filenames[i] } close(filenamechan) wg.wait() }
https://play.golang.org/p/O0omcPBMAJ
multithreading go system-calls goroutine
Vitaly isaev
source share