我该怎么做才能让多个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读写大文件时跑满磁盘的读写上限速度?
任何建议或者回应都非常感谢.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果按照你说的 将大文件打散,然后并发读取,应该是没问题的。是不是你的代码有问题?方便贴一下 这个方案的代码吗?帮你排查一下。