如何通过Perl中的主机名有效地分组大量URL?

时间:2010-04-06 20:54:07

标签: perl performance

我的文字文件包含超过一百万个网址。我必须处理此文件,以便根据主机地址为组分配URL:

{
    'http://www.ex1.com' => ['http://www.ex1.com/...', 'http://www.ex1.com/...', ...],
    'http://www.ex2.com' => ['http://www.ex2.com/...', 'http://www.ex2.com/...', ...]
}

我目前的基本解决方案需要大约600 MB的RAM来执行此操作(文件大小约为300 MB)。你能提供一些更有效的方法吗?

我目前的解决方案只是逐行读取,通过正则表达式提取主机地址并将网址放入哈希值。

修改

这是我的实施(我已经切断了无关紧要的事情):

while($line = <STDIN>) { 
    chomp($line); 
    $line =~ /(http:\/\/.+?)(\/|$)/i; 
    $host = "$1"; 
    push @{$urls{$host}}, $line; 
}

store \%urls, 'out.hash'; 

4 个答案:

答案 0 :(得分:5)

您可以采取的一种方法是将您的网址哈希绑定到像BerkeleyDB这样的DBM。你可以明确地给它选择它可以使用多少内存。

答案 1 :(得分:1)

如果你从两个文件读取600MB并将它们存储在内存中(在散列中),在内存使用方面没有太多优化空间(没有压缩数据,这可能不是一个可行的选择)。

但是,根据您将如何使用哈希中的数据,可能值得考虑将数据存储在数据库中,并查询它以获取所需的信息。

修改

根据您发布的代码,快速优化将不是存储整行而是存储相对URL。毕竟你已经将主机名作为哈希中的一个键。

答案 2 :(得分:1)

除了将数据结构存储到磁盘(如Leon Timmermans建议的绑定DBM哈希,SQLite3等SQL数据库等)之外,您将无法大幅减少内存消耗。 300M的实际数据,加上perl解释器,加上程序的字节码表示,加上每个提取的字符串的元数据,如果将所有内存全部保存在内存中,总计会占用超过300M的总内存。如果有的话,我有点惊讶它只是输入文件大小的两倍。

另一件需要考虑的事情是,如果您要多次处理同一个文件,将已解析的数据结构存储在磁盘上意味着您永远不必花时间在其上重新解析它未来的计划运行。

答案 3 :(得分:0)

你究竟想要实现什么?如果您要进行一些复杂的分析,存储到数据库是一个好主意,分组只是中间步骤,您可能只是对文本文件进行排序,而不是按顺序处理它直接导出您正在寻找的结果。