Всем привет. Буду благодарен, если кто-то сможет прояснить, как именно ведёт себя рантайм Go при выполнении медленных сисколлов. Представим, что есть приложение, которое выполняет интенсивную работу с ФС (создаёт, пишет, синкает файлы). По очевидным причинам вызов syscall.Fsync достаточно дорогой: на какое-то время вызывающая горутина будет заблокирована. Вопрос в том, продолжат ли остальные горутины работать? Или любое переключение в контекст ядра останавливает весь рантайм?
Иными словами, имеет ли смысл применять многопоточность для ввода на диск? Пример:
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
}
f, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY, os.FileMode(0644))
if err != nil {
log.Fatal(err)
continue
}
if _, err := f.Write(data); err != nil {
log.Fatal(err)
continue
}
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()
}
Спасибо всем за помощь.