Perl 记忆XML解析函数会破坏它

Perl 记忆XML解析函数会破坏它,perl,xml-parsing,memoization,Perl,Xml Parsing,Memoization,我是Perl新手,需要提高其他人编写的应用程序的性能 分析表明该程序在库中花费了大量时间。 基于对应用程序的使用如何随时间变化的了解,我们怀疑它多次重新解析相同的XML数据 XML解析函数似乎是一个简单的解决方案。它从中获取XML数据的文件假定在程序运行时不会更改,所以让我们只缓存每个文件的结果 这样的函数(库的入口点)是XMLin 我对软件的一个改动是添加 use Memoize; memoize('XMLin'); 尝试运行时返回错误: Not a HASH reference a

我是Perl新手,需要提高其他人编写的应用程序的性能

分析表明该程序在库中花费了大量时间。 基于对应用程序的使用如何随时间变化的了解,我们怀疑它多次重新解析相同的XML数据

XML解析函数似乎是一个简单的解决方案。它从中获取XML数据的文件假定在程序运行时不会更改,所以让我们只缓存每个文件的结果

这样的函数(库的入口点)是XMLin

我对软件的一个改动是添加

use Memoize;
memoize('XMLin');
尝试运行时返回错误:

    Not a HASH reference at C:\QuEST\Scripts\RangeAnalyzer/ParseETP.pl line 269.
第269行是:

@constantElements = @{$xml->{declarations}->{Package}->{declarations}->{Constant}};
    
。。。而
$xml
被定义为以下几行:

my $xml = XMLin($Filename, KeyAttr => {ConstValue => '', Operator => '', VariableRef => '', Variable => '', StateMachine => '', State => '', IfBlock => '', WhenBlock => '', SizeParameter => ''}, ForceArray => ['Variable', 'ConstValue', 'DataArrayOp', 'Constant']);
撤消更改将修复错误

为什么记忆函数会破坏其返回值?如何修复它?

我注意到,
XML::Simple
已被弃用,而替换它(最好是用更快的东西)则在尝试的事情列表中。 然而,这个错误打破了我的记忆模式


我使用的是Perl 5.10.0。

恐怕您的问题中没有足够的信息来完全回答问题所在。(至少在出现MWE之前)。然而,我想指出两件你可能需要考虑的事情。 为了记忆函数,memoize使用规范化器检查参数是否相同。根据,默认情况下,这只会将参数字符串化。这意味着hashref将转换为它的字符串表示形式,这是它在内存中的位置。这将在函数调用之间发生变化,因此它永远不会正确标识您传递了相同的参数

您可能希望提供自己的规范化函数来处理XML::Simple所需的特定参数样式


此外,根据文档中的说明,如果函数返回引用,则返回相同的引用。这意味着,如果您在某个时候修改了结构(根据给定的信息,我无法知道是否会发生这种情况),那么修改后的结构将稍后返回。

我担心您的问题中没有足够的信息来完全回答出了什么问题。(至少在出现MWE之前)。然而,我想指出两件你可能需要考虑的事情。 为了记忆函数,memoize使用规范化器检查参数是否相同。根据,默认情况下,这只会将参数字符串化。这意味着hashref将转换为它的字符串表示形式,这是它在内存中的位置。这将在函数调用之间发生变化,因此它永远不会正确标识您传递了相同的参数

您可能希望提供自己的规范化函数来处理XML::Simple所需的特定参数样式


此外,根据文档中的说明,如果函数返回引用,则返回相同的引用。这意味着,如果您在某个时候修改了结构(根据给定的信息,我无法知道是否会发生这种情况),那么修改后的结构将在稍后返回。

您能否提供一个最小的、可运行的问题演示,也许您可以在出错之前显示
Data::Dumper
所说的
$xml
中包含的行?不确定是什么破坏了您的代码,但即使memoize确实起作用,也值得指出的是,您为
KeyAttr
选项传递的值正在使用匿名hashref构造函数
{…}
它将在每次执行时返回对不同的、新构造的hashref的引用。因此,memoised函数在每次调用时都会看到不同的参数值,而不会从缓存中返回值。我怀疑错误与
memoize
无关,只是因为代码与XML不匹配。到目前为止。不要用它@一个金人,关于“OP不需要穿越可能相关或可能无关的线路”,是的,他们需要。我们的“工作”不是处理大量无关数据。他们确实需要生成一个最小的、可运行的问题演示。此外,将XML文件分解为包含“查询”中元素的位是很简单的,而且他们已经提供了加载XML文件所用的代码。您能提供一个最小的、可运行的问题演示吗?另外,也许您可以在出错之前显示
Data::Dumper
所说的
$xml
中包含的行?不确定是什么破坏了您的代码,但即使memoize确实起作用,也值得指出的是,您为
KeyAttr
选项传递的值正在使用匿名hashref构造函数
{…}
它将在每次执行时返回对不同的、新构造的hashref的引用。因此,memoised函数在每次调用时都会看到不同的参数值,而不会从缓存中返回值。我怀疑错误与
memoize
无关,只是因为代码与XML不匹配。到目前为止。不要用它@一个金人,关于“OP不需要穿越可能相关或可能无关的线路”,是的,他们需要。我们的“工作”不是处理大量无关数据。他们确实需要生成一个最小的、可运行的问题演示。此外,将XML文件分解为包含“查询”中元素的位并不重要,而且它们已经提供了用于加载XML文件的代码。如果它们总是传递文件名和相同的选项,自定义规范化函数可以简单地返回第一个参数(文件名)。如果它们总是传递一个文件名,但不总是传递相同的选项,那么使用
Cpanel::JSON::XS->new->canonical->encode(\@\ux)
就可以了