Golang 逐行读取大文件性能对比

51reboot ·
下面同样的读取2g的同一个文件,我给出分段读取分段处理的代码,是我认为比较快的代码了,时间一般是13s左右,竞争大则需要花费26s左右,还可以优化的!采用异步读取和写入!望能抛砖引玉: ``` package main import ( "fmt" "io" "os" "sync" "time" //"sync" ) var L sync.Mutex var L2 sync.Mutex var byteNum =4096 var rOff, wOff = -byteNum, -byteNum var retResev, retSend = false, false var wg = sync.WaitGroup{} var ch = make(chan []byte, 8) func main() { start := time.Now() newfile, err := os.OpenFile(`C:\Users\Administrator\Desktop\go_pro\src\io_pro\test12\test\阳光电影www.ygdy8.com.鬼影特攻:以暴制暴.BD.1080p.中英双字幕1111.mkv`, os.O_CREATE|os.O_WRONLY, 0666) checkErr(err) defer newfile.Close() file, e := os.Open(`C:\Users\Administrator\Desktop\go_pro\src\io_pro\test12\test\阳光电影www.ygdy8.com.鬼影特攻:以暴制暴.BD.1080p.中英双字幕.mkv`) checkErr(e) defer file.Close() for i := 0; i < 4; i++ { //接收数据 wg.Add(1) go resevCh(newfile) wg.Add(1) //发送数据 go SendCh(file) } wg.Wait() end := time.Now() fmt.Println(end.Sub(start)) fmt.Println("主程序退出") } func resevCh(newfile *os.File) { L2.Lock() //必须是与上面不同的锁 defer func() { //fmt.Println("写入子程序退出....") L2.Unlock() wg.Done() }() //限制口,防止在其中一个g程写入文件完成后然而其他g程还没结束 if retResev { return } for !retResev { ls, ok := <-ch if ok { wOff += byteNum //var n1 int _, err := newfile.WriteAt(ls, int64(wOff)) //fmt.Println("len(ls):", len(ls)) //fmt.Println("线程写入resevCh的字节数为:", n1) checkErr(err) } else { retResev = true } } } func SendCh(file *os.File) { L.Lock() defer func() { fmt.Println("读取SendCh子程序退出!!!") L.Unlock() wg.Done() }() //限制口,防止在其中一个g程读取文件完成后然而其他g程还没结束 if retSend { return } for !retSend { rOff += byteNum ls := make([]byte, byteNum) //每个g程都维护一个这样的结构 n, err := file.ReadAt(ls, int64(rOff)) //fmt.Println("某某线程读取了的字节数为:", n) checkErr(err) ch <- ls[:n] //通信 if err == io.EOF { retSend = true close(ch) //务必要关闭,而且只能由一个g程关闭,而不是所有的g程, //所以不能放到defer func中去 fmt.Println("关闭ch") return } } } func checkErr(err error) { if err != nil { fmt.Println(err) } } ```
#4
更多评论
受硬件影响较大,不说明配置确实难以比较
#1
同时你把读取的东西忽略掉也是受影响的,10g东西30s是不可能的事情
#2