ksh93이 왜 그렇게 빠른가요?

ksh93이 왜 그렇게 빠른가요?

따라서 일반적으로 저는 텍스트 처리(특히 대용량 파일의 경우)를 찾는 경향이 sed있으며 일반적으로 셸 자체에서 이러한 작업을 수행하는 것을 피합니다.

그러나 나는 이것이 바뀔 수 있다고 생각합니다. 나는 이리저리 살펴 man ksh보다가 이것을 발견했습니다.

<#pattern     Seeks forward to the beginning of the
              next line containing pattern.

<##pattern    The same as <# except that  the  por‐
              tion  of  the file that is skipped is
              copied to standard output.

실제 실용성에 회의적이어서 한번 시도해 보기로 결정했습니다. 나는 그랬다:

seq -s'foo bar
' 1000000 >file

...다음과 같은 백만 행의 데이터에 대해:

1foo bar
...
999999foo bar
1000000

...그리고 sed다음과 비교해보세요:

p='^[^0-8]99999.*bar'
for c in "sed '/$p/q'" "ksh -c ':<##@(~(E)$p)'"    
do </tmp/file eval "time ( $c )"
done | wc -l

따라서 두 명령 모두 달성해야 합니다.999999푸바이렇게 하려면 패턴 일치 구현에서 최소한 각 줄의 시작과 끝을 평가해야 합니다. 또한 음수 패턴에 대해 첫 번째 문자의 유효성을 검사해야 합니다. 간단한 일이지만... 결과는 내가 기대했던 것과 다릅니다.

( sed '/^[^0-8]99999.*bar/q' ) \
    0.40s user 0.01s system 99% cpu 0.419 total
( ksh -c ':<##@(~(E)^[^0-8]99999.*bar)' ) \
    0.02s user 0.01s system 91% cpu 0.033 total
1999997

ksh여기서는 ERE와 sedBRE가 사용됩니다. 이전에 쉘 모드로 동일한 작업을 수행했지만 ksh결과는 다르지 않았습니다.

ksh그럼에도 불구하고, 이는 10배가 넘는 매우 중요한 차이입니다 sed. 이전에 David Korn이 자신의 io lib를 작성하고 이를 구현했다는 내용을 읽은 적이 있습니다 ksh. 관련이 있을 수 있습니까? - 하지만 나는 그것에 대해 거의 아무것도 모릅니다. 쉘은 왜 그렇게 잘 작동합니까?

나에게 더욱 놀라운 점은 ksh사용자가 요청한 위치에 오프셋을 남겨둔다는 것입니다. 얻기 위해(거의)또한(암소 비슷한 일종의 영양) sed당신은 사용해야합니다 -u-아주 느린.

다음은 grepv. ksh테스트입니다.

1000000         #grep + head
( grep -qm1 '^[^0-8]99999.*bar'; head -n1; ) \
    0.02s user 0.00s system 90% cpu 0.026 total
999999foo bar   #ksh + head
( ksh -c ':<#@(~(E)^[^0-8]99999.*bar)'; head -n1; )  \
    0.02s user 0.00s system 73% cpu 0.023 total

ksh여기서 비트는 grep- 항상 그런 것은 아니지만 - 거의 밀접하게 연결되어 있습니다. 하지만 여전히 훌륭해요그리고 kshhead미리보기 시작을 위한 입력 제공앞으로일치합니다.

사실이라고 하기엔 너무 좋은 것 같다고 생각했어요. 이러한 명령은 뒤에서 무엇을 다르게 수행합니까?

아, 그리고 여기에는 서브쉘도 없는 것 같습니다.

ksh -c 'printf %.5s "${<file;}"'

답변1

ksh는 다음을 사용하는 것뿐만 아니라SFIO그러나 자체 사용자 정의 메모리 할당자를 사용합니다.

그래도 내 생각에는 sfio가 이 경우에 차이를 만든다는 것입니다. 방금 strace에서 예제를 실행해 보았는데 ksh가 약 200회(65KB 블록) 읽기/쓰기를 호출하고 sed가 약 3400회(4KB 블록) 읽기/쓰기를 호출하는 것을 볼 수 있습니다. sed -u를 사용하면 내 노트북이 거의 녹아서 읽기는 바이트 단위로, 쓰기는 라인 단위로 이루어집니다. Ksh는 단순히 lseek를 사용합니다. Grep은 약 400개의 읽기(32KB 블록)를 사용합니다.

관련 정보