我已经编写了一个小型C
程序。它确实读取了一些gzip文件,进行了一些过滤,然后再次输出到gzip文件。
我用-O3 -Ofast
运行gcc。其他方面都很标准。
如果我在我的可执行文件上执行strace -c
,我会得到:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
46.01 0.077081 0 400582 read
42.73 0.071579 4771 15 munmap
9.34 0.015647 0 110415 brk
1.01 0.001688 32 52 openat
0.45 0.000746 3 228 mmap
0.20 0.000327 4 70 mprotect
0.15 0.000254 0 1128 write
0.06 0.000100 2 50 fstat
0.05 0.000087 1 52 close
0.00 0.000006 6 1 getrandom
0.00 0.000005 2 2 rt_sigaction
0.00 0.000004 2 2 1 arch_prctl
0.00 0.000003 3 1 1 stat
0.00 0.000003 1 2 lseek
0.00 0.000002 2 1 rt_sigprocmask
0.00 0.000002 2 1 prlimit64
0.00 0.000000 0 8 pread64
0.00 0.000000 0 1 1 access
0.00 0.000000 0 1 execve
0.00 0.000000 0 2 fdatasync
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.167534 512616 3 total
所以我的程序正忙于读取文件。现在,我不确定我是否能更快。相关代码如下:
while (gzgets(file_pointer, line, LL) != Z_NULL) {
linkage = strtok(line,"t");
linkage = strtok(NULL,"t");
linkage[strcspn(linkage, "n")] = 0;
add_linkage_entry(id_cnt, linkage);
id_cnt++;
}
你认为这里还有改进的余地吗?是否可以手动使用gzread
进行干预,或者gzgets
在这里做得不好,不逐个读取字符?
还有其他建议吗?(strace
中的错误令人担忧吗?(
编辑:add_linkage_entry
确实向uthash
哈希表添加了一个条目(https://troydhanson.github.io/uthash/)
我不认为gzgets
(以及相关的read
系统调用(是这里的瓶颈。
对于压缩良好的数据,read
调用的次数较少,而对于熵较大的数据,调用次数会增加(zlib
必须更频繁地从磁盘请求未压缩的数据(。例如,对于从urandom
生成的文本数据(通过
base64 /dev/urandom | tr -- '+HXA' 't' | head -n 10000000 | gzip
)我收到了大约70000个1000万条线路的read
呼叫,相当于大约140条线路/呼叫。这与您每次通话100…1000条线路的体验非常匹配。
更重要的是,读取这些行的CPU时间仍然可以忽略不计(大约2.5M行/s,包括strtok
调用(。高度压缩的数据所需的read
调用减少了约40倍,读取速度也提高了约4倍,但通过命令行上的gzip -d
进行原始解压缩也可以看到这4倍。
因此,您的函数add_linkage_entry
似乎是此处的瓶颈。特别是,大量的brk
呼叫看起来并不常见。
strace输出中的错误看起来无害。