我目前正在编写以下(未压缩)格式的非常大的文件:
1
2
1
1
...
每行有一个文本形式的整数,重复次数很多。
我正在使用C zlib stdio风格的接口从数组中写出数据:
gzFile file = gzopen("myfile.gz", "w");
for (i=0; i<nlines; i++)
gzprintf(file, "%d\n", array[i]);
gzclose(file);
由于重复程度高,压缩文件与源相比非常小(3.7GB低至5.3MB),但写入需要很长时间。
我不熟悉压缩算法或实现,但我担心用短字符串对gzprintf
进行大量(约20亿)调用可能会导致某种瓶颈。我尝试用gzbuffer
增加缓冲区大小,但这没什么效果。
我使用zlib的方式是否合适,并且在此应用程序中加速压缩是否有任何悬而未决的成果?
答案 0 :(得分:1)
您可以通过准备多行的内部缓冲区来减少系统调用次数。这将显着加快您的计划。例如,写信给stdout
而不是gzprintf()
:
#include <stdio.h>
#define ITEMS_PER_LINE 4
#define nlines 20
int main(){
char buffer [ITEMS_PER_LINE*2 + 1];
int array [nlines] = {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9};
int i, j;
char *cptr;
for (i=0; i<nlines; i+=ITEMS_PER_LINE) {
cptr = buffer;
for (j=0; j<ITEMS_PER_LINE; j++) {
if (i+j >= nlines) break;
cptr += sprintf (cptr, "%d\n", array[i+j]);
}
printf("%s", buffer);
//gzprintf(file, "%s", buffer);
}
return 0;
}
如果数字> = 10,显然buffer
需要更大。
答案 1 :(得分:1)
根据应用程序的确切细节,值得考虑使用带管道的外部gzip进程:
FILE *pipe = popen("gzip - > myfile.gz", "w");
for (i=0; i<nlines; i++) {
fprintf(pipe, "%d\n", array[i]);
}
pclose(pipe);
这样做的好处是,在多核计算机(现在大多数计算机)上,程序的处理和压缩可以在不同的核心上并行进行。
这是否是一个好主意将取决于许多因素,包括您的程序使用多少CPU:如果它真的只是从数组中读取值,可能没有太大的收益(或者实际上它可能会减慢由于涉及额外的IPC)。但是如果你正在做一些非常重要的处理,你可能会看到加速。
鉴于修改你的程序相对容易做到这一点,它绝对值得尝试(并测量 - 所有性能“增强”,总是可以衡量!)。
答案 2 :(得分:0)
您可以在gzopen的第二个参数中设置压缩级别和压缩方法。例如,以下将使用压缩级别4而不是默认值9。
gzopen("myfile.gz", "w4");