2 回答
TA贡献1810条经验 获得超5个赞
这是一种不太难也不太慢的方法,使用bytes.IndexByte(因为你发现 Go 的 asm 实现有帮助)和syscall.Mmap:
package main
import (
"bytes"
"fmt"
"log"
"os"
"syscall"
)
func main() {
if len(os.Args) < 2 {
log.Fatal("pass filename on command line")
}
f, err := os.Open(os.Args[1])
if err != nil {
log.Fatal("open: ", err)
}
stat, err := f.Stat()
if err != nil {
log.Fatal("stat: ", err)
}
data, err := syscall.Mmap(int(f.Fd()), 0, int(stat.Size()), syscall.PROT_READ, syscall.MAP_SHARED)
if err != nil {
log.Fatal("mmap: ", err)
}
newlines := 0
for {
i := bytes.IndexByte(data, 10)
if i == -1 {
break
}
newlines++
data = data[i+1:]
}
fmt.Println(newlines)
}
Mmap 看起来很奇怪,但在这里就像您将文件读入一个切片一样,除了由于操作系统的帮助而占用的资源较少。
您可以在没有太多工作的情况下并行计数,但我不确定这是否值得。(amd64例如,如果单核计数受到内存带宽的限制,如果增益为零或负值,我不会感到震惊,但这对我来说测试速度并不快。)
- 2 回答
- 0 关注
- 165 浏览
添加回答
举报