我编写了这个简单的脚本,它每秒生成一个输出行(generator.sh):
\nfor i in {0..5}; do echo $i; sleep 1; done\nRun Code Online (Sandbox Code Playgroud)\nraku 程序将启动此脚本并在出现这些行时立即打印它们:
\nmy $proc = Proc::Async.new("sh", "generator.sh");\n$proc.stdout.tap({ .print });\nmy $promise = $proc.start;\nawait\xc2\xa0$promise;\nRun Code Online (Sandbox Code Playgroud)\n一切都按预期进行:每一秒我们都会看到一条新线。但是让我们用 raku 重写生成器(generator.raku):
\nfor 0..5 { .say; sleep 1 }\nRun Code Online (Sandbox Code Playgroud)\n并将程序的第一行更改为:
\nmy $proc = Proc::Async.new("raku", "generator.raku");\nRun Code Online (Sandbox Code Playgroud)\n现在出了点问题:首先我们看到输出的第一行(“0”),然后长时间停顿,最后我们看到输出的所有剩余行。
\n我尝试通过命令获取生成器的输出script:
script -c \'sh generator.sh\' script-sh\nscript -c \'raku generator.raku\' script-raku\nRun Code Online (Sandbox Code Playgroud)\n在十六进制编辑器中分析它们,看起来它们是相同的:在每个数字之后,字节0d和0a后面。
为什么使用看似相同的发电机会产生如此大的差异?我需要理解这一点,因为我将启动一个外部程序并在线处理其输出。
\nJon*_*ton 19
为什么使用看似相同的发电机会产生如此大的差异?
首先,关于标题,问题不在于阅读方面,而在于写作方面。
Raku 的 I/O 实现会检查 STDOUT 是否附加到TTY。如果是 TTY,任何输出都会立即写入输出句柄。但是,如果它不是 TTY,那么它将应用缓冲,这会显着提高性能,但代价是输出被缓冲区大小分块。
如果更改generator.raku为禁用输出缓冲:
$*OUT.out-buffer = False; for 0..5 { .say; sleep 1 }
Run Code Online (Sandbox Code Playgroud)
然后立即可以看到输出。
我需要理解这一点,因为我将启动一个外部程序并在线处理其输出。
只有当您启动的外部程序也有这样的缓冲策略时,这才会成为一个问题。
| 归档时间: |
|
| 查看次数: |
216 次 |
| 最近记录: |