要求是:
事实 1:我们有一些由遗留系统生成的数据文件
事实 2:我们有一些由新系统生成的数据文件,最终应该会取代旧系统
事实 3:
- 这两个文件都是文本/ASCII 文件,记录由多行组成。
- 记录中的每一行都由字段名和字段值组成。
- 1 和 2 中行的显示格式不同,但是可以通过使用正则表达式从每行中提取字段名和字段值
- 字段名称可以在 1 和 2 之间变化,但我们有一个关联它们的映射
- 每条记录都有一个唯一标识符,可帮助我们将旧记录与新记录相关联,因为输出文件中的记录顺序在两个系统中不必相同。
- 每个要比较的文件至少为 10 MB,平均为 30 - 35 MB
事实 4:当我们迭代构建新系统时,我们需要比较两个系统在完全相同的条件下生成的文件并协调差异。
事实 5:这种比较是使用昂贵的视觉差异工具手动完成的。为了帮助解决这个问题,我编写了一个工具,将两个不同的字段名合并为一个通用名称,然后对每个记录、每个文件中的字段名进行排序,以便它们按顺序同步(新文件可以有额外的字段,在视觉差异)
事实 6:由于人工比较是由人工进行的,而且人工会犯错误,我们会得到错误的正面和负面,这会极大地影响我们的时间线。
显然问题是,“ALG”和“DS”应该是什么?
我必须解决的场景:
人们继续在视觉上检查差异 - 在这种情况下,现有脚本的性能令人沮丧 - 大部分处理似乎是按字典顺序对行数组进行排序(读取/获取数组元素:Tie::File:: FETCH,Tie::File::Cache::lookup 并将其放在正确的位置以便对其进行排序:Tie::File::Cache::insert, Tie::File::Heap::insert)
use strict;
use warnings;
use Tie::File;
use Data::Dumper;
use Digest::MD5 qw(md5_hex);
# open an existing file in read-only mode
use Fcntl 'O_RDONLY';
die "Usage: $0 <unsorted input filename> <sorted output filename>" if ($#ARGV < 1);
our $recordsWrittenCount = 0;
our $fieldsSorted = 0;
our @array;
tie @array, 'Tie::File', $ARGV[0], memory => 50_000_000, mode => O_RDONLY or die "Cannot open $ARGV[0]: $!";
open(OUTFILE, ">" . $ARGV[1]) or die "Cannot open $ARGV[1]: $!";
our @tempRecordStorage = ();
our $dx = 0;
# Now read in the EL6 file
our $numberOfLines = @array; # accessing @array in a loop might be expensive as it is tied??
for($dx = 0; $dx < $numberOfLines; ++$dx)
{
if($array[$dx] eq 'RECORD')
{
++$recordsWrittenCount;
my $endOfRecord = $dx;
until($array[++$endOfRecord] eq '.')
{
push @tempRecordStorage, $array[$endOfRecord];
++$fieldsSorted;
}
print OUTFILE "RECORD\n";
local $, = "\n";
print OUTFILE sort @tempRecordStorage;
@tempRecordStorage = ();
print OUTFILE "\n.\n"; # PERL does not postfix trailing separator after the last array element, so we need to do this ourselves)
$dx = $endOfRecord;
}
}
close(OUTFILE);
# Display results to user
print "\n[*] Done: " . $fieldsSorted . " fields sorted from " . $recordsWrittenCount . " records written.\n";
所以我想了想,我相信,如果是 trie,可能是后缀 trie/PATRICIA trie,这样在插入时,每条记录中的字段都会被排序。因此,我不必一次性对最终数组进行排序,成本将被摊销(我的猜测)
在这种情况下会出现另一个问题 - Tie::File 使用数组来抽象文件中的行 - 将行读入树然后将它们序列化回数组将需要额外的内存和处理/
问题是 - 这会比当前对绑定数组进行排序的成本更高吗?