最近一直用的golang,然后写pat1015德才论的时候出了问题,运行超时,不是说golang速度还可以吗。
于是从网上找了同样的c++做了一下比较,发现同样的数据(10万行,一行3个整数),c++几十毫秒就完成,golang要十几秒,这也差距太大了吧。输出运行时间后,发现是输入输出有问题。网上查了一圈,原来是标准的fmt包没有缓存,然后速度就很慢。
找了几个改进的方法。
Scanner
这个最快的。默认的读取方式是一行行的读。
sc := bufio.NewScanner(f)//f文件指针
for sc.Scan() {
str := sc.Text()
s := strings.Fields(str," ")//因为3个整数之间的空格数量不等,用Split的话,就不能分割多个空格的情况
id := strconv.PraseInt(s[0],10,0)//因为数据最后要是int,所以自己处理转换一下。
}
Reader
这个就是把文件指针给了Reader而已。要是这里改成和上面只读一行,返回字符串,然后在自己处理的话,和上面差不多。因为我在stack overflow看一个测试,这个要稍微慢一丢丢,这是GitHub链接。
reader := bufio.NewReader(f)
for i := 0; i < N; i++{
fmt.Fscanf(reader,"%d%d%d".&id,&d,&c)
}
Nobuf
这个就直接从文件输入。
for i := 0; i < N; i++{
fmt.Fscanf(f,"%d%d%d".&id,&d,&c)
}
时间对比
三种方式的时间对比
最快的Scanner,他就一个读取一整行的操作,后面的转换我自己做的。这个只把文件指针加到reader里,让fmt包来转换慢一点180ms了。这个没有缓存的这也太慢了吧。
测试是在WSL里测试的。
对比c++
c++就直接用的fscanf(f,"%d%d%d".&id,&d,&c)
。编译指令g++ main.c++ -o main
,用时31ms。比golang的scanner还快一点。而且输出只有15ms,我用golang的bufio.NewWriter()
输出要780ms,而且这个writer还要手动的Flush。
然后是这个sort排序时间,一开始没有用这个优化指令,比golang的sort多了一倍。改了O2
编译之后和golang差不多了。这个优化还是厉害,但是输入输出没有变化。
还是了解的太少了😂,这种基础操作都不会。以后要多使用这个bufio。