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

发布于 2022-09-11 22:57:52 字数 2450 浏览 30 评论 0

大家好,我是一个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读写大文件时跑满磁盘的读写上限速度?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风吹短裙飘 2022-09-18 22:57:52

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文