"wc -l"보다 빠른 것이 필요합니다.

"wc -l"보다 빠른 것이 필요합니다.

1GB와 같은 대용량 파일의 경우 wc -l속도가 매우 느립니다. 특정 파일의 개행 수를 계산하는 더 빠른 방법이 있습니까?

답변1

당신은 시도 할 수 있습니다C로 작성:

#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(){
  char buf[BUFSIZ];
  int nread;
  size_t nfound=0;
  while((nread=read(0, buf, BUFSIZ))>0){
    char const* p;
    for(p=buf; p=memchr(p,'\n',nread-(p-buf)); nfound++,p++) {;}
  }
  if(nread<0) { perror("Error"); return 1; }
  printf("%lu\n", nfound);
  return 0;
}

예를 들어, wcl.c컴파일, 예를 들어, gcc wcl.c -O2 -o wcl실행하고 저장합니다.

<yourFile ./wcl

이것은 내 시스템에서 개행 문자로 가득 찬 1GB 파일을 발견했습니다.370밀리초(실행을 반복). (버퍼 크기를 늘리면 시간이 약간 늘어나는데 이는 예상한 대로입니다. BUFSIZ는 최적 값에 가까워야 합니다.) 비교가 많이 되더라구요~380밀리초나는 에서 왔습니다 wc -l.

Mmaping을 통해 더 나은 시간을 보냈습니다.280밀리초, 그러나 물론 실제 파일로 제한되는 제한 사항이 있습니다(FIFO 없음, 터미널 입력 없음 등).

#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
  struct stat sbuf;
  if(fstat(0, &sbuf)<0){ perror("Can't stat stdin"); return 1; }

  char* buf = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, 0/*stdin*/, 0/*offset*/);
  if(buf == MAP_FAILED){ perror("Mmap error"); return 1; } 

  size_t nread = sbuf.st_size, nfound=0;
  char const* p;
  for(p=buf; p=memchr(p,'\n',nread-(p-buf)); nfound++,p++) {;}

  printf("%lu\n", nfound);
  return 0;
}

다음 명령을 사용하여 테스트 파일을 만들었습니다.

 $ dd if=/dev/zero of=file bs=1M count=1042 

몇 가지 테스트 줄바꿈을 추가했습니다.

 $ echo >> 1GB 

그리고 16진수 편집기.

답변2

에 대한 호출 수를 줄임으로써 @pskocik이 제안한 솔루션을 개선할 수 있습니다 read. 하나 있다많은BUFSIZ1Gb 파일에서 블록을 읽기 위한 호출 수입니다. 일반적인 접근 방식은 버퍼 크기를 늘리는 것입니다.

  • 재미삼아 버퍼 크기를 10배 또는 100배 늘려보세요. 내 Debian 7에서는 BUFSIZ8192입니다. 원래 프로그램을 사용하면 이는 120,000개의 읽기 작업입니다. 아마도 1Mb 입력 버퍼를 100배로 줄일 여유가 있을 것입니다.
  • 보다 최적화된 접근 방식을 위해 애플리케이션은 단일 읽기 작업이 필요한 파일만큼 큰 버퍼를 할당할 수 있습니다. 이는 "작은" 파일에 충분합니다(일부 리더의 컴퓨터에는 1GB 이상이 있지만).
  • 마지막으로 할당 자체를 처리하는 메모리 매핑된 I/O를 사용해 볼 수 있습니다.

다양한 방법을 벤치마킹할 때 Linux와 같은 일부 시스템에서는 컴퓨터의 사용되지 않는 메모리 중 상당 부분을 디스크 캐시로 사용한다는 사실을 기억하실 것입니다. 얼마 전(약 20년 전,비열한 FAQ), 나는 텍스트 편집기에서 메모리 부족 상황을 처리하기 위해 개발한 (별로 좋지는 않은) 페이징 알고리즘의 예상치 못한 좋은 결과에 혼란스러웠습니다. 프로그램이 파일을 읽는 데 사용되는 메모리 버퍼에서 작동하기 때문에 매우 빠르게 실행되며, 파일을 다시 읽거나 쓸 때 속도 차이만 있다고 설명했습니다.

동일하게 적용됩니다 mmap(다른 경우에는 FAQ에 포함하기 위해 여전히 내 할 일 목록에 있으며 개발자는 디스크 캐싱이 개선의 실제 이유인 매우 좋은 결과를 보고했습니다). 벤치마크를 개발하려면 성능이 좋은(또는 나쁜) 이유를 분석하는 데 시간과 노력이 필요합니다.

추가 자료:

관련 정보