가능한 가장 빠른 grep


80

grep가능한 한 빨리 만들 수있는 팁이 있는지 알고 싶습니다 . 가능한 가장 빠른 방법으로 검색 할 수있는 텍스트 파일 기반이 상당히 많습니다. -i옵션을 제거 할 수 있도록 모두 소문자로 만들었습니다 . 이렇게하면 검색이 훨씬 빨라집니다.

또한 -F-P모드가 기본 모드보다 빠르다 는 것을 알게되었습니다 . 검색 문자열이 정규식이 아닌 경우 (단지 일반 텍스트) 전자를 사용하고 정규식이 포함 된 경우 후자를 사용합니다.

누구든지 속도 향상에 대한 경험이 grep있습니까? 특정 플래그를 사용하여 처음부터 컴파일하거나 (저는 Linux CentOS에 있습니다) 특정 방식으로 파일을 구성하거나 어떤 방식 으로든 검색을 병렬로 만들 수 있습니까?


1
이것은 항상 동일한 파일 세트입니까? 를 사용하여 동일한 (대용량) 파일 세트를 검색하는 경우 grep, 해당 파일 을 적절하게 인덱싱 할 솔루션을 찾을 때입니다 ( "최상의"솔루션은 파일 종류에 따라 달라집니다).
FatalError

예, 동일한 파일 세트입니다. lucene과 같은 전체 텍스트 솔루션이 성능을 향상시킬 것이라고 생각하십니까? 일반적으로 약 2 억 5 천만 단어의 총 단어 수에 대해 2,500 개의 파일 (각 문학 책)을 검색하는 데 약 30/40 초가 걸립니다.
pistacchio

1
"...or maybe make the search parallel in some way?"이것에 대해 듣고 정말 기쁩니다. grep완전히 병렬로 작동 할 수 있어야하지만 검색이 여전히 I / O 바운드 일 수 있습니다.
Conrad.Dean 2012 년

2
사용해 보셨습니까 ack-grep?
omuraliev MEDER

2
ack-grep또는 더 나은 Ag를 사용하십시오 ! geoff.greer.fm/2011/12/27/the-silver-searcher-better-than-ack
니콜라스 윌슨에게

답변:


104

다음과 함께 사용하는 방법에 대한 예제가 포함 GNU parallel을 사용해보십시오 .grep

grep -r디렉토리를 통해 반복적으로 greps. 멀티 코어 CPU에서 GNU parallel는 종종이 속도를 높일 수 있습니다.

find . -type f | parallel -k -j150% -n 1000 -m grep -H -n STRING {}

그러면 코어 당 1.5 개의 작업이 실행되고 grep.

큰 파일의 경우 --pipe--block인수를 사용하여 입력을 여러 청크로 분할 할 수 있습니다 .

 parallel --pipe --block 2M grep foo < bigfile

SSH를 통해 여러 머신에서 실행할 수도 있습니다 (비밀번호를 피하기 위해 ssh-agent가 필요함).

parallel --pipe --sshlogin server.example.com,server2.example.net grep foo < bigfile

5
--color=alwaysgrep 색상을 보존하기 위해 사용 (파이프에서도 grep을 사용할 때마다
Jim

2
술어 find가 있으면 -print0(대부분의 경우)를 사용하는 것이 좋습니다 find . -type f -print0 | parallel -0 -k …. 내 인스턴스는 man(1) parallel실제로 이것을 말합니다. 또한 globstar특정 파일 패턴을 shopt -s globstar; parallel -k -j150% -n 1000 -m fgrep -H -n STRING ::: **/*.c
추구

3
@WilliamPursell 액세스 cat하려는 경우 유용하게 사용할 sudo수 있습니다.bigfile
Jayen 2015 년

2
코어 당 1.5 개의 작업을 설정하는 이유는 무엇입니까? 코어 당 하나의 작업이 아닌 이유는 무엇입니까?
JohnGalt

2
@JohnGalt 종종 디스크 I / O가 프로세스 중 하나를 중단시킵니다. 코어보다 몇 개 더 시작하면 일부 작업이 데이터를 기다리고 있더라도 모든 코어에 대해 수행 할 작업이 있습니다. 150 %를 조정하여 시스템에서 가장 잘 작동하는 것을 확인하십시오.
Ole Tange

70

매우 큰 파일을 검색하는 경우 로케일을 설정하면 정말 도움이 될 수 있습니다.

GNU grep은 UTF-8보다 C 로켈에서 훨씬 더 빠릅니다.

export LC_ALL=C

1
인상적이며이 단일 라인이 2 배의 속도를 제공하는 것처럼 보입니다.
Fedir RYKHTIK

누군가 이것이 이유를 설명 할 수 있습니까?
Robert E Mealey 2014

5
"다중 바이트 문자 비교 대 단순한 바이트 비교"<오른쪽 오른쪽 오른쪽 내 상사 ... 말한다
로버트 E Mealey

7
따라서 이것은 정확히 안전하지 않습니다. 특히 패턴 일치 (단순한 문자열 일치가 아닌)이거나 파일의 내용이 ASCII가 아닌 경우에는 더욱 그렇습니다. 어떤 경우에는 여전히 가치가 있지만주의해야합니다.
Robert E Mealey 2014

@RobertEMealey "단순"대신 "싱글"이라고 했나요?
Elijah Lynn

12

Ripgrep은 이제 가장 빠르다고 주장합니다.

https://github.com/BurntSushi/ripgrep

기본적으로 병렬 처리도 포함

 -j, --threads ARG
              The number of threads to use.  Defaults to the number of logical CPUs (capped at 6).  [default: 0]

README에서

Rust의 정규식 엔진 위에 구축되었습니다. Rust의 정규식 엔진은 유한 오토마타, SIMD 및 공격적인 리터럴 최적화를 사용하여 검색을 매우 빠르게 만듭니다.


이것은 엄청나게 빠릅니다!
비트


4

엄격하게 코드 개선은 아니지만 2 백만 개 이상의 파일에서 grep을 실행 한 후 도움이되는 것으로 나타났습니다.

저렴한 SSD 드라이브 (120GB)로 작업을 옮겼습니다. 약 $ 100에 정기적으로 많은 파일을 처리하는 경우 저렴한 옵션입니다.


3

어떤 파일에 문자열이 포함되어 있는지 신경 쓰지 않는다면 읽기grepping 을 두 개의 작업으로 분리 할 수 있습니다 grep. 각 작은 파일에 대해 한 번씩 여러 번 생성하는 데 비용이 많이들 수 있기 때문 입니다.

  1. 매우 큰 파일이 하나있는 경우 :

    parallel -j100% --pipepart --block 100M -a <very large SEEKABLE file> grep <...>

  2. 많은 작은 압축 파일 (inode별로 정렬 됨)

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j80% --group "gzcat {}" | parallel -j50% --pipe --round-robin -u -N1000 grep <..>

나는 보통 최대 처리량을 위해 lz4로 파일을 압축합니다.

  1. 일치하는 파일 이름 만 원하는 경우 :

    ls -i | sort -n | cut -d' ' -f2 | fgrep \.gz | parallel -j100% --group "gzcat {} | grep -lq <..> && echo {}


2

Sandro의 응답을 바탕으로 그가 여기 에서 제공 한 참고 자료를 살펴보고 BSD grep 대 GNU grep을 가지고 놀았습니다. 내 빠른 벤치 마크 결과는 GNU grep이 훨씬 빠릅니다.

그래서 원래 질문 인 "가장 빠른 grep"에 대한 저의 추천 : BSD grep (예 : MacOS의 기본값) 대신 GNU grep을 사용하고 있는지 확인하십시오.


250MB .sql 덤프 파일을 검색하는 동안 8GB, 6 코어 Linode보다 13 형 MacBook Pro에서 BSD Grep을 더 빠르게 표시하고 있습니다. 6 초 대 25 초
AnthumChris

2

개인적으로 grep 대신 ag (silver searcher)를 사용하며 훨씬 빠르며 병렬 및 파이프 블록과 결합 할 수도 있습니다.

https://github.com/ggreer/the_silver_searcher

업데이트 : 이제 사용 사례에 따라 ag보다 빠른 https://github.com/BurntSushi/ripgrep 을 사용합니다.


나는 이것에서 버그를 발견했다. 때로는 트리 깊숙이 들어 가지 않고 grep이 결과를 표시하지만 ag는 표시하지 않는 경우가 있습니다. 속도에 대한 정확성은 타협 할 수 없습니다.
username_4567

1
당신은 그들의 github 계정에서 이슈를 열고 그것을보고해야합니다 (나는 그렇게 할 것이지만 나는 그것을 복제 할 수 없습니다), 지금까지 나는 어떤 부정확성을 발견하지 못했습니다. 확실히 그들이 이것을 분류 할 것이고 네 당신이 옳습니다. 저는 전적으로 동의합니다 : 정확성이 먼저입니다.
Jinxmcg

1

하나의 큰 파일에서 검색 (특히 패턴 변경)을 위해 grep을 사용하는 것이 더 빠르다는 것을 알게 된 한 가지는 병렬 플래그와 함께 split + grep + xargs를 사용하는 것입니다. 예를 들면 :

my_ids.txt라는 큰 파일에서 검색하려는 ID 파일이 있음 bigfile의 이름 bigfile.txt

split을 사용하여 파일을 여러 부분으로 분할합니다.

# Use split to split the file into x number of files, consider your big file
# size and try to stay under 26 split files to keep the filenames 
# easy from split (xa[a-z]), in my example I have 10 million rows in bigfile
split -l 1000000 bigfile.txt
# Produces output files named xa[a-t]

# Now use split files + xargs to iterate and launch parallel greps with output
for id in $(cat my_ids.txt) ; do ls xa* | xargs -n 1 -P 20 grep $id >> matches.txt ; done
# Here you can tune your parallel greps with -P, in my case I am being greedy
# Also be aware that there's no point in allocating more greps than x files

제 경우에는 17 시간 작업을 1 시간 20 분 작업으로 줄였습니다. 효율성에 대한 일종의 종 곡선이 있다고 확신하며 사용 가능한 코어를 살펴 보는 것은 아무런 효과가 없지만 위에서 언급 한 내 요구 사항에 대한 위의 설명보다 훨씬 나은 솔루션이었습니다. 이것은 대부분 (리눅스) 네이티브 도구를 사용하는 데있어 스크립트 병렬에 비해 추가적인 이점이 있습니다.


0

가능한 경우 cgrep은 grep보다 훨씬 빠를 수 있습니다.


0

MCE 1.508에는 많은 C 바이너리를 지원하는 이중 청크 수준 {file, list} 래퍼 스크립트가 포함되어 있습니다. agrep, grep, egrep, fgrep 및 tre-agrep.

https://metacpan.org/source/MARIOROY/MCE-1.509/bin/mce_grep

https://metacpan.org/release/MCE

-i가 빠르게 실행되도록하려면 소문자로 변환 할 필요가 없습니다. --lang = C를 mce_grep에 전달하기 만하면됩니다.

출력 순서가 유지됩니다. -n 및 -b 출력도 올 바릅니다. 불행히도이 페이지에 언급 된 GNU 병렬의 경우는 그렇지 않습니다. 저는 GNU Parallel이 여기서 일하기를 정말로 바랐습니다. 또한 mce_grep은 바이너리를 호출 할 때 하위 쉘 (sh -c / path / to / grep)을 수행하지 않습니다 .

또 다른 대안은 MCE에 포함 된 MCE :: Grep 모듈입니다.


해당 도구의 작성자 인 면책 조항을 제공해야합니다.
FractalSpace

0

원래 주제와 약간의 차이 : googlecodesearch 프로젝트의 색인화 된 검색 명령 줄 유틸리티는 grep : https://github.com/google/codesearch 보다 훨씬 빠릅니다 .

컴파일 한 후 ( golang 패키지가 필요함) 다음을 사용하여 폴더를 색인화 할 수 있습니다.

# index current folder
cindex .

색인은 아래에 생성됩니다. ~/.csearchindex

이제 다음을 검색 할 수 있습니다.

# search folders previously indexed with cindex
csearch eggs

나는 여전히 grep을 통해 결과를 파이핑하여 색상이 지정된 일치를 얻습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.