使用gzprintf进行高效的gzip编写

时间:2014-12-10 12:46:52

标签: c zlib

上下文

我目前正在编写以下(未压缩)格式的非常大的文件:

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的方式是否合适,并且在此应用程序中加速压缩是否有任何悬而未决的成果?

3 个答案:

答案 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");