나는 30M 줄을 포함하는 큰 입력 파일을 가지고 있습니다 \r\n
. 나는 어리석은 일을 하고 read -r
모든 줄을 계산하는 속도를 비교하기로 결정했습니다( 두 문자 이상을 분할하는 것이 불가능해 보이기 때문에 xargs
첫 번째 줄을 제거 ). 내 두 명령은 다음과 같습니다.\r
xargs
time tr -d '\r' < input.txt | xargs -P 1 -d '\n' -I {} echo "{}" | wc -l
time while read -r p || [ -n "$p" ]; do echo "$p"; done < input.txt | wc -l
여기서 두 번째 해결책은많은서둘러요. 왜 그런 겁니까?
나는 이것이 파일의 줄 수를 계산하는 올바른 방법이 아니라는 것을 알고 있습니다. 이 질문은 단지 나의 관찰적 관심에서 나온 것입니다.
답변1
예, 예상한 대로 이는 실제로 xargs -P 1 -d '\n' -I {} echo "{}"
프로세스를 분기하고 각 입력 줄에 대해 상위 프로세스에서 종료될 때까지 기다리는 동안 하위 프로세스에서 독립적인 프로세스를 실행하는 기본 명령과 동일합니다.xargs -rd '\n' -n1
echo
echo
따라서 이는 동일한 쉘 프로세스에서 비효율적인 내장 기능과 모든 내장 기능을 사용하는 것보다 read
훨씬 더 많은 작업입니다 .echo
xargs
xargs
(적어도 일부 구성 및 최신 버전에서는) 프로세스를 분기하지 않고 내부적으로 busybox를 호출 하는 GNU 대신 busybox를 사용하면 루프보다 훨씬 빠르다 echo
는 것을 알 수 있습니다 .bash
보다 관련성이 높은 비교를 위해서는 다음을 비교해야 합니다.
tr -d '\r' | xargs -rd'\n' -n1
그리고
tr -d '\r' |
while IFS= read -r line || [ -n "$line" ]; do
/bin/echo "$line"
done
대부분의 시간이 프로세스를 분기하고 독립적으로 실행하는 데 소비되므로 비슷한 결과를 얻을 수 있습니다 echo
.
여기에서 출력 seq 3e7
및 측정 pv -al > /dev/null
( a
초당 평균 라인으로 측정된 처리량)과 관련하여 해결책을 얻었습니다.l
- busybox xargs는 1.12M/s입니다.
- 70k/s의 에코가 내장된 bash 루프
- GNU xargs는 860/s입니다.
- /bin/echo를 사용한 bash 루프의 경우 850/s