【发布时间】:2015-05-31 23:48:28
【问题描述】:
我有一个 perl 脚本,它从数据库中读取约 50,000 行并将它们存储在一个哈希数组中。标准 DBI 代码。与其直接处理哈希,我更喜欢将数据放入可以非常干净地传递给其他代码模块的对象中。我正在阅读的表格中有 15 列以上。我的代码基本上是这样的:
my $db = DBI->connect(); # Just pretend you see a proper DBI connect here
my $resultSet = $db->selectall_arrayref($sql);
$db->disconnect();
# Here's where the problem starts.
my %objects;
for my $row (@{$resultSet}) {
my ($col1, $col2, ..., $col15) = @{$row};
my %inputHash;
$inputHash{col1} = $col1 if $col1;
...
$inputHash{col15} = $col1 if $col15;
my $obj = Model::Object->new(%inputHash);
$objects{$col1} = $obj;
}
return values %objects;
它将内容收集到哈希中以消除选择中的重复。问题从“问题出在这里”的注释下方的循环中开始。我在循环中放了一条消息,为每创建 100 个对象记录一行。前 100 个对象是在 5 秒内创建的。接下来的 100 个用时 16 秒。达到 300 需要 30 多秒。它最多可包含 9000 个对象,并且需要 12 分钟以上才能创建 100 个对象。我不认为 50,000 个对象大到足以造成这类问题。
正在创建的 Model::Object 是一个具有每个属性的 getter 和 setter 的类。它有一个新方法和一个序列化方法(本质上是一个 toString),就是这样。没有逻辑。
我正在一台 Windows 笔记本电脑上运行 ActiveState Perl 5.16,该笔记本电脑具有 8 GB 的 RAM、一个 i7 处理器(3 年前)和一个具有合理空间的 SSD 驱动器。我已经在具有相同版本 Perl 的 Linux 机器上看到了这一点,所以我认为这不是硬件问题。我需要继续使用 AS Perl 的 5.16。任何有关如何提高性能的建议将不胜感激。谢谢。
【问题讨论】:
-
您是否在不创建 $obj(甚至 %inputHash)的情况下检查了性能?性能问题似乎与散列有关。
-
如果性能有问题,那么您应该将您的
my $obj = Model::Object->new(%inputHash);行转换为my $obj = \%inputHash,仅用于测试目的。再次进行基准测试。如果更改几乎没有区别,那么Model::Object不是您的问题。如果它有很大的不同,那么它很可能是。 -
如果您在开始陷入困境之前对可能的最佳结果有所了解,则更容易进行性能调整。据我们所知,真正的问题可能是您使用
...传递的代码。 -
@DavidO:虽然我大体上同意你的观点,不应该遗漏任何代码,但在这种情况下,周围环境强烈建议它只有 13 个分配给
$inputHash。此外,与“shotgun profiling”相比,分析是找到慢行的更好方法。 -
Model::Object里面的结构是什么?你不能简单地说$objects{$input_hash{col1}} = bless \%input_hash, 'Model::Object'而不是调用构造函数吗?并且您总是想要与col1的last 值对应的数据吗?如果 first 可以,那么当它只会被丢弃时,您可以节省大量构建%input_hash的工作。您还可以向后迭代$result_set以获取列表中的最后一个值
标签: performance perl object