2011-08-08 51 views
22

是否有存在较大的性能差异:管与临时文件

  • 过程的书写到一个临时文件,进程B读数文件
  • 进程A写入一个管道,而进程B读从该管

我很想知道Windows和* nix的答案是什么。

编辑:我应该问:缓冲区缓存是否消除了临时文件和管道之间的区别?

回答

29

一个很大的区别是,使用管道,进程A和B可以同时运行,以便B在A完成生产之前处理来自A的输出。此外,管道的大小是有限的,所以A将不能产生比B消耗的数据更多的数据;它会等待B赶上。

如果数据量很大,那么写入临时文件涉及磁盘活动,即使仅用于创建并销毁该文件。数据可能会留在内存缓冲池中 - 所以没有磁盘I/O - 即使是出乎意料的大文件。写入管道“从不”涉及写入磁盘。

+0

+1 - 你唯一没有明确回答的是,对Windows和Unix来说这是一样的。 (我怀疑会有什么区别,但它是在原来的问题。) – OverZealous

+0

@OverZealous:公平点。我的答案比Windows更适用于Unix。 Windows有时会获得与Unix略有不同的结果,但我认为我的观点在Windows上是有效的。我不确定Windows管道从不涉及写入磁盘。 –

8

最大的区别在于第一种方法实际上使用磁盘存储,而管道将使用内存(除非您真的很迂腐并开始考虑交换空间)。

性能方面,内存比磁盘(几乎总是)要快。对于所有操作系统而言,这应该是正确的。

使用临时文件的唯一时间是真正有意义的是,如果进程B必须检查多遍数据(如某些种类的视频编码)。对于这种用途,整个数据流将需要缓冲,如果有足够的数据是,它可能会否定内存优势。因此,对于多遍(搜索绑定)操作,请使用临时文件。

+1

请参阅,我想知道磁盘缓存是否会消除管道和临时文件之间的区别。 –

+2

最大的问题是:当进程A写入一个*文件*时,进程B不会做任何事情(直到完成)。当进程A写入* pipe *时,进程B可以立即开始读取。所以,即使操作系统缓存了整个文件,你仍然需要等到A完成。是的,可以“流”一个文件(就像tail -f一样),但是在你看到任何东西之前,你仍然必须等待A刷新。所以再次使用管道,除非你需要寻找。 –

+0

@Chris我不认为进程B必须等到直到进程A已经刷新到文件。如果进程B甚至在进程A完成之前开始读取文件,则没有发生任何错误。进程B的请求将从缓冲区本身完成。它不需要等到更改提交到磁盘。还是我误解了? –

2

除非我理解管道完全离开墙壁,否则答案是肯定的。

写入临时文件涉及磁盘访问以及相关的开销。

写入管道,并从中读取,发生在内存中。快多了。

0

我认为一个实际的答案可能会有所帮助。我正在加速优化我使用的脚本大约4个步骤。我将其设置为使用管道和非管道方法。这是在Windows 7 64位下。

我得到了3%的减速不使用管道。对我而言,这是值得的,因为现在我可以在每一步之间停下来并更新窗口标题,而当窗口标题完全是一个命令时,我无法更新窗口标题。个人而言,我会以3%的命中率打开窗口标题。为了好奇,我打量一个大于20M的文件,然后将它传递给专门的perl脚本来修改结果,然后使用SORT.EXE中的窗口对它们进行排序,然后使用cygwin的UNIQ.EXE对它们进行uniq'ing,然后重新刷新这些相同的结果以获得基于ANSI的grep结果着色。大部分时间都花在分类阶段。

+0

你在讨论什么窗口标题?你在答案中提到的流程是否属于这一部分? – Cristik

+0

是的,我有一些脚本需要几秒钟的时间,所以他们更新窗口标题的命令行窗口给我看的东西[最小化时],并没有得到ntsy,它可能不会做任何事情:) – ClintL

+0

注意排序命令是并发的阻塞程序。在读取完所有输入之前,它不能产生任何输出。鉴于这一点以及您的评论大部分时间都是在分类阶段进行的,因此您在管道和非管道控制流之间的性能变化非常小并不奇怪。如果您的管道没有阻塞排序,那么您可能会从增加的并发性中显示更大的处理时间节省。 –