提高在C中读取gz文件的速度



我已经编写了一个小型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输出中的错误看起来无害。

最新更新