为什么不使用WriteAt并行编写goroutine?

时间:2017-12-12 17:40:04

标签: go concurrency goroutine file-writing

我正在尝试从文件中读取和写入。 为了同时写入文件,我创建了以下函数:

func write(f *os.File, b []byte, off int64, c chan int) {
    var _, err = f.WriteAt(b, off)
    check(err)
    c <- 0
}

然后我创建一个文件和100000个goroutine来执行写操作。 它们每个都将一个16384字节数组写入硬盘:

func main() {
    path := "E:/test"
    f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0666)
    check(err)

    size := int64(16384)
    ones := make([]byte, size)

    n := int64(100000)
    c := make(chan int, n)

    for i := int64(0); i < size; i++ {
        ones[i] = 1
    }

    // Start timing
    start := time.Now()

    for i := int64(0); i < n; i++ {
        go write(f, ones, size*i, c)
    }

    for i := int64(0); i < n; i++ {
        <-c
    }

    // Check elapsed time
    fmt.Println(time.Now().Sub(start))

    err = f.Sync()
    check(err)
    err = f.Close()

    check(err)
}

在这种情况下,写入大约1.6 GB,其中每个goroutine写入非重叠字节范围。 io包的文档指出Clients of WriteAt can execute parallel WriteAt calls on the same destination if the ranges do not overlap. 所以我期望看到的是,当我使用go write(f, ones, 0, c)时,由于所有写操作都在相同的字节范围内,因此需要更长的时间。

然而,经过测试,我的结果非常出乎意料:

使用go write(f, ones, size*i, c)平均约为3s

但使用go write(f, ones, 0, c)的平均值只有约480ms

我是否以错误的方式使用WriteAt功能?如何实现对非重叠字节范围的并发写入?

0 个答案:

没有答案