Você pode tentar escrever em 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;
}
Salvar em, por exemplo, wcl.c
, compilar, por exemplo, com gcc wcl.c -O2 -o wcl
e executar com
<yourFile ./wcl
Isso encontra novas linhas polvilhadas em um arquivo de 1 GB no meu sistema em cerca de 370 ms (execuções repetidas).
(O aumento dos tamanhos de buffer aumenta ligeiramente o tempo, o que é esperado - BUFSIZ deve estar próximo do ideal).
Isso é muito comparável ao ~ 380 ms que estou obtendo de wc -l
.
Mmaping me dá um tempo melhor de aproximadamente 280ms , mas é claro que tem a limitação de ser limitado a arquivos reais (sem FIFOS, sem entrada de terminal, etc.):
#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;
}
Eu criei meu arquivo de teste com:
$ dd if=/dev/zero of=file bs=1M count=1042
e adicionamos algumas novas linhas de teste com:
$ echo >> 1GB
e um editor hexadecimal.