state - Demonstrate and time various Perl module loading algorithms
state
state -algorithm null -algorithm state
state -iterations 100000000
state -help
state -version
-algorithm null
This option specifies what module loading algorithm to benchmark. It can be specified more than once. The valid algorithm names are documented under ALGORITHMS
The default is to benchmark all programmed algorithms, in ASCIIbetical order.
This option displays the documentation for this script. The script then exits.
-iterations 100000000
This option specifies how many times the tested subroutine is called.
The default is -iterations 10 which is sufficient for demonstration purposes, but grossly insufficient for benchmarking.
This option displays the version of this script. The script then exits.
This Perl script is used to explore the magnitude of the time saving (if any) involved in various approaches to loading Perl modules at execution time. It was originally written to investigate the behavior of the state algorithm.
This code contains a commented-out override of the core require() subroutine, which can be uncommented to demonstrate how often require() is called by each algorithm. You do not want this override enabled if you are doing large numbers of iterations, because of the volume of output that can be generated, and because of the extra overhead imposed on algorithms that call require once for each invocation.
The following algorithms for run-time module loading are supported. For narrative convenience the algorithms are documented below as though they were normal subroutines, but they are actually implemented as anonymous subroutines in a hash keyed by algorithm name.
my $conditional;
sub test_conditional {
$conditional
or require YAML;
$conditional = 1;
return;
}
Something like this is the way to explicitly ensure require YAML is executed only once in pre-5.10 Perl.
sub test_null {
return;
}
This is included to give an estimate of the amount of time spent simply calling the code being tested.
sub test_require {
require YAML;
return;
}
The require() built-in is idempotent, so the YAML module is only loaded once however many times this code is executed. But require() is executed at every call.
sub test_state {
state $dummy = require YAML;
return;
}
THe state() built-in was introduced in Perl 5.10. It creates a lexical variable, but the assignment is only done the first time it is encountered. It occurred to me that if the right-hand side of the assignment were a require(), then it would only be executed the first time it was encountered.
Running 10**9 iterations of all four algorithms on a system with no other user-requested load produced the following results:
Benchmark: timing 1000000000 iterations of conditional, null, require, state...
conditional: 48 wallclock secs (48.04 usr + 0.00 sys = 48.04 CPU) @ 20815986.68/s (n=1000000000)
null: 9 wallclock secs ( 8.45 usr + 0.01 sys = 8.46 CPU) @ 118203309.69/s (n=1000000000)
require: 70 wallclock secs (70.41 usr + -0.03 sys = 70.38 CPU) @ 14208581.98/s (n=1000000000)
state: 24 wallclock secs (22.92 usr + -0.01 sys = 22.91 CPU) @ 43649061.55/s (n=1000000000)
Deducting the time of the null algorithm from each of the others produces:
require: 61 wallclock secs @ 16393442.62/s
conditional: 39 wallclock secs @ 25641025.64/s
state: 15 wallclock secs @ 66666666.67/s
Two conclusions appear to be reasonable:
Under the test conditions the
statealgorithm is significantly faster than just making use ofrequire's idempotence. If that is unavailable, an explicit conditional is still a win.Unless you anticipate truly staggering numbers of iterations, the difference is probably not worth worrying about.
Thomas R. Wyant, III wyant at cpan dot org
Copyright (C) 2016 by Thomas R. Wyant, III
This program is free software; you can redistribute it and/or modify it under the same terms as Perl 5.10.0. For more details, see the Artistic License 1.0 at http://www.perlfoundation.org/artistic_license_1_0, and/or the Gnu GPL at http://www.gnu.org/licenses/old-licenses/gpl-1.0.txt.
This program is distributed in the hope that it will be useful, but without any warranty; without even the implied warranty of merchantability or fitness for a particular purpose.