Bug 28278: Improve $KOHA_CONF parsing speed by using XML::LibXML
- Without the patch:
$ hyperfine --warmup 1 \
'perl -MKoha::Config -e "Koha::Config->read_from_file(\$ENV{KOHA_CONF}) for (1..1000)"'
Time (mean ± σ): 3.585 s ± 0.018 s [User: 3.531 s, System: 0.049 s]
Range (min … max): 3.547 s … 3.612 s 10 runs
- With the patch:
$ hyperfine --warmup 1 \
'perl -MKoha::Config -e "Koha::Config->read_from_file(\$ENV{KOHA_CONF}) for (1..1000)"'
Time (mean ± σ): 1.122 s ± 0.028 s [User: 1.104 s, System: 0.014 s]
Range (min … max): 1.095 s … 1.189 s 10 runs
Test plan:
1. Apply the first patch (the one with the unit tests) and make sure
tests pass: `prove t/Koha/Config.t`
2. Apply the rest of the patches and verify that tests still pass:
`prove t/Koha/Config.t`.
Signed-off-by: Victor Grousset/tuxayo <victor@tuxayo.net>
Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
parent
9d19e85d04
commit
a892f655ef
|
|
@ -17,7 +17,7 @@ package Koha::Config;
|
|||
|
||||
use Modern::Perl;
|
||||
|
||||
use XML::Simple;
|
||||
use XML::LibXML ':libxml';
|
||||
|
||||
# Default config file, if none is specified
|
||||
use constant CONFIG_FNAME => "/etc/koha/koha-conf.xml";
|
||||
|
|
@ -37,21 +37,70 @@ sub read_from_file {
|
|||
|
||||
return if not defined $file;
|
||||
|
||||
my $xml;
|
||||
my $config = {};
|
||||
eval {
|
||||
$xml = XMLin(
|
||||
$file,
|
||||
keyattr => ['id'],
|
||||
forcearray => ['listen', 'server', 'serverinfo'],
|
||||
suppressempty => ''
|
||||
);
|
||||
my $dom = XML::LibXML->load_xml(location => $file);
|
||||
foreach my $childNode ($dom->documentElement->nonBlankChildNodes) {
|
||||
$class->_read_from_dom_node($childNode, $config);
|
||||
}
|
||||
};
|
||||
|
||||
if ($@) {
|
||||
die "\nError reading file $file.\nTry running this again as the koha instance user (or use the koha-shell command in debian)\n\n";
|
||||
}
|
||||
|
||||
return $xml;
|
||||
return $config;
|
||||
}
|
||||
|
||||
sub _read_from_dom_node {
|
||||
my ($class, $node, $config) = @_;
|
||||
|
||||
if ($node->nodeType == XML_TEXT_NODE) {
|
||||
$config->{content} = $node->textContent;
|
||||
} elsif ($node->nodeType == XML_ELEMENT_NODE) {
|
||||
my $subconfig = {};
|
||||
|
||||
foreach my $attribute ($node->attributes) {
|
||||
my $key = $attribute->nodeName;
|
||||
my $value = $attribute->value;
|
||||
$subconfig->{$key} = $value;
|
||||
}
|
||||
|
||||
foreach my $childNode ($node->nonBlankChildNodes) {
|
||||
$class->_read_from_dom_node($childNode, $subconfig);
|
||||
}
|
||||
|
||||
my $key = $node->nodeName;
|
||||
if ($node->hasAttribute('id')) {
|
||||
my $id = $node->getAttribute('id');
|
||||
$config->{$key} //= {};
|
||||
$config->{$key}->{$id} = $subconfig;
|
||||
delete $subconfig->{id};
|
||||
} else {
|
||||
my @keys = keys %$subconfig;
|
||||
if (1 == scalar @keys && $keys[0] eq 'content') {
|
||||
# An element with no attributes and no child elements becomes its text content
|
||||
$subconfig = $subconfig->{content};
|
||||
} elsif (0 == scalar @keys) {
|
||||
# An empty element becomes an empty string
|
||||
$subconfig = '';
|
||||
}
|
||||
|
||||
if (exists $config->{$key}) {
|
||||
unless (ref $config->{$key} eq 'ARRAY') {
|
||||
$config->{$key} = [$config->{$key}];
|
||||
}
|
||||
push @{ $config->{$key} }, $subconfig;
|
||||
} else {
|
||||
if (grep { $_ eq $key } (qw(listen server serverinfo))) {
|
||||
# <listen>, <server> and <serverinfo> are always arrays
|
||||
$config->{$key} = [$subconfig];
|
||||
} else {
|
||||
$config->{$key} = $subconfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Koha's main configuration file koha-conf.xml
|
||||
|
|
|
|||
Loading…
Reference in New Issue