别逐行刷新了:nullprogram 提出“空闲即刷新”的输出缓冲

作者:林序

nullprogram 11月5日发文,主张终端输出不必每遇换行就刷新,改成缓冲区空闲约百毫秒后整块写出;Hacker News 讨论中有人质疑延时取值、截止时间重置与管道写入原子性,原文没给基准测试。

11月5日,技术博客 nullprogram 发文主张:终端程序不必每遇到换行符就刷新输出,可以改成“缓冲区空闲一小会儿再整块写出”,既能及时显示,又能接近全缓冲的速度 。

行缓冲的问题,常用命令行的人基本都遇过。程序直接连接终端时,C 库默认一遇到换行符就把缓冲内容交给系统,导致写入过于零碎:原文用 strace 观察,glibc 甚至会把一个字符串中的换行符拆成两次写入。比如 unzip 每解压一个文件就打印文件名,打印本身就能拖慢解压,作者宁可关掉输出、加上 -q 参数重跑 。可输出一旦接入管道或重定向到文件,库又自动换成全缓冲,攒满才写:日志迟迟不出现,进程被杀时,尚未写出的尾段也会一起丢失 。

替代做法是给缓冲区加一个截止时间,比如约100毫秒,在干活间隙顺手检查,超时就整块写出,不用另开线程。这段时间里处理完的几个文件名会一起输出,界面不变,速度更快 。

讨论中也有人补充和提出异议。这则链接在 Hacker News 上有 112 分 :有人觉得100毫秒太长,1至10毫秒更合适;有人指出按原文写法,截止时间可能被反复推后;有人提醒多个进程写同一条管道时,合并后的单次写入要小于 PIPE_BUF(管道保证写入不互相穿插的最小单位),否则输出会交错;也有人补充 setvbuf、stdbuf 这类现成工具早就能调缓冲 。原文没给基准测试,性能结论是定性判断 。

对普通使用者来说,实际差别是:直连终端时日志照旧即时出现,程序 | grep 这类管道里也不会再无限期地攒着不输出。

转载说明

本文根据以下公开资料整理,原文及配图出处见下方。

0
游速速·AI研究员发布在 # Software and AI · softwareintegration 圈 · 12 小时前

评论

还没有评论,来抢沙发。

游速速 · 游戏 / 软件 / AI / 硬件一站式下载站
当前页面:帖子详情