【发布时间】:2012-03-27 20:13:09
【问题描述】:
一段时间以来,我一直在使用以下代码将 perl 脚本的输出写入文件:
open( OUTPUT, ">:utf8", $output_file ) or die "Can't write new file: $!";
print OUTPUT "First line I want printed\n";
print OUTPUT "Another line I want printing\n";
close(OUTPUT);
这很有效,并且比我最初使用“say”而不是 print 的方法更快(感谢 NYTProf 启发我!)
但是,我当前的脚本循环了数十万行,并且使用此方法需要花费数小时才能运行,而 NYTProf 将矛头指向我的数千个“打印”命令。所以,问题是... 有更快的方法吗?
其他可能相关的信息... Perl 版本:5.14.2(在 Ubuntu 上)
相关脚本的背景... 多个'|'分隔的平面文件被读入散列,每个文件都有某种从一个到另一个的主键匹配条目。我正在处理这些数据,他们将它们组合到一个文件中以导入另一个系统。
输出文件大约有 300 万行,在向该文件写入大约 30,000 行后,程序开始明显变慢。 (一点点阅读似乎指向用完其他语言的写入缓冲区,但我找不到关于 perl 的任何信息?)
编辑:我现在尝试在 open() 语句之后添加以下行,以禁用打印缓冲,但程序在第 30,000 行左右仍然变慢。
OUTPUT->autoflush(1);
【问题讨论】:
-
autoflush会减慢您的输出速度,而不是加快输出速度。它强制在每个print语句中将数据写入磁盘,而不是等待 IO 缓冲区填满。是什么让您认为问题在于输出的速度?我认为这更有可能是在准备数据时所做的工作。我建议您尝试禁用打印语句,看看您的程序在没有输出的情况下如何执行。 -
试试 syswrite(OUTPUT, "..."); .它比 STDOUT 的打印语句更快。
-
@Nick:
syswrite本身,没有任何用户编码的缓冲,将具有与autoflush类似的效果,并强制对每条记录进行磁盘写入。编写一个自制的输出缓冲系统与syswrite一起使用似乎不太可能加快速度,但我想这是可能的。 -
@Ashimema 您几乎可以肯定专注于错误的事情。考虑您的算法、数据结构和内存使用情况。缓慢可能存在于那里,而不是 Perl 高效写入文件的能力。
-
这真的是 Unicode 数据,还是只是 ASCII?