ksh93은 얼마나 빠릅니까? 최대 999999foo bar가 되어야하며 패턴

따라서 일반적으로 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

따라서 두 명령 모두 최대 999999foo bar가 되어야하며 패턴 일치 구현은 최소한 각 행의 시작과 끝을 평가해야합니다. 또한 부정 된 패턴에 대해 첫 번째 문자를 확인해야합니다. 이것은 간단한 일이지만 … 결과는 내가 기대 한 것이 아닙니다.

( 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성능이 뛰어을 sed10 회 이상. David Korn은 자신의 io lib를 작성하여 구현하기 전에 읽었습니다. ksh아마도 관련이 있습니까? -그러나 나는 그것에 대해 아무것도 알지 못한다. 껍질이 어떻게 그렇게 잘합니까?

나에게 더 놀라운 것은 ksh실제로 당신이 그것을 요구하는 곳에 오프셋을 남겨 두는 것입니다. 얻으려면 (거의) 같은 아웃 (GNU)를 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

kshgrep여기에 이길 수 있지만 항상 그런 것은 아닙니다. 그럼에도 불구하고, 그것은 꽤 좋은입니다, 그리고 ksh 내다 제공 – head의 입력을 시작 하기 전에 의 일치합니다.

사실 너무 좋은 것 같아요. 이 명령들은 후드에서 어떻게 다르게 작동합니까?

아, 그리고 분명히 여기에도 서브 쉘이 없습니다 :

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


답변

ksh는 sfio를 사용할 뿐만 아니라 자체 커스텀 메모리 할당자를 사용합니다.

그럼에도 불구하고, 내 생각에 sfio는이 경우에 차이를 만듭니다. 방금 strace에서 예제를 실행하려고 시도했으며 ksh가 ~ 200 번 (65 KB 블록) 읽기 / 쓰기를하는 동안 sed가 ~ 3400 번 (4 KB 블록)을 수행한다는 것을 알 수 있습니다. sed -u 내 랩톱이 거의 녹 으면 바이트 당 읽기가 수행되고 라인 당 쓰기가 수행됩니다. Ksh simple은 lseek를 사용합니다. Grep은 ~ 400 회 읽기 (32KB 블록)를 사용합니다.