我该怎么做才能让多个goroutine读写大文件时跑满磁盘的读写上限速度

大家好,我是一个golang初学者.

我的目的是将一个大文件逐行读取,筛选出我需要的行,稍加处理并且全部存放到另一个文件中去.并且越快越好,因为文件很大,需要很长的时间.

当我运行下面的代码时,我发现读写速度只有30-40MB/S

我的硬盘是M.2固态,上限应该在1600MB/S左右,这是用 split 命令切割100G的文件观察到这个值,很稳定.

package main

import (
    "bufio"
    "log"
    "os"
    "sync"
)



func check(err error) {
    if err != nil {
        log.Fatal(err)
    }
}
func main() {
    var goroutineNum = 100
    var wg sync.WaitGroup
    wg.Add(goroutineNum)
    ch := make(chan string)
    
    
    src, e := os.Open("F:/src.txt")
    check(e)
    defer src.Close()


    dst, e := os.OpenFile("F:/dst.txt", os.O_WRONLY|os.O_CREATE, 0666)
    check(e)
    defer dst.Close()


    go func() {
        defer close(ch)
        bfsc := bufio.NewScanner(src)
        for bfsc.Scan() {
            ch <- bfsc.Text()
        }

    }()


    for i := 0; i < goroutineNum; i++ {
        go func () {
            defer wg.Done()
            for line := range ch {
                dst.Write([]byte("why?"+line+"\n"))
            }
    
        }()
    }

    wg.Wait()
}

后来我尝试另一种写法,将src.txt这个大文件分成 size/goroutine数量 等同份数,然后启动多个goroutine ,从不同的offset去读,然而速度也是一样.

再后来我尝试将文件先切割成goroutine数量等同份数
每个goroutine去读一个单独的文件,然后速度还是这样

代码如下: (之前的代码因为文件太大没有完整测试,读完会死锁,已更新了)

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
    "strconv"
    "sync"
)

func check(err error) {
    if err != nil {
        log.Fatal(err)
    }
}
func main() {
    var fileNum = 100

    var wg sync.WaitGroup
    wg.Add(fileNum)
    ch := make(chan string, 100)
    done := make(chan bool)
    dst, e := os.OpenFile("F:/test/dst.txt", os.O_WRONLY|os.O_CREATE, 0666)
    check(e)
    defer dst.Close()

    for i := 0; i < fileNum; i++ {
        go func(n int) {
            defer wg.Done()
            fmt.Println("open ", "F:/test/xx/"+strconv.Itoa(n)+".txt")
            src, e := os.Open("F:/test/xx/" + strconv.Itoa(n) + ".txt")
            check(e)
            defer src.Close()
            bfsc := bufio.NewScanner(src)
            for bfsc.Scan() {
                ch <- bfsc.Text()
            }
        }(i)
    }

    go func() {

        for line := range ch {
            dst.Write([]byte("why?" + line + "\n"))
        }
        done<-true
    }()
    wg.Wait()
    close(ch)
    <-done
}

所以请问,我该怎么做才能让多个goroutine读写大文件时跑满磁盘的读写上限速度?

任何建议或者回应都非常感谢.

阅读 5.5k
1 个回答

如果按照你说的 将大文件打散,然后并发读取,应该是没问题的。是不是你的代码有问题?方便贴一下 这个方案的代码吗?帮你排查一下。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题