ZLIB чрезвычайно медленно? - PullRequest
3 голосов
/ 14 мая 2010

Я занимаюсь тем, что разбираю огромные глобусы текстовых файлов, и проверял, какой метод ввода использовать.

Нет большой разницы в использовании c ++ std :: ifstreams vs c FILE,

Согласно документации zlib, он поддерживает несжатые файлы и будет читать файл без распаковки.

Я вижу разницу от 12 секунд для non-zlib до более чем 4 минут для zlib.h

Это я тестировал, делая несколько запусков, так что это не проблема кеша диска.

Я неправильно использую zlib?

спасибо

#include <zlib.h>
#include <cstdio>
#include <cstdlib>
#include <fstream>
#define LENS 1000000


size_t fg(const char *fname){
  fprintf(stderr,"\t-> using fgets\n");
  FILE *fp =fopen(fname,"r");
  size_t nLines =0;
  char *buffer = new char[LENS];
  while(NULL!=fgets(buffer,LENS,fp))
    nLines++;

  fprintf(stderr,"%lu\n",nLines);
  return nLines;
}

size_t is(const char *fname){
  fprintf(stderr,"\t-> using ifstream\n");
  std::ifstream is(fname,std::ios::in);
  size_t nLines =0;
  char *buffer = new char[LENS];
  while(is. getline(buffer,LENS))
    nLines++;

  fprintf(stderr,"%lu\n",nLines);
  return nLines;
}

size_t iz(const char *fname){
  fprintf(stderr,"\t-> using zlib\n");
  gzFile fp =gzopen(fname,"r");
  size_t nLines =0;
  char *buffer = new char[LENS];
  while(0!=gzgets(fp,buffer,LENS))
    nLines++;

  fprintf(stderr,"%lu\n",nLines);
  return nLines;
}

int main(int argc,char**argv){
  if(atoi(argv[2])==0)
    fg(argv[1]);
  if(atoi(argv[2])==1)
    is(argv[1]);
  if(atoi(argv[2])==2)
    iz(argv[1]);

}

1 Ответ

3 голосов
/ 15 мая 2010

Полагаю, вы используете zlib-1.2.3. В этой версии gzgets () фактически вызывает gzread () для каждого байта. Вызов gzread () таким образом приводит к большим накладным расходам. Вы можете сравнить процессорное время вызова gzread (gzfp, buffer, 4096) один раз и вызова gzread (gzfp, buffer, 1) в течение 4096 раз. Результат тот же, но время процессора сильно отличается.

Что вам нужно сделать, это реализовать буферизованный ввод / вывод для zlib, читая данные размером ~ 4 КБ в чанке с помощью одного вызова gzread () (подобно тому, что fread () делает для read ()). Последняя версия zlib-1.2.5 значительно улучшена в gzread / gzgetc / .... Вы также можете попробовать это. Поскольку он выпущен совсем недавно, я не пробовал лично.

EDIT:

Я попробовал zlib-1.2.5 только сейчас. gzgetc и gzgets в 1.2.5 намного быстрее, чем в 1.2.3.

...