ksh93怎么这么快?

ksh93怎么这么快?

因此,一般来说,我倾向于寻求sed文本处理 - 特别是对于大文件 - 并且通常避免在 shell 本身中执行此类操作。

不过,我认为这可能会改变。我四处闲逛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酒吧为此,它们的模式匹配实现必须至少评估每行的开头和结尾。他们还必须根据否定模式验证第一个字符。这是一件简单的事情,但是......结果并不是我所期望的:

( 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。我之前用 shell 模式做了同样的事情,ksh但结果没有什么不同。

不管怎样,这是一个相当显着的差异——ksh超过sed了 10 倍。我之前读过 David Korn 编写了他自己的 io lib 并在其中实现了它ksh- 这可能是相关的? - 但我对此几乎一无所知。 shell 为何能做到如此出色?

对我来说更令人惊奇的是,它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

ksh这里节拍grep- 但并不总是 - 他们几乎是紧密相连的。不过还是很优秀了 ksh提供前瞻 -head的输入开始它的匹配。

我想,这似乎好得令人难以置信。这些命令在幕后有什么不同的作用?

哦,显然这里甚至没有子外壳:

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

答案1

ksh 不仅使用sfio但它使用自己的自定义内存分配器。

尽管如此,我的猜测是 sfio 在这种情况下有所作为。我只是尝试在 strace 下运行您的示例,可以看到 ksh 调用读/写约 200 次(65 KB 块),而 sed 调用读/写约 3400 次(4 KB 块)。使用 sed -u 我的笔记本电脑几乎融化了,读取是按字节完成的,写入是按行完成的。 Ksh 简单地使用 lseek。 Grep 使用读取约 400 次(32 KB 块)。

相关内容