读写操作:比你想象的更不对称
Reading and writing are less symmetric than you (probably) think
读写操作看似对称,实则存在关键差异。读取时,错误会在返回前被捕获;而写入时,由于缓冲机制,错误往往被延迟报告,甚至直到关闭文件时才发现。用户空间缓冲、内核缓冲缓存、RAID控制器缓存等多层缓存让写入操作变得复杂。即使检查了write的返回值,数据可能仍未真正写入磁盘,需调用fsync确保数据持久化。更棘手的是,元数据可能未同步,导致数据虽在磁盘却不可见。这些细节常被忽视,却关乎数据安全性。
写入侧的缓冲要棘手得多,因为它延迟了实际写入和错误报告,而这正是大多数程序员本应了解却通常忽略的。
HN 评论区
19- Pannoniae
很棒的文章 :D 其实这个兔子洞还能挖得更深,因为读取端的缓冲几乎总是有益的,但读取往往比写入对延迟敏感得多。这就引出了一个悖论:增大缓冲区大小/通过 mmapping 预取更多内容,反而可能因为增加的延迟导致性能更差。而减小缓冲区大小也可能产生同样的效果,因为会发出更多调用,所以为了在读取端榨取最优的吞吐量/延迟比,你必须针对每个工作负载进行调优……或者干脆试几种不同的缓冲区大小,看看哪个效果更好。
写入则恰恰相反,它们通常不是 RAW(读后写),而是“发射后不管”(fire and forget),所以你不太在乎延迟,但你非常在乎写入是否真正到达……这又是两个相互竞争的参数,因为写入批处理得越多,速度越快,但发生撕裂写入(torn write)或数据丢失的风险就越大。而且与读取不同,写入在应用层不是幂等的,所以理想情况下,你希望有一些逻辑能原子性地写入有意义的数据量,这样即使系统崩溃也不会导致数据撕裂。
不过在实践中,几乎没人真的这么做,但这确实是个有趣的思考 :D
- 1317
哦,我还以为这篇是关于语言和大脑工作原理的,说实话那篇文章听起来更有趣,抱歉。
- vatsachak
即使在 CPU 缓存层面这也是成立的,所以这个问题很可能会一直向下渗透。
例如,Jon G 在 Jane Street 做过一次演讲,讲述了他遇到的一个神秘的性能问题,后来被归因于多个核心争夺同一缓存行。