将此标记为已回答并围绕速度问题真正出现的地方开始一个更简单的主题
感谢您迄今为止的所有评论,非常有用
我有大约 40M 的 XML 文件分布(不均匀)。60K 子目录,结构基于 10 位数字拆分,因此:
12/34/56/78/90/files.xml
我有一个 perl 脚本,它针对文件运行,将单个字段的值拉出并打印值和文件名。Perl 脚本包含在一个 bash 脚本中,该脚本在深度 2 的所有目录列表中运行最多 12 个并行实例,然后遍历每个实例并在找到它们时在底层处理文件。
从多个运行中取出磁盘缓存,进程的 unix 时间返回大约:
real 37m47.993s
user 49m50.143s
sys 54m57.570s
我想将其迁移到 python 脚本(作为学习练习和测试),因此创建了以下内容(在大量阅读各种 python 方法之后):
import glob, os, re
from multiprocessing import Pool
regex = re.compile(r'<field name="FIELDNAME">([^<]+)<', re.S)
def extractField(root, dataFile):
line = ''
filesGlob = root + '/*.xml'
global regex
for file in glob.glob(filesGlob):
with open(file) as x:
f = x.read()
match = regex.search(f)
line += file + '\t' + match.group(1) + '\n'
dataFile.write(line)
def processDir(top):
topName = top.replace("/", "")
dataFile = open('data/' + topName + '.data', 'w')
extractField(top, dataFile)
dataFile.close()
filesDepth5 = glob.glob('??/??/??/??/??')
dirsDepth5 = filter(lambda f: os.path.isdir(f), filesDepth5)
processPool = Pool(12)
processPool.map(processDir, dirsDepth5)
processPool.close()
processPool.join()
但是无论我在运行它时如何对内容进行切片,unix time 都会给我这样的结果:
real 131m48.731s
user 35m37.102s
sys 48m11.797s
如果我在一个线程中针对一个小子集(最终被完全缓存)同时运行 python 和 perl 脚本,那么就没有磁盘 io(根据 iotop),那么脚本运行的时间几乎相同。
到目前为止,我能想到的唯一结论是,文件 io 在 python 脚本中的效率远低于在 perl 脚本中的效率,因为似乎是 io 导致了问题。
所以希望这是足够的背景,我的问题是我是在做一些愚蠢的事情还是错过了一个技巧,因为我的想法已经用完了,但不能相信 io 在处理时间上造成了如此大的差异。
感谢任何指针,并将根据需要提供更多信息。
谢谢
硅
参考 Perl 脚本如下:
use File::Find;
my $cwd = `pwd`;
chomp $cwd;
find( \&hasxml, shift );
sub hasxml {
if (-d) {
my @files = <$_/*.xml>;
if ( scalar(@files) > 0 ) {
process("$cwd/${File::Find::dir}/$_");
}
}
}
sub process {
my $dir = shift;
my @files = <$dir/*.xml>;
foreach my $file (@files) {
my $fh;
open( $fh, "< $file" ) or die "Could not read file <$file>";
my $contents = do { local $/; <$fh> };
close($fh);
my ($id) = $contents =~ /<field name="FIELDNAME">([^<]+)<\/field>/s;
print "$file\t<$id>\n";
}
}