line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Benchmark::DKbench; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
669906
|
use strict; |
|
3
|
|
|
|
|
18
|
|
|
3
|
|
|
|
|
90
|
|
4
|
3
|
|
|
3
|
|
15
|
use warnings; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
71
|
|
5
|
|
|
|
|
|
|
|
6
|
3
|
|
|
3
|
|
1557
|
use Digest; |
|
3
|
|
|
|
|
1786
|
|
|
3
|
|
|
|
|
98
|
|
7
|
3
|
|
|
3
|
|
20
|
use Digest::MD5 qw(md5_hex); |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
181
|
|
8
|
3
|
|
|
3
|
|
1468
|
use Encode; |
|
3
|
|
|
|
|
15903
|
|
|
3
|
|
|
|
|
260
|
|
9
|
3
|
|
|
3
|
|
1566
|
use File::Spec::Functions; |
|
3
|
|
|
|
|
2682
|
|
|
3
|
|
|
|
|
233
|
|
10
|
3
|
|
|
3
|
|
22
|
use List::Util qw(min max sum); |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
244
|
|
11
|
3
|
|
|
3
|
|
21
|
use Time::HiRes qw(clock_gettime CLOCK_MONOTONIC); |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
35
|
|
12
|
3
|
|
|
3
|
|
3633
|
use Time::Piece; |
|
3
|
|
|
|
|
35243
|
|
|
3
|
|
|
|
|
17
|
|
13
|
|
|
|
|
|
|
|
14
|
3
|
|
|
3
|
|
2317
|
use Astro::Coord::Constellations 'constellation_for_eq'; |
|
3
|
|
|
|
|
60291
|
|
|
3
|
|
|
|
|
194
|
|
15
|
3
|
|
|
3
|
|
23
|
use Astro::Coord::Precession 'precess'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
125
|
|
16
|
3
|
|
|
3
|
|
2029
|
use Crypt::JWT qw(encode_jwt decode_jwt); |
|
3
|
|
|
|
|
177911
|
|
|
3
|
|
|
|
|
229
|
|
17
|
3
|
|
|
3
|
|
2289
|
use CSS::Inliner; |
|
3
|
|
|
|
|
472028
|
|
|
3
|
|
|
|
|
121
|
|
18
|
3
|
|
|
3
|
|
2884
|
use DateTime; |
|
3
|
|
|
|
|
1642969
|
|
|
3
|
|
|
|
|
176
|
|
19
|
3
|
|
|
3
|
|
5525
|
use DBI; |
|
3
|
|
|
|
|
56770
|
|
|
3
|
|
|
|
|
243
|
|
20
|
3
|
|
|
3
|
|
34
|
use File::ShareDir 'dist_dir'; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
165
|
|
21
|
3
|
|
|
3
|
|
1714
|
use HTML::FormatText; |
|
3
|
|
|
|
|
21125
|
|
|
3
|
|
|
|
|
116
|
|
22
|
3
|
|
|
3
|
|
21
|
use HTML::TreeBuilder; |
|
3
|
|
|
|
|
9
|
|
|
3
|
|
|
|
|
49
|
|
23
|
3
|
|
|
3
|
|
3228
|
use Imager; |
|
3
|
|
|
|
|
154672
|
|
|
3
|
|
|
|
|
21
|
|
24
|
3
|
|
|
3
|
|
1539
|
use Imager::Filter::Mandelbrot; |
|
3
|
|
|
|
|
1925
|
|
|
3
|
|
|
|
|
105
|
|
25
|
3
|
|
|
3
|
|
1831
|
use Image::PHash; |
|
3
|
|
|
|
|
19220
|
|
|
3
|
|
|
|
|
104
|
|
26
|
3
|
|
|
3
|
|
24
|
use JSON::XS; |
|
3
|
|
|
|
|
8
|
|
|
3
|
|
|
|
|
241
|
|
27
|
3
|
|
|
3
|
|
22
|
use Math::DCT ':all'; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
483
|
|
28
|
3
|
|
|
3
|
|
3357
|
use Math::MatrixReal; |
|
3
|
|
|
|
|
91004
|
|
|
3
|
|
|
|
|
183
|
|
29
|
3
|
|
|
3
|
|
1929
|
use MCE::Loop; |
|
3
|
|
|
|
|
153571
|
|
|
3
|
|
|
|
|
24
|
|
30
|
3
|
|
|
3
|
|
3785
|
use SQL::Abstract::Classic; |
|
3
|
|
|
|
|
36860
|
|
|
3
|
|
|
|
|
134
|
|
31
|
3
|
|
|
3
|
|
1554
|
use SQL::Inserter; |
|
3
|
|
|
|
|
6528
|
|
|
3
|
|
|
|
|
157
|
|
32
|
3
|
|
|
3
|
|
1574
|
use System::CPU; |
|
3
|
|
|
|
|
7310
|
|
|
3
|
|
|
|
|
112
|
|
33
|
3
|
|
|
3
|
|
1461
|
use System::Info; |
|
3
|
|
|
|
|
55499
|
|
|
3
|
|
|
|
|
148
|
|
34
|
3
|
|
|
3
|
|
1460
|
use Text::Levenshtein::Damerau::XS; |
|
3
|
|
|
|
|
2002
|
|
|
3
|
|
|
|
|
155
|
|
35
|
3
|
|
|
3
|
|
1370
|
use Text::Levenshtein::XS; |
|
3
|
|
|
|
|
1963
|
|
|
3
|
|
|
|
|
160
|
|
36
|
|
|
|
|
|
|
|
37
|
3
|
|
|
3
|
|
26
|
use Exporter 'import'; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
26741
|
|
38
|
|
|
|
|
|
|
our @EXPORT = qw(system_identity suite_run calc_scalability); |
39
|
|
|
|
|
|
|
our $datadir = dist_dir("Benchmark-DKbench"); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
our $VERSION = '2.2'; |
42
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
=head1 NAME |
44
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
Benchmark::DKbench - Perl CPU Benchmark |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
=head1 SYNOPSIS |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# Run the suite single-threaded and then multi-threaded on multi-core systems |
50
|
|
|
|
|
|
|
# Will print scores for the two runs and multi/single thread scalability |
51
|
|
|
|
|
|
|
dkbench |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# A dual-thread "quick" run (with times instead of scores) |
54
|
|
|
|
|
|
|
dkbench -j 2 -q |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# If BioPerl is installed, enable the BioPerl benchmarks by downloading Genbank data |
57
|
|
|
|
|
|
|
dkbench --setup |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# Force install the reference versions of all CPAN modules |
60
|
|
|
|
|
|
|
setup_dkbench --force |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=head1 DESCRIPTION |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
A Perl benchmark suite for general compute, created to evaluate the comparative |
65
|
|
|
|
|
|
|
performance of systems when running computationally intensive Perl (both pure Perl |
66
|
|
|
|
|
|
|
and C/XS) workloads. It is a good overall indicator for generic CPU performance in |
67
|
|
|
|
|
|
|
real-world scenarios. It runs single and multi-threaded (able to scale to hundreds |
68
|
|
|
|
|
|
|
of CPUs) and can be fully customized to run the benchmarks that better suit your own |
69
|
|
|
|
|
|
|
scenario. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
=head1 INSTALLATION |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
The only non-CPAN software required to install/run the suite is a build environment |
74
|
|
|
|
|
|
|
for the C/XS modules (C compiler, make etc.) and Perl. On the most popular Linux |
75
|
|
|
|
|
|
|
package managers you can easily set up such an environment (as root or with sudo): |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# Debian/Ubuntu etc |
78
|
|
|
|
|
|
|
apt-get update |
79
|
|
|
|
|
|
|
apt-get install build-essential perl cpanminus |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
# CentOS/Red Hat |
82
|
|
|
|
|
|
|
yum update |
83
|
|
|
|
|
|
|
yum install gcc make patch perl perl-App-cpanminus |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
After that, you can use L<App::cpanminus> to install the benchmark suite (as |
86
|
|
|
|
|
|
|
root/sudo is the easiest, will install for all users): |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
cpanm -n Benchmark::DKbench |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
See the C<setup_dkbench> script below for more on the installation of a couple of |
91
|
|
|
|
|
|
|
optional benchmarks and standardizing your benchmarking environment. |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=head1 SCRIPTS |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
You will most likely only ever need the main script C<dkbench> which launches the |
96
|
|
|
|
|
|
|
suite, although C<setup_dkbench> can help with setup or standardizing/normalizing your |
97
|
|
|
|
|
|
|
benchmarking environment. |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
=head2 C<dkbench> |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
The main script that runs the DKbench benchmark suite. If L<BioPerl> is installed, |
102
|
|
|
|
|
|
|
you may want to start with C<dkbench --setup>. But beyond that, there are many |
103
|
|
|
|
|
|
|
options to control number of threads, iterations, which benchmarks to run etc: |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
dkbench [options] |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
Options: |
108
|
|
|
|
|
|
|
--threads <i>, -j <i> : Number of benchmark threads (default is 1). |
109
|
|
|
|
|
|
|
--multi, -m : Multi-threaded using all your CPU cores/threads. |
110
|
|
|
|
|
|
|
--max_threads <i> : Override the cpu detection to specify max cpu threads. |
111
|
|
|
|
|
|
|
--iter <i>, -i <i> : Number of suite iterations (with min/max/avg at the end). |
112
|
|
|
|
|
|
|
--include <regex> : Run only benchmarks that match regex. |
113
|
|
|
|
|
|
|
--exclude <regex> : Do not run benchmarks that match regex. |
114
|
|
|
|
|
|
|
--time, -t : Report time (sec) instead of score. |
115
|
|
|
|
|
|
|
--quick, -q : Quick benchmark run (implies -t). |
116
|
|
|
|
|
|
|
--no_mce : Do not run under MCE::Loop (implies -j 1). |
117
|
|
|
|
|
|
|
--skip_bio : Skip BioPerl benchmarks. |
118
|
|
|
|
|
|
|
--skip_prove : Skip Moose prove benchmark. |
119
|
|
|
|
|
|
|
--time_piece : Run optional Time::Piece benchmark (see benchmark details). |
120
|
|
|
|
|
|
|
--bio_codons : Run optional BioPerl Codons benchmark (does not scale well). |
121
|
|
|
|
|
|
|
--sleep <i> : Sleep for <i> secs after each benchmark. |
122
|
|
|
|
|
|
|
--setup : Download the Genbank data to enable the BioPerl tests. |
123
|
|
|
|
|
|
|
--datapath <path> : Override the path where the expected benchmark data is found. |
124
|
|
|
|
|
|
|
--ver <num> : Skip benchmarks added after the specified version. |
125
|
|
|
|
|
|
|
--help -h : Show basic help and exit. |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
The default run (no options) will run all the benchmarks both single-threaded and |
128
|
|
|
|
|
|
|
multi-threaded (using all detected CPU cores/hyperthreads) and show you scores and |
129
|
|
|
|
|
|
|
multi vs single threaded scalability. |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
The scores are calibrated such that a reference CPU (Intel Xeon Platinum 8481C - |
132
|
|
|
|
|
|
|
Sapphire Rapids) would achieve a score of 1000 in a single-core benchmark run using |
133
|
|
|
|
|
|
|
the default software configuration (Linux/Perl 5.36.0 with reference CPAN modules). |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
The multi-thread scalability should approach 100% if each thread runs on a full core |
136
|
|
|
|
|
|
|
(i.e. no SMT), and the core can maintain the clock speed it had on the single-thread |
137
|
|
|
|
|
|
|
runs. Note that the overall scalability is an average of the benchmarks that drops |
138
|
|
|
|
|
|
|
non-scaling outliers (over 2*stdev less than the mean). |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
The suite will report a Pass/Fail per benchmark. A failure may be caused if you have |
141
|
|
|
|
|
|
|
different CPAN module version installed - this is normal, and you will be warned. |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
The suite uses L<MCE::Loop> to run on the desired number of parallel threads, although |
144
|
|
|
|
|
|
|
there is an option to disable it, which forces a single-thread run. |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 C<setup_dkbench> |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Simple installer to check/get the reference versions of CPAN modules and download |
149
|
|
|
|
|
|
|
the Genbank data file required for the BioPerl benchmarks of the DKbench suite. |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
It assumes that you have some software already installed (see INSTALLATION above), |
152
|
|
|
|
|
|
|
try C<setup_dkbench --help> will give you more details. |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
setup_dkbench [--force --sudo --test --data=s --help] |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
Options: |
157
|
|
|
|
|
|
|
--sudo : Will use sudo for cpanm calls. |
158
|
|
|
|
|
|
|
--force : Will install reference CPAN module versions and re-download the genbank data. |
159
|
|
|
|
|
|
|
--test : Will run the test suites for the CPAN module (default behaviour is to skip). |
160
|
|
|
|
|
|
|
--data=s : Data dir path to copy files from. Should not need if you installed DKbench. |
161
|
|
|
|
|
|
|
--help : Print this help text and exit. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
Running it without any options will fetch the data for the BioPerl tests (similar to |
164
|
|
|
|
|
|
|
C<dkbench --setup>) and use C<cpanm> to install any missing libraries. |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
Using it with C<--force> will install the reference CPAN module versions, including |
167
|
|
|
|
|
|
|
BioPerl which is not a requirement for DKbench, but enables the BioPerl benchmarks. |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
The reference Perl and CPAN versions are suggested if you want a fair comparison |
170
|
|
|
|
|
|
|
between systems and also for the benchmark Pass/Fail results to be reliable. |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
=head1 BENCHMARKS |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
The suite consists of 21 benchmarks, 19 will run by default. However, the |
175
|
|
|
|
|
|
|
C<BioPerl Monomers> requires the optional L<BioPerl> to be installed and Genbank |
176
|
|
|
|
|
|
|
data to be downloaded (C<dkbench --setup> can do the latter), so you will only |
177
|
|
|
|
|
|
|
see 18 benchmarks running just after a standard install. Because the overall score |
178
|
|
|
|
|
|
|
is an average, it is generally unaffected by adding or skipping a benchmark or two. |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
The optional benchmarks are enabled with the C<--time_piece> and C<--bio_codons> |
181
|
|
|
|
|
|
|
options. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
=over 4 |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
=item * C<Astro> : Calculates precession between random epochs and finds the |
186
|
|
|
|
|
|
|
constellation for random equatorial coordinates using L<Astro::Coord::Precession> |
187
|
|
|
|
|
|
|
and L<Astro::Coord::Constellations> respectively. |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
=item * C<BioPerl Codons> : Counts codons on a sample bacterial sequence. Requires |
190
|
|
|
|
|
|
|
L<BioPerl> to be installed. |
191
|
|
|
|
|
|
|
This test does not scale well on multiple threads, so is disabled by default (use |
192
|
|
|
|
|
|
|
C<--bio_codons>) option. Requires data fetched using the C<--setup> option. |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
=item * C<BioPerl Monomers> : Counts monomers on 500 sample bacterial sequences using |
195
|
|
|
|
|
|
|
L<BioPerl> (which needs to be installed). Requires data fetched using the C<--setup> |
196
|
|
|
|
|
|
|
option. |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
=item * C<CSS::Inliner> : Inlines CSS on 2 sample wiki pages using L<CSS::Inliner>. |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
=item * C<Crypt::JWT> : Creates large JSON Web Tokens with RSA and EC crypto keys |
201
|
|
|
|
|
|
|
using L<Crypt::JWT>. |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
=item * C<DateTime> : Creates and manipulates L<DateTime> objects. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
=item * C<DBI/SQL> : Creates a mock L<DBI> connection (using L<DBD::Mock>) and passes |
206
|
|
|
|
|
|
|
it insert/select statements using L<SQL::Inserter> and L<SQL::Abstract::Classic>. |
207
|
|
|
|
|
|
|
The latter is quite slow at creating the statements, but it is widely used. |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
=item * C<Digest> : Creates MD5, SH1 and SHA-512 digests of a large string. |
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
=item * C<Encode> : Encodes/decodes large strings from/to UTF-8/16, cp-1252. |
212
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
=item * C<HTML::FormatText> : Converts HTML to text for 2 sample wiki pages using |
214
|
|
|
|
|
|
|
L<HTML::FormatText>. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
=item * C<Imager> : Loads a sample image and performs edits/manipulations with |
217
|
|
|
|
|
|
|
L<Imager>, including filters like gaussian, unsharp mask, mandelbrot. |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
=item * C<JSON::XS> : Encodes/decodes random data structures to/from JSON using |
220
|
|
|
|
|
|
|
L<JSON::XS>. |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
=item * C<Math::DCT> : Does 8x8, 18x18 and 32x32 DCT transforms with L<Math::DCT>. |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
=item * C<Math::MatrixReal> : Performs various manipulations on L<Math::MatrixReal> |
225
|
|
|
|
|
|
|
matrices. |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
=item * C<Moose> : Creates L<Moose> objects. |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
=item * C<Moose prove> : Runs 110 tests from the Moose 2.2201 test suite. The least |
230
|
|
|
|
|
|
|
CPU-intensive test (which is why there is the option C<--no_prove> to disable it), |
231
|
|
|
|
|
|
|
most of the time will be spent loading the interpreter and the Moose module for each |
232
|
|
|
|
|
|
|
test, which is behaviour representative of how a Perl test suite runs by default. |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
=item * C<Primes> : Calculates all primes up to 7.5 million. Small number with |
235
|
|
|
|
|
|
|
repeat was chosen to keep low memory (this is a pure Perl function no Math libraries). |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=item * C<Regex/Subst> : Concatenates 3 wiki pages into a byte string then matches |
238
|
|
|
|
|
|
|
3 typical regexes (for names, emails, URIs), replaces html tags with their contents |
239
|
|
|
|
|
|
|
(starting with the innermost) and does calls subst a few times. |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=item * C<Regex/Subst utf8> : Exactly the same as C<Regex/Subst>, but reads into |
242
|
|
|
|
|
|
|
a utf8 string. Perl version can make a big difference, as Unicode behaviour has |
243
|
|
|
|
|
|
|
changed (old Perl versions are faster but less strict in general). |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
=item * C<Text::Levenshtein> : The edit distance for strings of various lengths (up |
246
|
|
|
|
|
|
|
to 2500) are calculated using L<Text::Levenshtein::XS> and L<Text::Levenshtein::Damerau::XS>. |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
=item * C<Time::Piece> : Creates and manipulates/converts Time::Piece objects. It |
249
|
|
|
|
|
|
|
is disabled by default because it uses the OS time libraries, so it might skew results |
250
|
|
|
|
|
|
|
if you are trying to compare CPUs on different OS platforms. It can be enabled with |
251
|
|
|
|
|
|
|
the C<--time_piece> option. For MacOS specifically, it can only be enabled if C<--no_mce> |
252
|
|
|
|
|
|
|
is specified, as it runs extremely slow when forked. |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=back |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
=head1 EXPORTED FUNCTIONS |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
You will normally not use the Benchmark::DKbench module itself, but here are the |
259
|
|
|
|
|
|
|
exported functions that the C<dkbench> script uses for reference: |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=head2 C<system_identity> |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
my $cores = system_identity(); |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
Prints out software/hardware configuration and returns then number of cores detected. |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=head2 C<suite_run> |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
my %stats = suite_run(\%options); |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
Runs the benchmark suite given the C<%options> and prints results. Returns a hash |
272
|
|
|
|
|
|
|
with run stats. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=head2 C<calc_scalability> |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
calc_scalability(\%options, \%stat_single, \%stat_multi); |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
Given the C<%stat_single> results of a single-threaded C<suite_run> and C<%stat_multi> |
279
|
|
|
|
|
|
|
results of a multi-threaded run, will calculate and print the multi-thread scalability. |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head1 NOTES |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
The benchmark suite was created to compare the performance of various cloud offerings. |
284
|
|
|
|
|
|
|
You can see the L<original perl blog post|http://blogs.perl.org/users/dimitrios_kechagias/2022/03/cloud-provider-performance-comparison-gcp-aws-azure-perl.html> |
285
|
|
|
|
|
|
|
as well as the L<2023 follow-up|https://dev.to/dkechag/cloud-vm-performance-value-comparison-2023-perl-more-1kpp>. |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
The benchmarks for the first version were more tuned to what I would expect to run |
288
|
|
|
|
|
|
|
on the servers I was testing, in order to choose the optimal types for the company |
289
|
|
|
|
|
|
|
I was working for. The second version has expanded a bit over that, and is friendlier |
290
|
|
|
|
|
|
|
to use. |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
Althought this benchmark is in general a good indicator of general CPU performance |
293
|
|
|
|
|
|
|
and can be customized to your needs, no benchmark is as good as running your own |
294
|
|
|
|
|
|
|
actual workload. |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
=head2 SCORES |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
Some sample DKbench score results from various systems for comparison (all on |
299
|
|
|
|
|
|
|
reference setup with Perl 5.36.0): |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
CPU Cores/HT Single Multi Scalability |
302
|
|
|
|
|
|
|
Intel i7-4750HQ @ 2.0 (MacOS) 4/8 612 2332 46.9% |
303
|
|
|
|
|
|
|
AMD Ryzen 5 PRO 4650U @ 2.1 (WSL) 6/12 905 4444 40.6% |
304
|
|
|
|
|
|
|
Apple M1 Pro @ 3.2 (MacOS) 10/10 1283 10026 78.8% |
305
|
|
|
|
|
|
|
Apple M2 Pro @ 3.5 (MacOS) 12/12 1415 12394 73.1% |
306
|
|
|
|
|
|
|
Ampere Altra @ 3.0 (Linux) 48/48 708 32718 97.7% |
307
|
|
|
|
|
|
|
Intel Xeon Platinum 8481C @ 2.7 (Linux) 88/176 1000 86055 48.9% |
308
|
|
|
|
|
|
|
AMD EPYC Milan 7B13 @ 2.45 (Linux) 112/224 956 104536 49.3% |
309
|
|
|
|
|
|
|
AMD EPYC Genoa 9B14 @ 2.7 (Linux) 180/360 1197 221622 51.4% |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
=head1 AUTHOR |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
Dimitrios Kechagias, C<< <dkechag at cpan.org> >> |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=head1 BUGS |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
Please report any bugs or feature requests either on L<GitHub|https://github.com/dkechag/Benchmark-DKbench> (preferred), or on RT (via the email |
318
|
|
|
|
|
|
|
C<bug-Benchmark-DKbench at rt.cpan.org> or L<web interface|https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Benchmark-DKbench>). |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=head1 GIT |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
L<https://github.com/dkechag/Benchmark-DKbench> |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
This software is copyright (c) 2021-2023 by Dimitrios Kechagias. |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
This is free software; you can redistribute it and/or modify it under |
331
|
|
|
|
|
|
|
the same terms as the Perl 5 programming language system itself. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=cut |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
sub benchmark_list { |
336
|
|
|
|
|
|
|
return { # idx : 0 = result, 1 = ref time, 2 = func, 3 = quick test, 4 = normal test, 5 = ver |
337
|
12
|
|
|
12
|
0
|
683
|
'Astro' => ['e71c7ae08f16fe26aea7cfdb72785873', 5.674, \&bench_astro, 20000, 80000], |
338
|
|
|
|
|
|
|
'BioPerl Codons' => ['97c443c099886ca60e99f7ab9df689b5', 8.752, \&bench_bioperl_codons, 3, 5, 1], |
339
|
|
|
|
|
|
|
'BioPerl Monomers' => ['d29ed0a5c205c803c112be1338d1f060', 5.241, \&bench_bioperl_mono, 6, 20], |
340
|
|
|
|
|
|
|
'Crypt::JWT' => ['d41d8cd98f00b204e9800998ecf8427e', 6.451, \&bench_jwt, 250, 900], |
341
|
|
|
|
|
|
|
'CSS::Inliner' => ['82c1b6de9ca0500a48f8a8df0998df3c', 4.603, \&bench_css, 2, 5], |
342
|
|
|
|
|
|
|
'DBI/SQL' => ['2b8252daad9568a5b39038c696df4be3', 5.700, \&bench_dbi, 5000, 15000, 2.1], |
343
|
|
|
|
|
|
|
'DateTime' => ['b08d2eeb994083b7422f6c9d86fed2c6', 6.198, \&bench_datetime, 5000, 15000], |
344
|
|
|
|
|
|
|
'Digest' => ['4b69f6cf0f53cbf6c3444f2f767dd21d', 4.513, \&bench_digest, 50, 250], |
345
|
|
|
|
|
|
|
'Encode' => ['PASS 1025', 5.725, \&bench_encode, 40, 120], |
346
|
|
|
|
|
|
|
'HTML::FormatText' => ['8c2589f0a5276252805e11301fc2ab56', 4.756, \&bench_formattext, 4, 10], |
347
|
|
|
|
|
|
|
'Imager' => ['8829cb3703e884054eb025496f336c63', 6.792, \&bench_imager, 4, 16], |
348
|
|
|
|
|
|
|
'JSON::XS' => ['PASS', 5.388, \&bench_json, 600, 2200], |
349
|
|
|
|
|
|
|
'Math::DCT' => ['766e3bfd7a2276f452bb3d1bd21939bc', 7.147, \&bench_dct, 25000, 100_000], |
350
|
|
|
|
|
|
|
'Math::MatrixReal' => ['4606231b1309fb21ae1223fa0043fd76', 4.293, \&bench_matrixreal, 200, 650], |
351
|
|
|
|
|
|
|
'Moose' => ['d1cb92c513f6378506dfa11f694cffac', 4.968, \&bench_moose, 10_000, 30_000], |
352
|
|
|
|
|
|
|
'Moose prove' => ['PASS', 7.974, \&bench_moose_prv, 0.5, 1], |
353
|
|
|
|
|
|
|
'Primes' => ['4266f70a7a9efb3484cf5d98eba32244', 3.680, \&bench_primes_m, 2, 5], |
354
|
|
|
|
|
|
|
'Regex/Subst' => ['30ce365b25f3d597578b3bdb14aa3f57', 4.652, \&bench_regex_asc, 8, 24], |
355
|
|
|
|
|
|
|
'Regex/Subst utf8' => ['857eb4e63a4d174ca4a16fe678f7626f', 5.703, \&bench_regex_utf8, 3, 10], |
356
|
|
|
|
|
|
|
'Text::Levenshtein' => ['2948a300ed9131fa0ce82bb5eabb8ded', 5.539, \&bench_textlevenshtein, 7, 25, 2.1], |
357
|
|
|
|
|
|
|
'Time::Piece' => ['2d4b149fe7f873a27109fc376d69211b', 5.907, \&bench_timepiece, 75_000, 275_000], |
358
|
|
|
|
|
|
|
}; |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
sub system_identity { |
362
|
1
|
|
|
1
|
1
|
1653
|
my ($physical, $cores, $ncpu) = System::CPU::get_cpu; |
363
|
1
|
|
50
|
|
|
2845
|
$ncpu ||= 1; |
364
|
1
|
50
|
|
|
|
7
|
local $^O = 'linux' if $^O =~ /android/; |
365
|
1
|
|
|
|
|
11
|
my $info = System::Info->sysinfo_hash; |
366
|
1
|
|
0
|
|
|
23214
|
my $osn = $info->{distro} || $info->{os} || $^O; |
367
|
1
|
|
50
|
|
|
29
|
my $model = System::CPU::get_name || ''; |
368
|
1
|
|
50
|
|
|
4772
|
my $arch = System::CPU::get_arch || ''; |
369
|
1
|
50
|
|
|
|
11340
|
$arch = " ($arch)" if $arch; |
370
|
1
|
|
|
|
|
46
|
print "--------------- Software ---------------\nDKbench v$VERSION\n"; |
371
|
1
|
|
|
|
|
49
|
print "Perl $^V\n"; |
372
|
1
|
|
|
|
|
26
|
print "OS: $osn\n--------------- Hardware ---------------\n"; |
373
|
1
|
|
|
|
|
298
|
print "CPU type: $model$arch\n"; |
374
|
1
|
|
|
|
|
15
|
print "CPUs: $ncpu"; |
375
|
1
|
|
|
|
|
14
|
my @extra; |
376
|
1
|
50
|
33
|
|
|
105
|
push @extra, "$physical Processors" if $physical && $physical > 1; |
377
|
1
|
50
|
|
|
|
75
|
push @extra, "$cores Cores" if $cores; |
378
|
1
|
50
|
33
|
|
|
58
|
push @extra, "$ncpu Threads" if $cores && $cores != $ncpu; |
379
|
1
|
50
|
|
|
|
34
|
print " (".join(', ', @extra).")" if @extra; |
380
|
1
|
|
|
|
|
11
|
print "\n".("-"x40)."\n"; |
381
|
|
|
|
|
|
|
|
382
|
1
|
|
|
|
|
110
|
return $ncpu; |
383
|
|
|
|
|
|
|
}; |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
sub suite_run { |
386
|
6
|
|
|
6
|
1
|
35694
|
my $opt = shift; |
387
|
6
|
100
|
|
|
|
67
|
$datadir = $opt->{datapath} if $opt->{datapath}; |
388
|
6
|
|
100
|
|
|
58
|
$opt->{threads} //= 1; |
389
|
6
|
|
100
|
|
|
60
|
$opt->{repeat} //= 1; |
390
|
6
|
100
|
|
|
|
41
|
$opt->{f} = $opt->{time} ? '%.3f' : '%5.0f'; |
391
|
6
|
|
|
|
|
31
|
my %stats = (threads => $opt->{threads}); |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
MCE::Loop::init { |
394
|
|
|
|
|
|
|
max_workers => $opt->{threads}, |
395
|
|
|
|
|
|
|
chunk_size => 1, |
396
|
6
|
100
|
|
|
|
79
|
} unless $opt->{no_mce}; |
397
|
|
|
|
|
|
|
|
398
|
6
|
|
|
|
|
155
|
foreach (1..$opt->{iter}) { |
399
|
8
|
100
|
|
|
|
173
|
print "Iteration $_ of $opt->{iter}...\n" if $opt->{iter} > 1; |
400
|
8
|
|
|
|
|
53
|
run_iteration($opt, \%stats); |
401
|
|
|
|
|
|
|
} |
402
|
|
|
|
|
|
|
|
403
|
5
|
100
|
|
|
|
63
|
total_stats($opt, \%stats) if $opt->{iter} > 1; |
404
|
|
|
|
|
|
|
|
405
|
5
|
|
|
|
|
910
|
return %stats; |
406
|
|
|
|
|
|
|
} |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
sub calc_scalability { |
409
|
2
|
|
|
2
|
1
|
7965
|
my ($opt, $stats1, $stats2) = @_; |
410
|
2
|
|
|
|
|
60
|
my $benchmarks = benchmark_list(); |
411
|
2
|
|
|
|
|
28
|
my $threads = $stats2->{threads}/$stats1->{threads}; |
412
|
2
|
100
|
|
|
|
39
|
my $display = $opt->{time} ? 'times' : 'scores'; |
413
|
2
|
100
|
|
|
|
31
|
$opt->{f} = $opt->{time} ? '%.3f' : '%5.0f'; |
414
|
2
|
|
|
|
|
28
|
my (@perf, @scal); |
415
|
2
|
|
|
|
|
25
|
print "Multi thread Scalability:\n".pad_to("Benchmark",24).pad_to("Multi perf xSingle",24).pad_to("Multi scalability %",24); |
416
|
2
|
|
|
|
|
153
|
print "\n"; |
417
|
2
|
|
|
|
|
27
|
my $cnt; |
418
|
2
|
|
|
|
|
56
|
foreach my $bench (sort keys %$benchmarks) { |
419
|
42
|
100
|
100
|
|
|
374
|
next unless $stats1->{$bench}->{times} && $stats2->{$bench}->{times}; |
420
|
2
|
|
|
|
|
22
|
$cnt++; |
421
|
2
|
|
|
|
|
32
|
my @res1 = min_max_avg($stats1->{$bench}->{times}); |
422
|
2
|
|
|
|
|
30
|
my @res2 = min_max_avg($stats2->{$bench}->{times}); |
423
|
2
|
50
|
|
|
|
43
|
push @perf, $res1[2]/$res2[2]*$threads if $res2[2]; |
424
|
2
|
50
|
|
|
|
34
|
push @scal, $res1[2]/$res2[2]*100 if $res2[2]; |
425
|
2
|
|
|
|
|
42
|
print pad_to("$bench:",24).pad_to(sprintf("%.2f",$perf[-1]),24).pad_to(sprintf("%2.0f",$scal[-1]),24)."\n"; |
426
|
|
|
|
|
|
|
} |
427
|
2
|
|
|
|
|
181
|
print (("-"x40)."\n"); |
428
|
2
|
|
|
|
|
59
|
my $avg1 = min_max_avg($stats1->{total}->{$display}); |
429
|
2
|
|
|
|
|
40
|
my $avg2 = min_max_avg($stats2->{total}->{$display}); |
430
|
2
|
|
|
|
|
148
|
print "DKbench summary ($cnt benchmarks, $stats2->{threads} threads):\n"; |
431
|
2
|
|
|
|
|
28
|
print pad_to("Single:").sprintf($opt->{f}, $avg1)."\n"; |
432
|
2
|
|
|
|
|
49
|
print pad_to("Multi:").sprintf($opt->{f}, $avg2)."\n"; |
433
|
2
|
|
|
|
|
38
|
my @newperf = Benchmark::DKbench::drop_outliers(\@perf, -1); |
434
|
2
|
|
|
|
|
34
|
my @newscal = Benchmark::DKbench::drop_outliers(\@scal, -1); |
435
|
2
|
|
|
|
|
35
|
@perf = min_max_avg(\@newperf); |
436
|
2
|
|
|
|
|
52
|
@scal = min_max_avg(\@newscal); |
437
|
2
|
|
|
|
|
50
|
print pad_to("Multi/Single perf:").sprintf("%.2fx\t(%.2f - %.2f)", $perf[2], $perf[0], $perf[1])."\n"; |
438
|
2
|
|
|
|
|
34
|
print pad_to("Multi scalability:").sprintf("%2.1f%% \t(%.0f%% - %.0f%%)", $scal[2], $scal[0], $scal[1])."\n"; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
sub run_iteration { |
442
|
8
|
|
|
8
|
0
|
56
|
my ($opt, $stats) = @_; |
443
|
8
|
|
|
|
|
53
|
my $benchmarks = benchmark_list(); |
444
|
8
|
100
|
|
|
|
56
|
my $title = $opt->{time} ? 'Time (sec)' : 'Score'; |
445
|
8
|
|
|
|
|
67
|
print pad_to("Benchmark").pad_to($title); |
446
|
8
|
100
|
|
|
|
101
|
print "Pass/Fail" unless $opt->{time}; |
447
|
8
|
|
|
|
|
96
|
print "\n"; |
448
|
8
|
|
|
|
|
92
|
my ($total_score, $total_time, $i) = (0, 0, 0); |
449
|
8
|
|
|
|
|
147
|
foreach my $bench (sort keys %$benchmarks) { |
450
|
168
|
100
|
100
|
|
|
831
|
next if $opt->{skip_bio} && $bench =~ /Monomers/; |
451
|
166
|
100
|
100
|
|
|
557
|
next if $opt->{skip_prove} && $bench =~ /prove/; |
452
|
164
|
100
|
100
|
|
|
764
|
next if !$opt->{bio_codons} && $bench =~ /Codons/; |
453
|
158
|
100
|
100
|
|
|
693
|
next if !$opt->{time_piece} && $bench =~ /Time::Piece/; |
454
|
152
|
100
|
100
|
|
|
615
|
next if $opt->{ver} && $benchmarks->{$bench}->[5] && $opt->{ver} < $benchmarks->{$bench}->[5]; |
|
|
|
100
|
|
|
|
|
455
|
150
|
100
|
100
|
|
|
700
|
next if $opt->{exclude} && $bench =~ /$opt->{exclude}/; |
456
|
144
|
100
|
100
|
|
|
990
|
next if $opt->{include} && $bench !~ /$opt->{include}/; |
457
|
23
|
50
|
|
|
|
157
|
if ($bench =~ /Bio/) { |
458
|
0
|
|
|
|
|
0
|
require Bio::SeqIO; |
459
|
0
|
|
|
|
|
0
|
require Bio::Tools::SeqStats; |
460
|
|
|
|
|
|
|
} |
461
|
23
|
|
|
|
|
141
|
my ($time, $res) = mce_bench_run($opt, $benchmarks->{$bench}); |
462
|
23
|
|
50
|
|
|
523
|
my $score = int(1000*$opt->{threads}*$benchmarks->{$bench}->[1]/($time || 1)+0.5); |
463
|
23
|
|
|
|
|
127
|
$total_score += $score; |
464
|
23
|
|
|
|
|
88
|
$total_time += $time; |
465
|
23
|
|
|
|
|
72
|
$i++; |
466
|
23
|
|
|
|
|
72
|
push @{$stats->{$bench}->{times}}, $time; |
|
23
|
|
|
|
|
404
|
|
467
|
23
|
|
|
|
|
94
|
push @{$stats->{$bench}->{scores}}, $score; |
|
23
|
|
|
|
|
265
|
|
468
|
23
|
100
|
|
|
|
267
|
my $d = $stats->{$bench}->{$opt->{time} ? 'times' : 'scores'}->[-1]; |
469
|
23
|
100
|
|
|
|
174
|
$stats->{$bench}->{fail}++ if $res ne 'Pass'; |
470
|
23
|
|
|
|
|
297
|
print pad_to("$bench:").pad_to(sprintf($opt->{f}, $d)); |
471
|
23
|
100
|
|
|
|
297
|
print "$res" unless $opt->{time}; |
472
|
23
|
|
|
|
|
351
|
print "\n"; |
473
|
23
|
50
|
|
|
|
257
|
sleep $opt->{sleep} if $opt->{sleep}; |
474
|
|
|
|
|
|
|
} |
475
|
8
|
100
|
|
|
|
418
|
die "No tests to run\n" unless $i; |
476
|
7
|
|
|
|
|
51
|
my $s = int($total_score/$i+0.5); |
477
|
7
|
100
|
|
|
|
77
|
print pad_to("Overall $title: ").sprintf($opt->{f}."\n", $opt->{time} ? $total_time : $s); |
478
|
7
|
|
|
|
|
59
|
push @{$stats->{total}->{times}}, $total_time; |
|
7
|
|
|
|
|
131
|
|
479
|
7
|
|
|
|
|
40
|
push @{$stats->{total}->{scores}}, $s; |
|
7
|
|
|
|
|
1251
|
|
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
sub mce_bench_run { |
483
|
23
|
|
|
23
|
0
|
87
|
my $opt = shift; |
484
|
23
|
|
|
|
|
72
|
my $benchmark = shift; |
485
|
23
|
100
|
|
|
|
138
|
$benchmark->[3] = $benchmark->[4] unless $opt->{quick}; |
486
|
23
|
100
|
|
|
|
143
|
return bench_run($benchmark) if $opt->{no_mce}; |
487
|
|
|
|
|
|
|
|
488
|
|
|
|
|
|
|
my @stats = mce_loop { |
489
|
0
|
|
|
0
|
|
0
|
my ($mce, $chunk_ref, $chunk_id) = @_; |
490
|
0
|
|
|
|
|
0
|
for (@{$chunk_ref}) { |
|
0
|
|
|
|
|
0
|
|
491
|
0
|
|
|
|
|
0
|
my ($time, $res) = bench_run($benchmark); |
492
|
0
|
|
|
|
|
0
|
MCE->gather([$time, $res]); |
493
|
|
|
|
|
|
|
} |
494
|
|
|
|
|
|
|
} |
495
|
1
|
|
|
|
|
37
|
(1 .. $opt->{threads} * $opt->{repeat}); |
496
|
|
|
|
|
|
|
|
497
|
1
|
|
|
|
|
20075905
|
my ($res, $time) = ('Pass', 0); |
498
|
1
|
|
|
|
|
34
|
foreach (@stats) { |
499
|
2
|
|
|
|
|
32
|
$time += $_->[0]; |
500
|
2
|
50
|
|
|
|
45
|
$res = $_->[1] if $_->[1] ne 'Pass'; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
1
|
|
50
|
|
|
57
|
return $time/($opt->{threads}*$opt->{repeat} || 1), $res; |
504
|
|
|
|
|
|
|
} |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
sub bench_run { |
507
|
23
|
|
|
23
|
0
|
207
|
my ($benchmark, $srand) = @_; |
508
|
23
|
|
100
|
|
|
195
|
$srand //= 1; |
509
|
23
|
|
|
|
|
83
|
srand($srand); # For repeatability |
510
|
23
|
|
|
|
|
196
|
my $t0 = clock_gettime(CLOCK_MONOTONIC); |
511
|
23
|
|
|
|
|
328
|
my $out = $benchmark->[2]->($benchmark->[3]); |
512
|
22
|
|
|
|
|
42014
|
my $time = sprintf("%.3f", clock_gettime(CLOCK_MONOTONIC)-$t0); |
513
|
22
|
100
|
|
|
|
990
|
my $r = $out eq $benchmark->[0] ? 'Pass' : "Fail ($out)"; |
514
|
22
|
|
|
|
|
351
|
return $time, $r; |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
sub bench_astro { |
518
|
1
|
|
|
1
|
0
|
3
|
my $iter = shift; |
519
|
1
|
|
|
|
|
48
|
my $d = Digest->new("MD5"); |
520
|
|
|
|
|
|
|
my $precessed = precess([rand(24), rand(180)-90], rand(200)+1900, rand(200)+1900) |
521
|
1
|
|
|
|
|
87
|
for (1..$iter*10); |
522
|
1
|
|
|
|
|
11212441
|
my $constellation_abbrev; |
523
|
|
|
|
|
|
|
$d->add(constellation_for_eq(rand(24), rand(180)-90, rand(200)+1900)) |
524
|
1
|
|
|
|
|
26
|
for (1..$iter); |
525
|
1
|
|
|
|
|
8565950
|
return $d->hexdigest; |
526
|
|
|
|
|
|
|
} |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
sub bench_bioperl_codons { |
529
|
0
|
|
|
0
|
0
|
0
|
my $skip = shift; |
530
|
0
|
|
|
|
|
0
|
my $iter = shift; |
531
|
0
|
|
|
|
|
0
|
my $d = Digest->new("MD5"); |
532
|
0
|
|
|
|
|
0
|
my $file = catfile($datadir, "gbbct5.seq"); |
533
|
0
|
|
|
|
|
0
|
foreach (1..$iter) { |
534
|
0
|
|
|
|
|
0
|
my $in = Bio::SeqIO->new(-file => $file, -format => "genbank"); |
535
|
0
|
|
|
|
|
0
|
$in->next_seq for (1..$skip); |
536
|
0
|
|
|
|
|
0
|
my $seq = $in->next_seq; |
537
|
0
|
|
|
|
|
0
|
my $seq_stats = Bio::Tools::SeqStats->new($seq); |
538
|
0
|
|
|
|
|
0
|
my $codon_ref = $seq_stats->count_codons(); |
539
|
0
|
|
|
|
|
0
|
$d->add($_, $codon_ref->{$_}) for sort keys %$codon_ref; |
540
|
|
|
|
|
|
|
} |
541
|
0
|
|
|
|
|
0
|
return $d->hexdigest; |
542
|
|
|
|
|
|
|
} |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
sub bench_bioperl_mono { |
545
|
0
|
|
|
0
|
0
|
0
|
my $iter = shift; |
546
|
0
|
|
|
|
|
0
|
my $file = catfile($datadir, "gbbct5.seq"); |
547
|
0
|
|
|
|
|
0
|
my $in = Bio::SeqIO->new(-file => $file, -format => "genbank"); |
548
|
0
|
|
|
|
|
0
|
my $d = Digest->new("MD5"); |
549
|
0
|
|
|
|
|
0
|
my $builder = $in->sequence_builder(); |
550
|
0
|
|
|
|
|
0
|
$builder->want_none(); |
551
|
0
|
|
|
|
|
0
|
$builder->add_wanted_slot('display_id','seq'); |
552
|
0
|
|
|
|
|
0
|
for (1..$iter) { |
553
|
0
|
|
|
|
|
0
|
my $seq = $in->next_seq; |
554
|
0
|
|
|
|
|
0
|
my $seq_stats = Bio::Tools::SeqStats->new($seq); |
555
|
0
|
|
|
|
|
0
|
my $weight = $seq_stats->get_mol_wt(); |
556
|
0
|
|
|
|
|
0
|
$d->add(int($weight->[0])); |
557
|
0
|
|
|
|
|
0
|
my $monomer_ref = $seq_stats->count_monomers(); |
558
|
0
|
|
|
|
|
0
|
$d->add($_, $monomer_ref->{$_}) for sort keys %$monomer_ref; |
559
|
|
|
|
|
|
|
} |
560
|
0
|
|
|
|
|
0
|
return $d->hexdigest; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
sub bench_css { |
564
|
1
|
|
|
1
|
0
|
5
|
my $iter = shift; |
565
|
1
|
|
|
|
|
10
|
my $d = Digest->new("MD5"); |
566
|
1
|
|
|
|
|
67
|
my $file; |
567
|
|
|
|
|
|
|
my $html; |
568
|
1
|
|
|
|
|
5
|
for (1..$iter) { |
569
|
2
|
|
|
|
|
3654
|
my $inliner = new CSS::Inliner(); |
570
|
2
|
|
|
|
|
2613
|
my $i = $_ % 2 + 1; |
571
|
2
|
|
|
|
|
36
|
$file = catfile($datadir, "wiki$i.html"); |
572
|
2
|
|
|
|
|
36
|
$inliner->read_file({ filename => $file }); |
573
|
2
|
|
|
|
|
15657169
|
$html = $inliner->inlinify(); |
574
|
2
|
|
|
|
|
16411590
|
$d->add(Encode::encode_utf8($html)); |
575
|
|
|
|
|
|
|
} |
576
|
1
|
|
|
|
|
28623
|
return $d->hexdigest; |
577
|
|
|
|
|
|
|
} |
578
|
|
|
|
|
|
|
|
579
|
|
|
|
|
|
|
sub bench_datetime { |
580
|
1
|
|
|
1
|
0
|
5
|
my $iter = shift; |
581
|
1
|
|
|
|
|
5
|
my @tz = map {DateTime::TimeZone->new( name => $_ )} qw(UTC Europe/London America/New_York); |
|
3
|
|
|
|
|
20923
|
|
582
|
1
|
|
|
|
|
3968
|
my $d = Digest->new("MD5"); |
583
|
1
|
|
|
|
|
40
|
my $str; |
584
|
|
|
|
|
|
|
|
585
|
1
|
|
|
|
|
6
|
for (1..$iter) { |
586
|
5000
|
|
|
|
|
136361
|
my $dt = DateTime->now(); |
587
|
5000
|
|
|
|
|
1393721
|
my $dt1 = DateTime->from_epoch( |
588
|
|
|
|
|
|
|
epoch => 946684800 + rand(100000000), |
589
|
|
|
|
|
|
|
); |
590
|
5000
|
|
|
|
|
1425841
|
my $dt2 = DateTime->from_epoch( |
591
|
|
|
|
|
|
|
epoch => 946684800 + rand(100000000), |
592
|
|
|
|
|
|
|
); |
593
|
5000
|
|
|
|
|
1396687
|
$str = $dt2->strftime('%FT%T')."\n"; |
594
|
5000
|
|
|
|
|
585812
|
$d->add($str); |
595
|
5000
|
|
|
|
|
9671
|
eval {$dt2->set_time_zone($tz[int(rand(3))])}; |
|
5000
|
|
|
|
|
19991
|
|
596
|
5000
|
|
|
|
|
1136416
|
my $dur = $dt2->subtract_datetime($dt1); |
597
|
5000
|
|
|
|
|
6368308
|
eval {$dt2->add_duration($dur)}; |
|
5000
|
|
|
|
|
18226
|
|
598
|
5000
|
|
|
|
|
6342937
|
eval {$dt2->subtract(days => int(rand(1000)+1))}; |
|
5000
|
|
|
|
|
25096
|
|
599
|
5000
|
|
|
|
|
6898194
|
$dt->week; |
600
|
5000
|
|
|
|
|
132509
|
$dt->epoch; |
601
|
5000
|
|
|
|
|
41377
|
$d->add($dt2->strftime('%FT%T')); |
602
|
5000
|
|
|
|
|
613718
|
eval {$dt2->set( year => int(rand(2030)))}; |
|
5000
|
|
|
|
|
20882
|
|
603
|
5000
|
|
|
|
|
3419825
|
$d->add($dt2->ymd('/')); |
604
|
|
|
|
|
|
|
} |
605
|
1
|
|
|
|
|
41
|
return $d->hexdigest; |
606
|
|
|
|
|
|
|
} |
607
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
sub bench_dbi { |
609
|
1
|
|
|
1
|
0
|
5
|
my $iter = shift; |
610
|
1
|
|
|
|
|
10
|
my $d = Digest->new("MD5"); |
611
|
1
|
|
|
|
|
132
|
my $dbh = DBI->connect( 'DBI:Mock:', '', '' ); |
612
|
1
|
|
|
|
|
21907
|
my ($data, $cols) = _db_data(); |
613
|
|
|
|
|
|
|
|
614
|
1
|
|
|
|
|
8
|
foreach (1..$iter) { |
615
|
5000
|
|
|
|
|
2311088
|
my $inserter = SQL::Inserter->new( |
616
|
|
|
|
|
|
|
dbh => $dbh, |
617
|
|
|
|
|
|
|
table => 'table', |
618
|
|
|
|
|
|
|
cols => $cols, |
619
|
|
|
|
|
|
|
buffer => 2 |
620
|
|
|
|
|
|
|
); |
621
|
5000
|
|
|
|
|
167151
|
$inserter->insert($data->[int(rand(20))]) for 1..2; |
622
|
5000
|
|
|
|
|
3731160
|
$d->add($dbh->last_insert_id); |
623
|
5000
|
|
|
|
|
57137
|
my $sql = SQL::Abstract::Classic->new(); |
624
|
5000
|
|
|
|
|
231392
|
my ($stmt, @bind) = $sql->insert('table', $data->[int(rand(20))]); |
625
|
5000
|
|
|
|
|
3921510
|
$d->add($dbh->quote($stmt)); |
626
|
5000
|
|
|
|
|
87662
|
($stmt, @bind) = $sql->select('table', $cols->[int(rand(20))], [map {_rand_where()} 1..int(rand(3)+1)]); |
|
10091
|
|
|
|
|
22951
|
|
627
|
5000
|
|
|
|
|
6048879
|
$d->add($dbh->quote($stmt._random_str(5))); |
628
|
5000
|
|
|
|
|
89630
|
my $dbh2 = DBI->connect( 'DBI:Mock:', '', '' ); |
629
|
|
|
|
|
|
|
} |
630
|
1
|
|
|
|
|
522
|
return $d->hexdigest; |
631
|
|
|
|
|
|
|
} |
632
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
sub bench_dct { |
634
|
2
|
|
|
2
|
0
|
21
|
my $iter = shift; |
635
|
2
|
|
|
|
|
40
|
my $d = Digest->new("MD5"); |
636
|
2
|
|
|
|
|
136
|
$d->add(bench_dct_sz(@$_)) foreach [$iter, 32], [$iter, 18], [$iter*8,8]; |
637
|
|
|
|
|
|
|
|
638
|
2
|
|
|
|
|
61
|
return $d->hexdigest; |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
sub bench_dct_sz { |
642
|
6
|
|
|
6
|
0
|
48
|
my $iter = shift; |
643
|
6
|
|
|
|
|
41
|
my $sz = shift; |
644
|
6
|
|
|
|
|
77
|
my $d = Digest->new("MD5"); |
645
|
6
|
|
|
|
|
333
|
my @arrays; |
646
|
6
|
|
|
|
|
176
|
push @arrays, [map { rand(256) } ( 1..$sz*$sz )] foreach 1..10; |
|
28240
|
|
|
|
|
39996
|
|
647
|
6
|
|
|
|
|
58
|
foreach (1..$iter) { |
648
|
500000
|
|
|
|
|
1028983
|
my $dct = dct2d($arrays[$iter % 10], $sz); |
649
|
500000
|
100
|
|
|
|
16842282
|
$d->add($dct->[0]) if $_ % 10 == 1; |
650
|
|
|
|
|
|
|
} |
651
|
6
|
|
|
|
|
1184
|
return $d->hexdigest; |
652
|
|
|
|
|
|
|
} |
653
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
sub bench_digest { |
655
|
1
|
|
|
1
|
0
|
5
|
my $iter = shift; |
656
|
1
|
|
|
|
|
9
|
my $str = _read_wiki_files(); |
657
|
1
|
|
|
|
|
15
|
my $d = Digest->new("MD5"); |
658
|
1
|
|
|
|
|
76
|
my $hex; |
659
|
1
|
|
|
|
|
6
|
foreach (1..$iter) { |
660
|
50
|
|
|
|
|
250
|
my $d2 = Digest->new("MD5"); |
661
|
50
|
|
|
|
|
430433
|
$d2->add($str); |
662
|
50
|
|
|
|
|
500
|
$hex = $d2->hexdigest; |
663
|
50
|
|
|
|
|
228
|
$d->add($hex); |
664
|
50
|
|
|
|
|
234
|
$d2 = Digest->new("SHA-512"); |
665
|
50
|
|
|
|
|
1133356
|
$d2->add($str); |
666
|
50
|
|
|
|
|
765
|
$hex = $d2->hexdigest; |
667
|
50
|
|
|
|
|
286
|
$d->add($hex); |
668
|
50
|
|
|
|
|
258
|
$d2 = Digest->new("SHA-1"); |
669
|
50
|
|
|
|
|
661487
|
$d2->add($str); |
670
|
50
|
|
|
|
|
606
|
$hex = $d2->hexdigest; |
671
|
50
|
|
|
|
|
435
|
$d->add($hex); |
672
|
|
|
|
|
|
|
} |
673
|
1
|
|
|
|
|
16
|
return $d->hexdigest; |
674
|
|
|
|
|
|
|
} |
675
|
|
|
|
|
|
|
|
676
|
|
|
|
|
|
|
sub bench_encode { |
677
|
1
|
|
|
1
|
0
|
4
|
my $iter = shift; |
678
|
1
|
|
|
|
|
6
|
my $str = _read_wiki_files('utf8'); |
679
|
1
|
|
|
|
|
13
|
my $UTF8 = Encode::find_encoding('UTF-8'); |
680
|
1
|
|
|
|
|
73
|
my $UTF16 = Encode::find_encoding('UTF-16'); |
681
|
1
|
|
|
|
|
4079
|
our $cp1252 = Encode::find_encoding('cp-1252'); |
682
|
1
|
|
|
|
|
452
|
my $res = 'PASS'; |
683
|
1
|
|
|
|
|
7
|
my $unenc = 0; |
684
|
|
|
|
|
|
|
|
685
|
1
|
|
|
|
|
7
|
foreach (1..$iter) { |
686
|
40
|
|
|
|
|
52312
|
my $bytes = encode_utf8($str); |
687
|
40
|
50
|
|
|
|
16586
|
$res = 'Fail' unless length($bytes) > length($str); |
688
|
40
|
|
|
|
|
51365
|
my $cp = decode_utf8($bytes); |
689
|
40
|
100
|
|
|
|
177800
|
my $enc = rand(1) > 0.25 ? $UTF8 : $UTF16; |
690
|
40
|
|
|
|
|
860014
|
$bytes = $enc->encode($cp); |
691
|
40
|
|
|
|
|
526287
|
$cp = $enc->decode($bytes); |
692
|
40
|
50
|
|
|
|
112813
|
$res = 'Fail' unless $cp eq $str; |
693
|
40
|
|
|
|
|
942842
|
my $str2 = $cp1252->encode($cp); |
694
|
40
|
|
|
|
|
1855799
|
$enc->encode($cp1252->decode($str2)); |
695
|
40
|
|
|
|
|
42764
|
$unenc = () = $str2 =~ /\?/g; # Non-encodable |
696
|
|
|
|
|
|
|
} |
697
|
1
|
|
|
|
|
19
|
return "$res $unenc"; |
698
|
|
|
|
|
|
|
} |
699
|
|
|
|
|
|
|
|
700
|
|
|
|
|
|
|
sub bench_imager { |
701
|
2
|
|
|
2
|
0
|
20
|
my $iter = shift; |
702
|
2
|
|
|
|
|
25
|
my $d = Digest->new("MD5"); |
703
|
|
|
|
|
|
|
|
704
|
2
|
|
|
|
|
118
|
my $data; |
705
|
2
|
100
|
|
|
|
281
|
open (my $fh, '<:raw', catfile($datadir,'M31.bmp')) or die $!; |
706
|
1
|
|
|
|
|
2634
|
read($fh, $data, -s $fh); |
707
|
1
|
|
|
|
|
24
|
close($fh); |
708
|
|
|
|
|
|
|
|
709
|
1
|
|
|
|
|
7
|
foreach (1..$iter) { |
710
|
4
|
50
|
|
|
|
532138
|
my $img = Imager->new(data=>$data, type=>'bmp') or die Imager->errstr(); |
711
|
4
|
|
|
|
|
104072
|
my $thumb = $img->scale(scalefactor=>.3); |
712
|
4
|
|
|
|
|
297307
|
my $newimg = $img->scale(scalefactor=>1.15); |
713
|
4
|
|
|
|
|
682490
|
$newimg->filter(type=>'autolevels'); |
714
|
4
|
|
|
|
|
77886
|
$newimg->filter(type=>"gaussian", stddev=>0.5); |
715
|
4
|
|
|
|
|
638113
|
$newimg->paste(left=>40,top=>20,img=>$thumb); |
716
|
4
|
|
|
|
|
3265
|
$newimg->rubthrough(src=>$thumb,tx=>30, ty=>50); |
717
|
4
|
|
|
|
|
2923
|
$newimg->compose(src => $thumb, tx => 30, ty => 20, combine => 'color'); |
718
|
4
|
|
|
|
|
36580
|
$newimg->flip(dir=>"h"); |
719
|
4
|
|
|
|
|
37467
|
$newimg->flip(dir=>"vh"); |
720
|
4
|
|
|
|
|
36622
|
$d->add(scalar(Image::PHash->new($newimg)->pHash)); |
721
|
4
|
|
|
|
|
156688
|
$newimg = $img->crop(left=>50, right=>100, top=>10, bottom=>100); |
722
|
4
|
|
|
|
|
1406
|
$newimg = $img->crop(left=>50, top=>10, width=>50, height=>90); |
723
|
4
|
|
|
|
|
768
|
$newimg = $img->copy(); |
724
|
4
|
|
|
|
|
29248
|
$newimg->filter(type=>"unsharpmask", stddev=>1, scale=>0.5); |
725
|
4
|
|
|
|
|
737172
|
$newimg = $img->rotate(degrees=>20); |
726
|
4
|
|
|
|
|
403976
|
$newimg->filter(type=>"contrast", intensity=>1.4); |
727
|
4
|
|
|
|
|
135896
|
$newimg = $img->convert(matrix => [[0, 1, 0], [1, 0, 0], [0, 0, 1]]); |
728
|
4
|
|
|
|
|
49072
|
$newimg = $img->convert(preset=>'grey'); |
729
|
4
|
|
|
|
|
44788
|
$d->add(scalar(Image::PHash->new($newimg)->pHash)); |
730
|
4
|
|
|
|
|
134107
|
$img->filter(type=>'mandelbrot'); |
731
|
|
|
|
|
|
|
} |
732
|
1
|
|
|
|
|
177354
|
return $d->hexdigest; |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
sub bench_json { |
736
|
1
|
|
|
1
|
0
|
4
|
my $iter = shift; |
737
|
1
|
|
|
|
|
7
|
my $res = 'PASS'; |
738
|
1
|
|
|
|
|
6
|
for (1..$iter) { |
739
|
600
|
|
|
|
|
1927
|
my $len = int(rand(40)) + 1; |
740
|
600
|
|
|
|
|
1390
|
my $obj = rand_hash($len); |
741
|
600
|
|
|
|
|
25980
|
my $str = encode_json($obj); |
742
|
600
|
|
|
|
|
1467
|
foreach (1..100) { |
743
|
60000
|
|
|
|
|
2540715
|
$obj = decode_json($str); |
744
|
60000
|
|
|
|
|
2147513
|
$str = encode_json($obj); |
745
|
|
|
|
|
|
|
} |
746
|
600
|
|
|
|
|
23370
|
my $obj2 = decode_json($str); |
747
|
600
|
50
|
|
|
|
2176
|
$res = 'FAIL' unless compare_obj($obj, $obj2); |
748
|
|
|
|
|
|
|
} |
749
|
1
|
|
|
|
|
11
|
return $res; |
750
|
|
|
|
|
|
|
} |
751
|
|
|
|
|
|
|
|
752
|
|
|
|
|
|
|
sub bench_jwt { |
753
|
1
|
|
|
1
|
0
|
5
|
my $iter = shift; |
754
|
1
|
|
|
|
|
9
|
my $d = Digest->new("MD5"); |
755
|
1
|
|
|
|
|
72
|
my $data = _random_str(5000); |
756
|
1
|
|
|
|
|
11
|
my $rsa ='-----BEGIN PRIVATE KEY----- |
757
|
|
|
|
|
|
|
MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqPfgaTEWEP3S9w0t |
758
|
|
|
|
|
|
|
gsicURfo+nLW09/0KfOPinhYZ4ouzU+3xC4pSlEp8Ut9FgL0AgqNslNaK34Kq+NZ |
759
|
|
|
|
|
|
|
jO9DAQIDAQABAkAgkuLEHLaqkWhLgNKagSajeobLS3rPT0Agm0f7k55FXVt743hw |
760
|
|
|
|
|
|
|
Ngkp98bMNrzy9AQ1mJGbQZGrpr4c8ZAx3aRNAiEAoxK/MgGeeLui385KJ7ZOYktj |
761
|
|
|
|
|
|
|
hLBNAB69fKwTZFsUNh0CIQEJQRpFCcydunv2bENcN/oBTRw39E8GNv2pIcNxZkcb |
762
|
|
|
|
|
|
|
NQIgbYSzn3Py6AasNj6nEtCfB+i1p3F35TK/87DlPSrmAgkCIQDJLhFoj1gbwRbH |
763
|
|
|
|
|
|
|
/bDRPrtlRUDDx44wHoEhSDRdy77eiQIgE6z/k6I+ChN1LLttwX0galITxmAYrOBh |
764
|
|
|
|
|
|
|
BVl433tgTTQ= |
765
|
|
|
|
|
|
|
-----END PRIVATE KEY-----'; |
766
|
1
|
|
|
|
|
5
|
my $key = '-----BEGIN PRIVATE KEY----- |
767
|
|
|
|
|
|
|
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgYirTZSx+5O8Y6tlG |
768
|
|
|
|
|
|
|
cka6W6btJiocdrdolfcukSoTEk+hRANCAAQkvPNu7Pa1GcsWU4v7ptNfqCJVq8Cx |
769
|
|
|
|
|
|
|
zo0MUVPQgwJ3aJtNM1QMOQUayCrRwfklg+D/rFSUwEUqtZh7fJDiFqz3 |
770
|
|
|
|
|
|
|
-----END PRIVATE KEY-----'; |
771
|
1
|
|
|
|
|
9
|
foreach (1..$iter) { |
772
|
250
|
|
|
|
|
671
|
my $extra = _random_str(100); |
773
|
250
|
|
|
|
|
1019
|
my $data_in = $data.$extra; |
774
|
250
|
|
|
|
|
941
|
my $token = encode_jwt( |
775
|
|
|
|
|
|
|
payload => $data_in, |
776
|
|
|
|
|
|
|
alg => 'ES256', |
777
|
|
|
|
|
|
|
key => \$key, |
778
|
|
|
|
|
|
|
); |
779
|
|
|
|
|
|
|
|
780
|
250
|
|
|
|
|
2193096
|
my $data_out = _decode_jwt2(token=>$token, key=>\$key); |
781
|
250
|
50
|
|
|
|
1062
|
$d->add($token) if $data_in eq $data_out.$extra; |
782
|
|
|
|
|
|
|
|
783
|
250
|
|
|
|
|
899
|
$token = encode_jwt( |
784
|
|
|
|
|
|
|
payload => $data_in, |
785
|
|
|
|
|
|
|
alg => 'RS256', |
786
|
|
|
|
|
|
|
key => \$rsa, |
787
|
|
|
|
|
|
|
); |
788
|
|
|
|
|
|
|
|
789
|
250
|
|
|
|
|
212282
|
$data_out = _decode_jwt2(token=>$token, key=>\$rsa); |
790
|
250
|
50
|
|
|
|
1382
|
$d->add($token) if $data_in eq $data_out.$extra; |
791
|
|
|
|
|
|
|
} |
792
|
1
|
|
|
|
|
26
|
return $d->hexdigest; |
793
|
|
|
|
|
|
|
} |
794
|
|
|
|
|
|
|
|
795
|
|
|
|
|
|
|
sub bench_formattext { |
796
|
1
|
|
|
1
|
0
|
6
|
my $iter = shift; |
797
|
1
|
|
|
|
|
17
|
my $d = Digest->new("MD5"); |
798
|
1
|
|
|
|
|
66
|
my $file; |
799
|
1
|
|
|
|
|
7
|
for (0..$iter-1) { |
800
|
4
|
|
|
|
|
5628444
|
my $i = $_ % 2; |
801
|
4
|
|
|
|
|
74
|
$file = catfile($datadir, "wiki$i.html"); |
802
|
4
|
|
|
|
|
72
|
my $tree = HTML::TreeBuilder->new->parse_file($file); |
803
|
4
|
|
|
|
|
14139341
|
my $formatter = HTML::FormatText->new(); |
804
|
4
|
|
|
|
|
228
|
my $text = $formatter->format($tree); |
805
|
4
|
|
|
|
|
10784934
|
$formatter = HTML::FormatText->new(leftmargin => 0, rightmargin => 30); |
806
|
4
|
|
|
|
|
17787
|
$d->add(Encode::encode_utf8($formatter->format($tree))); |
807
|
|
|
|
|
|
|
} |
808
|
1
|
|
|
|
|
5232345
|
return $d->hexdigest; |
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
sub bench_matrixreal { |
812
|
2
|
|
|
2
|
0
|
15
|
my $iter = shift; |
813
|
2
|
|
|
|
|
57
|
my $d = Digest->new("MD5"); |
814
|
2
|
|
|
|
|
197
|
my $smatrix = Math::MatrixReal->new_random(13); |
815
|
2
|
|
|
|
|
2755
|
my $matrix = Math::MatrixReal->new_random(20); |
816
|
2
|
|
|
|
|
4223
|
my $bmatrix = Math::MatrixReal->new_random(72); |
817
|
|
|
|
|
|
|
|
818
|
2
|
|
|
|
|
45123
|
for (1..$iter) { |
819
|
1300
|
|
|
|
|
14912
|
my $r = rand(10); |
820
|
1300
|
|
|
|
|
7126
|
my $m1 = $r*$bmatrix; |
821
|
1300
|
|
|
|
|
9327032
|
my $m2 = $bmatrix*$r; |
822
|
1300
|
|
|
|
|
9108865
|
my $m3 = $bmatrix->multiply_scalar($bmatrix,$r); |
823
|
|
|
|
|
|
|
# Should be zero |
824
|
1300
|
100
|
|
|
|
8305345
|
$d->add($m1->element(1, 1) + $m2->element(1, 1) - 2 * $bmatrix->element(1, 1)) |
825
|
|
|
|
|
|
|
if $_ % 10 == 1; |
826
|
|
|
|
|
|
|
|
827
|
1300
|
|
|
|
|
15289
|
my $m = $matrix->det; |
828
|
1300
|
100
|
|
|
|
15671784
|
$d->add($m) if $_ % 10 == 1; |
829
|
1300
|
|
|
|
|
4752
|
$m =$matrix->decompose_LR->det_LR; |
830
|
1300
|
100
|
|
|
|
15529575
|
$d->add($m) if $_ % 10 == 1; |
831
|
1300
|
|
|
|
|
8345
|
$m1 = $matrix ** 2; |
832
|
1300
|
|
|
|
|
16329023
|
$m2 = $matrix * $matrix; |
833
|
|
|
|
|
|
|
#should be zero |
834
|
1300
|
100
|
|
|
|
15861379
|
$d->add($m1->element(1, 1) - $m2->element(1, 1)) |
835
|
|
|
|
|
|
|
if $_ % 10 == 1; |
836
|
1300
|
|
|
|
|
12193
|
$m1 = $smatrix->inverse(); |
837
|
1300
|
|
|
|
|
14412691
|
$m2 = $smatrix ** -1; |
838
|
1300
|
|
|
|
|
14873974
|
$m3 = $smatrix->decompose_LR->invert_LR; |
839
|
1300
|
100
|
|
|
|
14333866
|
$d->add($m1->element(1, 1), $m2->element(1, 1), $m3->element(1, 1)) |
840
|
|
|
|
|
|
|
if $_ % 10 == 1; |
841
|
|
|
|
|
|
|
} |
842
|
|
|
|
|
|
|
|
843
|
2
|
|
|
|
|
312
|
return $d->hexdigest; |
844
|
|
|
|
|
|
|
} |
845
|
|
|
|
|
|
|
|
846
|
|
|
|
|
|
|
sub bench_moose { |
847
|
1
|
|
|
1
|
0
|
3
|
my $iter = shift; |
848
|
1
|
|
|
|
|
3
|
my $cnt = 0; |
849
|
|
|
|
|
|
|
|
850
|
1
|
|
|
|
|
5
|
for (1..$iter) { |
851
|
10000
|
|
|
|
|
4381130
|
my $p = rand(1000); |
852
|
10000
|
|
|
|
|
35693
|
my $root = Benchmark::DKbench::MooseTree->new(node => 'root'); |
853
|
10000
|
|
|
|
|
11451420
|
$root->price($p); |
854
|
10000
|
|
|
|
|
275816
|
$root->node; |
855
|
10000
|
|
|
|
|
29048
|
$root->cost; |
856
|
10000
|
|
|
|
|
34046
|
my $lchild = $root->left; |
857
|
10000
|
|
|
|
|
293429
|
$lchild->node('child'); |
858
|
10000
|
|
|
|
|
280255
|
$lchild->price($p); |
859
|
10000
|
|
|
|
|
275185
|
$lchild->tax; |
860
|
10000
|
|
|
|
|
33407
|
my $child = $root->right; |
861
|
10000
|
|
|
|
|
29952
|
$child->cost; |
862
|
10000
|
|
|
|
|
32562
|
my $grandchild = $child->left; |
863
|
10000
|
|
|
|
|
286302
|
$grandchild->node('grandchild'); |
864
|
10000
|
|
|
|
|
314870
|
$grandchild->has_parent; |
865
|
10000
|
|
|
|
|
271249
|
$grandchild->parent; |
866
|
10000
|
|
|
|
|
274312
|
$grandchild->price($p); |
867
|
10000
|
|
|
|
|
27893
|
$grandchild->cost; |
868
|
10000
|
|
|
|
|
36597
|
my $ggchild = $grandchild->right; |
869
|
10000
|
|
|
|
|
33549
|
$ggchild->cost; |
870
|
10000
|
|
|
|
|
41563
|
$cnt += 5; |
871
|
|
|
|
|
|
|
} |
872
|
1
|
|
|
|
|
456
|
return md5_hex("$cnt objects"); |
873
|
|
|
|
|
|
|
} |
874
|
|
|
|
|
|
|
|
875
|
|
|
|
|
|
|
sub bench_moose_prv { |
876
|
2
|
|
|
2
|
0
|
11
|
my $iter = shift; |
877
|
2
|
|
|
|
|
47
|
my $tdir = catfile($datadir, 't'); |
878
|
2
|
|
|
|
|
19
|
my $result; |
879
|
2
|
100
|
|
|
|
17
|
if ($iter < 1) { |
880
|
1
|
|
|
|
|
8
|
$tdir = catfile($tdir, 'recipes'); |
881
|
1
|
|
|
|
|
20135685
|
$result = `prove -rQ $tdir`; |
882
|
|
|
|
|
|
|
} else { |
883
|
1
|
|
|
|
|
78164299
|
$result = `prove -rQ $tdir` for (1..$iter); |
884
|
|
|
|
|
|
|
} |
885
|
2
|
50
|
|
|
|
323
|
if ($result =~ /Result: (\w*)/) { |
886
|
2
|
|
|
|
|
240
|
return $1; |
887
|
|
|
|
|
|
|
} else { |
888
|
0
|
|
|
|
|
0
|
return '?'; |
889
|
|
|
|
|
|
|
} |
890
|
|
|
|
|
|
|
} |
891
|
|
|
|
|
|
|
|
892
|
|
|
|
|
|
|
sub bench_primes_m { |
893
|
1
|
|
|
1
|
0
|
37
|
my $iter = shift; |
894
|
1
|
|
|
|
|
76
|
return bench_primes($iter, 7_500_000); |
895
|
|
|
|
|
|
|
} |
896
|
|
|
|
|
|
|
|
897
|
|
|
|
|
|
|
sub bench_primes { |
898
|
1
|
|
|
1
|
0
|
41
|
my $iter = shift; |
899
|
1
|
|
|
|
|
44
|
my $max = shift; |
900
|
1
|
|
|
|
|
35
|
my @primes; |
901
|
1
|
|
|
|
|
87
|
@primes = _get_primes($max) for (1..$iter); |
902
|
1
|
|
|
|
|
10102
|
return md5_hex(scalar(@primes)." primes up to $max"); |
903
|
|
|
|
|
|
|
} |
904
|
|
|
|
|
|
|
|
905
|
|
|
|
|
|
|
sub bench_regex_asc { |
906
|
1
|
|
|
1
|
0
|
12
|
my $iter = shift; |
907
|
1
|
|
|
|
|
24
|
return bench_regex_subst($iter, ''); |
908
|
|
|
|
|
|
|
} |
909
|
|
|
|
|
|
|
|
910
|
|
|
|
|
|
|
sub bench_regex_utf8 { |
911
|
1
|
|
|
1
|
0
|
19
|
my $iter = shift; |
912
|
1
|
|
|
|
|
47
|
return bench_regex_subst($iter, 'utf8'); |
913
|
|
|
|
|
|
|
} |
914
|
|
|
|
|
|
|
|
915
|
|
|
|
|
|
|
sub bench_regex_subst { |
916
|
2
|
|
|
2
|
0
|
24
|
my $iter = shift; |
917
|
2
|
|
|
|
|
21
|
my $enc = shift; |
918
|
2
|
|
|
|
|
32
|
my $str = _read_wiki_files($enc); |
919
|
2
|
|
|
|
|
20
|
my $match = bench_regex($str, $iter); |
920
|
2
|
|
|
|
|
19
|
my $repl = bench_subst($str, $iter); |
921
|
2
|
|
|
|
|
43
|
return md5_hex($match, $repl); |
922
|
|
|
|
|
|
|
} |
923
|
|
|
|
|
|
|
|
924
|
|
|
|
|
|
|
sub bench_regex { |
925
|
2
|
|
|
2
|
0
|
7
|
my $str = shift; |
926
|
2
|
|
|
|
|
11
|
my $iter = shift; |
927
|
2
|
|
|
|
|
8
|
my $count; |
928
|
2
|
|
|
|
|
18
|
for (1..$iter) { |
929
|
11
|
|
|
|
|
96
|
$count = 0; |
930
|
11
|
|
|
|
|
1077698
|
$count += () = $str =~ /\b[A-Z][a-z]+/g; |
931
|
11
|
|
|
|
|
1283209
|
$count += () = $str =~ /([\w\.+-]+)@[\w\.-]+\.([\w\.-]+)/g; |
932
|
11
|
|
|
|
|
933659
|
$count += () = $str =~ m![\w]+://[^/\s?#]+[^\s?#]+(?:\?[^\s#]*)?(?:#[^\s]*)?!g; |
933
|
|
|
|
|
|
|
} |
934
|
2
|
|
|
|
|
73
|
return "$count Matched"; |
935
|
|
|
|
|
|
|
} |
936
|
|
|
|
|
|
|
|
937
|
|
|
|
|
|
|
sub bench_subst { |
938
|
2
|
|
|
2
|
0
|
8
|
my $str = shift; |
939
|
2
|
|
|
|
|
20
|
my $iter = shift; |
940
|
2
|
|
|
|
|
8
|
my $count; |
941
|
2
|
|
|
|
|
20
|
for (1..$iter) { |
942
|
11
|
|
|
|
|
185
|
my $copy = $str; |
943
|
11
|
|
|
|
|
35
|
$count = 0; |
944
|
11
|
|
|
|
|
972846
|
while (my $s = $copy =~ s#<([^>]+)>([^>]*?)</\1>#$2#g) { |
945
|
44
|
|
|
|
|
3711458
|
$count += $s; |
946
|
|
|
|
|
|
|
} |
947
|
11
|
|
|
|
|
561406
|
$copy = substr($copy, int(rand(100))+1) for 1..10; |
948
|
|
|
|
|
|
|
} |
949
|
2
|
|
|
|
|
48
|
return "$count Replaced"; |
950
|
|
|
|
|
|
|
} |
951
|
|
|
|
|
|
|
|
952
|
|
|
|
|
|
|
sub bench_textlevenshtein { |
953
|
1
|
|
|
1
|
0
|
9
|
my $iter = shift; |
954
|
1
|
|
|
|
|
48
|
my $d = Digest->new("MD5"); |
955
|
1
|
|
|
|
|
119
|
my $data = _fuzzy_data(); |
956
|
1
|
|
|
|
|
8
|
my $diff; |
957
|
1
|
|
|
|
|
11
|
foreach (1..$iter) { |
958
|
7
|
|
|
|
|
49
|
foreach my $sz (qw/10 100 1000 2500/) { |
959
|
28
|
|
|
|
|
70
|
my $n = scalar @{$data->{$sz}}; |
|
28
|
|
|
|
|
128
|
|
960
|
28
|
|
|
|
|
139
|
my $i = int(rand($n)); |
961
|
|
|
|
|
|
|
$diff = Text::Levenshtein::XS::distance( |
962
|
|
|
|
|
|
|
$data->{$sz}->[$i], $data->{$sz}->[$_] |
963
|
28
|
|
|
|
|
177
|
) for 0..$n-1; |
964
|
28
|
|
100
|
|
|
1774842
|
$d->add($diff || -1); |
965
|
28
|
100
|
|
|
|
143
|
next if $sz > 1000; |
966
|
|
|
|
|
|
|
$diff = Text::Levenshtein::Damerau::XS::xs_edistance( |
967
|
|
|
|
|
|
|
$data->{$sz}->[$i], $data->{$sz}->[$_] |
968
|
21
|
|
|
|
|
137
|
) for 0..$n-1; |
969
|
21
|
|
|
|
|
1648316
|
$d->add($diff); |
970
|
|
|
|
|
|
|
} |
971
|
|
|
|
|
|
|
} |
972
|
1
|
|
|
|
|
96
|
return $d->hexdigest; |
973
|
|
|
|
|
|
|
} |
974
|
|
|
|
|
|
|
|
975
|
|
|
|
|
|
|
sub bench_timepiece { |
976
|
1
|
|
|
1
|
0
|
14
|
my $iter = shift; |
977
|
1
|
|
|
|
|
23
|
my $t = Time::Piece::localtime(1692119499); |
978
|
1
|
|
|
|
|
202
|
my $d = Digest->new("MD5"); |
979
|
1
|
|
|
|
|
51
|
my $day = 3600*24; |
980
|
1
|
|
|
|
|
34
|
local $ENV{TZ} = 'UTC'; |
981
|
|
|
|
|
|
|
|
982
|
1
|
|
|
|
|
10
|
for (1..$iter) { |
983
|
75000
|
|
|
|
|
298838
|
$t += int(rand(1000)-500)*$day; |
984
|
75000
|
50
|
|
|
|
2193586
|
$t += 100000*$day if $t->year < 1970; |
985
|
75000
|
|
|
|
|
488812
|
my $str = $t->strftime("%w, %d %m %Y %H:%M:%S"); |
986
|
75000
|
|
|
|
|
5242560
|
eval '$t = Time::Piece->strptime($str, "%w, %d %m %Y %H:%M:%S")'; |
987
|
75000
|
|
|
|
|
1583931
|
my $jd = $t->julian_day; |
988
|
75000
|
|
|
|
|
5675781
|
$d->add($str,$jd); |
989
|
|
|
|
|
|
|
} |
990
|
1
|
|
|
|
|
20
|
return $d->hexdigest; |
991
|
|
|
|
|
|
|
} |
992
|
|
|
|
|
|
|
|
993
|
|
|
|
|
|
|
sub total_stats { |
994
|
2
|
|
|
2
|
0
|
24
|
my ($opt, $stats) = @_; |
995
|
2
|
|
|
|
|
25
|
my $benchmarks = benchmark_list(); |
996
|
2
|
100
|
|
|
|
25
|
my $display = $opt->{time} ? 'times' : 'scores'; |
997
|
2
|
100
|
|
|
|
34
|
my $title = $opt->{time} ? 'Time (sec)' : 'Score'; |
998
|
2
|
|
|
|
|
23
|
print "Aggregates:\n".pad_to("Benchmark",24).pad_to("Avg $title").pad_to("Min $title").pad_to("Max $title"); |
999
|
2
|
100
|
|
|
|
34
|
print pad_to("Pass %") unless $opt->{time}; |
1000
|
2
|
|
|
|
|
62
|
print "\n"; |
1001
|
2
|
|
|
|
|
76
|
foreach my $bench (sort keys %$benchmarks) { |
1002
|
42
|
100
|
|
|
|
195
|
next unless $stats->{$bench}->{$display}; |
1003
|
2
|
|
|
|
|
33
|
my $str = calc_stats($opt, $stats->{$bench}->{$display}); |
1004
|
2
|
|
|
|
|
27
|
print pad_to("$bench:",24).$str; |
1005
|
|
|
|
|
|
|
print pad_to( |
1006
|
|
|
|
|
|
|
sprintf("%d", 100 * ($opt->{iter}-($stats->{$bench}->{fail} || 0)) / $opt->{iter})) |
1007
|
2
|
100
|
50
|
|
|
61
|
unless $opt->{time}; |
1008
|
2
|
|
|
|
|
42
|
print "\n"; |
1009
|
|
|
|
|
|
|
} |
1010
|
2
|
|
|
|
|
44
|
my $str = calc_stats($opt, $stats->{total}->{$display}); |
1011
|
2
|
|
|
|
|
34
|
print pad_to("Overall Avg $title:", 24)."$str\n"; |
1012
|
|
|
|
|
|
|
} |
1013
|
|
|
|
|
|
|
|
1014
|
|
|
|
|
|
|
sub calc_stats { |
1015
|
4
|
|
|
4
|
0
|
31
|
my $opt = shift; |
1016
|
4
|
|
|
|
|
10
|
my $arr = shift; |
1017
|
4
|
|
|
|
|
19
|
my $pad = shift; |
1018
|
4
|
|
|
|
|
40
|
my ($min, $max, $avg) = min_max_avg($arr); |
1019
|
4
|
|
|
|
|
26
|
return $avg, join '', map {pad_to(sprintf($opt->{f}, $_), $pad)} ($avg,$min,$max); |
|
12
|
|
|
|
|
110
|
|
1020
|
|
|
|
|
|
|
} |
1021
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
sub min_max_avg { |
1023
|
24
|
|
|
24
|
0
|
74
|
my $arr = shift; |
1024
|
24
|
100
|
|
|
|
102
|
return (0, 0, 0) unless @$arr; |
1025
|
23
|
|
|
|
|
229
|
return min(@$arr), max(@$arr), sum(@$arr)/scalar(@$arr); |
1026
|
|
|
|
|
|
|
} |
1027
|
|
|
|
|
|
|
|
1028
|
|
|
|
|
|
|
sub avg_stdev { |
1029
|
8
|
|
|
8
|
0
|
28
|
my $arr = shift; |
1030
|
8
|
100
|
|
|
|
55
|
return (0, 0) unless @$arr; |
1031
|
7
|
|
|
|
|
46
|
my $sum = sum(@$arr); |
1032
|
7
|
|
|
|
|
36
|
my $avg = $sum/scalar(@$arr); |
1033
|
7
|
|
|
|
|
24
|
my @sq; |
1034
|
7
|
|
|
|
|
79
|
push @sq, ($avg - $_)**2 for (@$arr); |
1035
|
7
|
|
|
|
|
53
|
my $dev = min_max_avg(\@sq); |
1036
|
7
|
|
|
|
|
58
|
return $avg, sqrt($dev); |
1037
|
|
|
|
|
|
|
} |
1038
|
|
|
|
|
|
|
|
1039
|
|
|
|
|
|
|
# $single = single tail of dist curve outlier, 1 for over (right), -1 for under (left) |
1040
|
|
|
|
|
|
|
sub drop_outliers { |
1041
|
7
|
|
|
7
|
0
|
37
|
my $arr = shift; |
1042
|
7
|
|
|
|
|
29
|
my $single = shift; |
1043
|
7
|
|
|
|
|
58
|
my ($avg, $stdev) = avg_stdev($arr); |
1044
|
7
|
|
|
|
|
24
|
my @newarr; |
1045
|
7
|
|
|
|
|
32
|
foreach (@$arr) { |
1046
|
43
|
100
|
|
|
|
91
|
if ($single) { |
1047
|
30
|
100
|
|
|
|
103
|
push @newarr, $_ unless $single*($_ - $avg) > 2*$stdev; |
1048
|
|
|
|
|
|
|
} else { |
1049
|
13
|
100
|
|
|
|
33
|
push @newarr, $_ unless abs($avg - $_) > 2*$stdev; |
1050
|
|
|
|
|
|
|
} |
1051
|
|
|
|
|
|
|
} |
1052
|
7
|
|
|
|
|
57
|
return @newarr; |
1053
|
|
|
|
|
|
|
} |
1054
|
|
|
|
|
|
|
|
1055
|
|
|
|
|
|
|
sub pad_to { |
1056
|
115
|
|
|
115
|
0
|
353
|
my $str = shift; |
1057
|
115
|
|
100
|
|
|
599
|
my $len = shift || 20; |
1058
|
115
|
|
|
|
|
17015
|
return $str." "x($len-length($str)); |
1059
|
|
|
|
|
|
|
} |
1060
|
|
|
|
|
|
|
|
1061
|
|
|
|
|
|
|
sub _read_wiki_files { |
1062
|
4
|
|
100
|
4
|
|
65
|
my $enc = shift || ''; |
1063
|
4
|
|
|
|
|
16
|
my $str = ""; |
1064
|
4
|
|
|
|
|
28
|
for (0..2) { |
1065
|
12
|
50
|
|
|
|
1162
|
open my $fh, "<:$enc", catfile($datadir,"wiki$_.html") or die $!; |
1066
|
12
|
|
|
|
|
67
|
$str .= do { local $/; <$fh> }; |
|
12
|
|
|
|
|
85
|
|
|
12
|
|
|
|
|
35484
|
|
1067
|
|
|
|
|
|
|
} |
1068
|
4
|
|
|
|
|
46
|
return $str; |
1069
|
|
|
|
|
|
|
} |
1070
|
|
|
|
|
|
|
|
1071
|
|
|
|
|
|
|
sub _random_str { |
1072
|
5264
|
|
100
|
5264
|
|
17171
|
my $length = shift || 1; |
1073
|
5264
|
|
|
|
|
8263
|
my $abc = shift; |
1074
|
5264
|
100
|
|
|
|
15115
|
my ($base, $rng) = $abc ? (65, 26) : (32, 95); |
1075
|
5264
|
|
|
|
|
10912
|
my $str = ""; |
1076
|
5264
|
|
|
|
|
47476
|
$str .= chr(int(rand($rng))+$base) for 1..$length; |
1077
|
5264
|
|
|
|
|
38501
|
return $str; |
1078
|
|
|
|
|
|
|
} |
1079
|
|
|
|
|
|
|
|
1080
|
|
|
|
|
|
|
sub _random_uchar { |
1081
|
46303
|
|
|
46303
|
|
67000
|
my $chr = int(rand(800))+32; |
1082
|
46303
|
100
|
|
|
|
80372
|
$chr += 128 if $chr > 127; # Skip Latin 1 supplement |
1083
|
46303
|
100
|
|
|
|
74992
|
$chr += 288 if $chr > 591; # Skip pre-Greek blocks |
1084
|
46303
|
|
|
|
|
147404
|
return chr($chr); |
1085
|
|
|
|
|
|
|
} |
1086
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
sub _fuzzy_data { |
1088
|
1
|
|
|
1
|
|
10
|
my %data; |
1089
|
100
|
|
|
|
|
235
|
push @{$data{10}}, join('', map {_random_uchar()} 1..(8+int(rand(5)))) |
|
996
|
|
|
|
|
1359
|
|
1090
|
1
|
|
|
|
|
14
|
for 0..99; |
1091
|
1
|
|
|
|
|
9
|
push @{$data{100}}, $data{10}->[$_]x10 for 0..49; |
|
50
|
|
|
|
|
193
|
|
1092
|
1
|
|
|
|
|
11
|
push @{$data{1000}}, _random_str(50,1)x20 for 0..7; |
|
8
|
|
|
|
|
35
|
|
1093
|
1
|
|
|
|
|
6
|
push @{$data{2500}}, _random_str(50,1)x50 for 0..3; |
|
4
|
|
|
|
|
20
|
|
1094
|
1
|
|
|
|
|
22
|
return \%data; |
1095
|
|
|
|
|
|
|
} |
1096
|
|
|
|
|
|
|
|
1097
|
|
|
|
|
|
|
sub _rand_where { |
1098
|
16477
|
|
|
16477
|
|
25126
|
my $p = rand(); |
1099
|
16477
|
100
|
|
|
|
32924
|
if ($p > 0.5) { |
|
|
100
|
|
|
|
|
|
1100
|
8377
|
|
|
|
|
29919
|
return {foo => rand(10)}; |
1101
|
|
|
|
|
|
|
} elsif ($p > 0.2) { |
1102
|
4922
|
|
|
|
|
27709
|
return {bar => {-in => [int($p*10)..int($p*20)]}}; |
1103
|
|
|
|
|
|
|
} else { |
1104
|
3178
|
100
|
|
|
|
7011
|
my $op = $p > 0.1 ? '-and' : '-or'; |
1105
|
3178
|
|
|
|
|
6457
|
my @cond = map {_rand_where()} 1..int(rand(3)+1); |
|
6386
|
|
|
|
|
11837
|
|
1106
|
3178
|
|
|
|
|
12903
|
return {$op => [@cond]}; |
1107
|
|
|
|
|
|
|
} |
1108
|
|
|
|
|
|
|
} |
1109
|
|
|
|
|
|
|
|
1110
|
|
|
|
|
|
|
sub _db_data { |
1111
|
1
|
|
|
1
|
|
5
|
my (@data, @cols); |
1112
|
1
|
|
|
|
|
6
|
foreach (1..20) { |
1113
|
|
|
|
|
|
|
my $d = { |
1114
|
|
|
|
|
|
|
id => int(rand(10000000)), |
1115
|
|
|
|
|
|
|
date => \"NOW()", |
1116
|
20
|
|
|
|
|
68
|
map {"data".$_ => "foo bar" x int(rand(5)+1)} 1..int(rand(20)+1) |
|
202
|
|
|
|
|
756
|
|
1117
|
|
|
|
|
|
|
}; |
1118
|
20
|
|
|
|
|
70
|
push @data, $d; |
1119
|
20
|
|
|
|
|
183
|
push @cols, [sort keys %$d]; |
1120
|
|
|
|
|
|
|
} |
1121
|
1
|
|
|
|
|
14
|
return \@data, \@cols; |
1122
|
|
|
|
|
|
|
} |
1123
|
|
|
|
|
|
|
|
1124
|
|
|
|
|
|
|
sub compare_obj { |
1125
|
28702
|
|
|
28702
|
0
|
44815
|
my ($obj1, $obj2) = @_; |
1126
|
28702
|
|
|
|
|
39885
|
my $t1 = ref($obj1); |
1127
|
28702
|
|
|
|
|
37020
|
my $t2 = ref($obj2); |
1128
|
28702
|
100
|
|
|
|
48896
|
return 0 if $t1 ne $t2; |
1129
|
28701
|
100
|
|
|
|
78833
|
return $obj1 eq $obj2 unless $t1; |
1130
|
3496
|
100
|
|
|
|
8296
|
return $t1 eq 'ARRAY' ? compare_arr($obj1, $obj2) : compare_hash($obj1, $obj2); |
1131
|
|
|
|
|
|
|
} |
1132
|
|
|
|
|
|
|
|
1133
|
|
|
|
|
|
|
sub compare_arr { |
1134
|
1461
|
|
|
1461
|
0
|
2365
|
my ($arr1, $arr2) = @_; |
1135
|
1461
|
|
|
|
|
2173
|
my $sz = scalar @$arr1; |
1136
|
1461
|
100
|
|
|
|
2678
|
return 0 if $sz != scalar @$arr2; |
1137
|
1460
|
|
|
|
|
2994
|
for (0..$sz-1) { |
1138
|
8156
|
100
|
|
|
|
13392
|
return 0 unless compare_obj($arr1->[$_], $arr2->[$_]); |
1139
|
|
|
|
|
|
|
} |
1140
|
1459
|
|
|
|
|
3435
|
return 1; |
1141
|
|
|
|
|
|
|
} |
1142
|
|
|
|
|
|
|
|
1143
|
|
|
|
|
|
|
sub compare_hash { |
1144
|
2039
|
|
|
2039
|
0
|
3889
|
my ($h1, $h2) = @_; |
1145
|
2039
|
100
|
|
|
|
5697
|
return 0 if scalar keys %$h1 != scalar keys %$h2; |
1146
|
2038
|
|
|
|
|
7968
|
for (keys %$h1) { |
1147
|
19945
|
100
|
|
|
|
34440
|
return 0 unless compare_obj($h1->{$_}, $h2->{$_}); |
1148
|
|
|
|
|
|
|
} |
1149
|
2037
|
|
|
|
|
13692
|
return 1; |
1150
|
|
|
|
|
|
|
} |
1151
|
|
|
|
|
|
|
|
1152
|
|
|
|
|
|
|
sub rand_arr { |
1153
|
1468
|
|
|
1468
|
0
|
2162
|
my $sz = shift; |
1154
|
1468
|
|
|
|
|
2022
|
my @arr; |
1155
|
1468
|
|
|
|
|
2350
|
for (1..$sz) { |
1156
|
8203
|
|
|
|
|
12397
|
my $len = int(rand(10)) + 1; |
1157
|
8203
|
100
|
|
|
|
15610
|
my $item = rand(1) < 0.9 ? _random_uchar()x($len*5) : rand(1) < 0.5 ? rand_arr($len) : rand_hash($len); |
|
|
100
|
|
|
|
|
|
1158
|
8203
|
|
|
|
|
15506
|
push @arr, $item; |
1159
|
|
|
|
|
|
|
} |
1160
|
1468
|
|
|
|
|
2545
|
return \@arr; |
1161
|
|
|
|
|
|
|
} |
1162
|
|
|
|
|
|
|
|
1163
|
|
|
|
|
|
|
sub rand_hash { |
1164
|
2044
|
|
|
2044
|
0
|
3089
|
my $sz = shift; |
1165
|
2044
|
|
|
|
|
2863
|
my %hash; |
1166
|
2044
|
|
|
|
|
3480
|
for (1..$sz) { |
1167
|
20008
|
|
|
|
|
31622
|
my $len = int(rand(10)) + 1; |
1168
|
20008
|
100
|
|
|
|
37757
|
my $item = rand(1) < 0.9 ? _random_uchar()x($len*5) : rand(1) < 0.5 ? rand_arr($len) : rand_hash($len); |
|
|
100
|
|
|
|
|
|
1169
|
20008
|
|
|
|
|
32615
|
$hash{_random_uchar()x($len*4)} = $item; |
1170
|
|
|
|
|
|
|
} |
1171
|
2044
|
|
|
|
|
4107
|
return \%hash; |
1172
|
|
|
|
|
|
|
} |
1173
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
# modified from https://github.com/famzah/langs-performance/blob/master/primes.pl |
1175
|
|
|
|
|
|
|
sub _get_primes { |
1176
|
2
|
|
|
2
|
|
36
|
my $n = shift; |
1177
|
2
|
|
|
|
|
23
|
my @s = (); |
1178
|
2
|
|
|
|
|
106
|
for (my $i = 3; $i < $n + 1; $i += 2) { |
1179
|
7499998
|
|
|
|
|
12978976
|
push(@s, $i); |
1180
|
|
|
|
|
|
|
} |
1181
|
2
|
|
|
|
|
44
|
my $mroot = $n**0.5; |
1182
|
2
|
|
|
|
|
26
|
my $half = scalar @s; |
1183
|
2
|
|
|
|
|
16
|
my $i = 0; |
1184
|
2
|
|
|
|
|
9
|
my $m = 3; |
1185
|
2
|
|
|
|
|
16
|
while ($m <= $mroot) { |
1186
|
2736
|
100
|
|
|
|
5947
|
if ($s[$i]) { |
1187
|
796
|
|
|
|
|
2941
|
for (my $j = int(($m * $m - 3) / 2); $j < $half; $j += $m) { |
1188
|
13244400
|
|
|
|
|
25501247
|
$s[$j] = 0; |
1189
|
|
|
|
|
|
|
} |
1190
|
|
|
|
|
|
|
} |
1191
|
2736
|
|
|
|
|
4011
|
$i++; |
1192
|
2736
|
|
|
|
|
6131
|
$m = 2 * $i + 3; |
1193
|
|
|
|
|
|
|
} |
1194
|
|
|
|
|
|
|
|
1195
|
2
|
|
|
|
|
653045
|
return 2, grep($_, @s); |
1196
|
|
|
|
|
|
|
} |
1197
|
|
|
|
|
|
|
|
1198
|
|
|
|
|
|
|
# Fix for Crypt::JWT that was submitted as a patch. Will remove if it is merged. |
1199
|
|
|
|
|
|
|
sub _decode_jwt2 { |
1200
|
501
|
|
|
501
|
|
1892
|
my %args = @_; |
1201
|
501
|
|
|
|
|
949
|
my ($header, $payload); |
1202
|
|
|
|
|
|
|
|
1203
|
501
|
100
|
|
|
|
9783
|
if ($args{token} =~ |
1204
|
|
|
|
|
|
|
/^([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]*)=*\.([a-zA-Z0-9_-]*)=*(?:\.([a-zA-Z0-9_-]+)=*\.([a-zA-Z0-9_-]+)=*)?$/ |
1205
|
|
|
|
|
|
|
) { |
1206
|
500
|
50
|
|
|
|
1899
|
if (length($5)) { |
1207
|
|
|
|
|
|
|
# JWE token (5 segments) |
1208
|
0
|
|
|
|
|
0
|
($header, $payload) = |
1209
|
|
|
|
|
|
|
Crypt::JWT::_decode_jwe($1, $2, $3, $4, $5, undef, {}, {}, |
1210
|
|
|
|
|
|
|
%args); |
1211
|
|
|
|
|
|
|
} else { |
1212
|
|
|
|
|
|
|
# JWS token (3 segments) |
1213
|
500
|
|
|
|
|
2307
|
($header, $payload) = |
1214
|
|
|
|
|
|
|
Crypt::JWT::_decode_jws($1, $2, $3, {}, %args); |
1215
|
|
|
|
|
|
|
} |
1216
|
|
|
|
|
|
|
} |
1217
|
501
|
100
|
|
|
|
2053640
|
return ($header, $payload) if $args{decode_header}; |
1218
|
500
|
|
|
|
|
1834
|
return $payload; |
1219
|
|
|
|
|
|
|
} |
1220
|
|
|
|
|
|
|
|
1221
|
|
|
|
|
|
|
# Helper package for Moose benchmark |
1222
|
|
|
|
|
|
|
|
1223
|
|
|
|
|
|
|
{ |
1224
|
|
|
|
|
|
|
package Benchmark::DKbench::MooseTree; |
1225
|
|
|
|
|
|
|
|
1226
|
3
|
|
|
3
|
|
1938
|
use Moose; |
|
3
|
|
|
|
|
1375069
|
|
|
3
|
|
|
|
|
22
|
|
1227
|
|
|
|
|
|
|
|
1228
|
|
|
|
|
|
|
has 'price' => (is => 'rw', default => 10); |
1229
|
|
|
|
|
|
|
has 'tax' => (is => 'rw', lazy_build => 1); |
1230
|
|
|
|
|
|
|
has 'node' => (is => 'rw', isa => 'Any'); |
1231
|
|
|
|
|
|
|
has 'parent' => ( |
1232
|
|
|
|
|
|
|
is => 'rw', |
1233
|
|
|
|
|
|
|
isa => 'Benchmark::DKbench::MooseTree', |
1234
|
|
|
|
|
|
|
predicate => 'has_parent', |
1235
|
|
|
|
|
|
|
weak_ref => 1, |
1236
|
|
|
|
|
|
|
); |
1237
|
|
|
|
|
|
|
has 'left' => ( |
1238
|
|
|
|
|
|
|
is => 'rw', |
1239
|
|
|
|
|
|
|
isa => 'Benchmark::DKbench::MooseTree', |
1240
|
|
|
|
|
|
|
predicate => 'has_left', |
1241
|
|
|
|
|
|
|
lazy => 1, |
1242
|
|
|
|
|
|
|
builder => '_build_child_tree', |
1243
|
|
|
|
|
|
|
); |
1244
|
|
|
|
|
|
|
has 'right' => ( |
1245
|
|
|
|
|
|
|
is => 'rw', |
1246
|
|
|
|
|
|
|
isa => 'Benchmark::DKbench::MooseTree', |
1247
|
|
|
|
|
|
|
predicate => 'has_right', |
1248
|
|
|
|
|
|
|
lazy => 1, |
1249
|
|
|
|
|
|
|
builder => '_build_child_tree', |
1250
|
|
|
|
|
|
|
); |
1251
|
|
|
|
|
|
|
before 'right', 'left' => sub { |
1252
|
|
|
|
|
|
|
my ($self, $tree) = @_; |
1253
|
|
|
|
|
|
|
$tree->parent($self) if defined $tree; |
1254
|
|
|
|
|
|
|
}; |
1255
|
|
|
|
|
|
|
|
1256
|
|
|
|
|
|
|
sub _build_tax { |
1257
|
50000
|
|
|
50000
|
|
85740
|
my $self = shift; |
1258
|
50000
|
|
|
|
|
1384908
|
$self->price * 0.2; |
1259
|
|
|
|
|
|
|
} |
1260
|
|
|
|
|
|
|
|
1261
|
|
|
|
|
|
|
sub _build_child_tree { |
1262
|
40000
|
|
|
40000
|
|
64430
|
my $self = shift; |
1263
|
40000
|
|
|
|
|
120478
|
return Benchmark::DKbench::MooseTree->new( parent => $self ); |
1264
|
|
|
|
|
|
|
} |
1265
|
|
|
|
|
|
|
|
1266
|
|
|
|
|
|
|
sub cost { |
1267
|
40000
|
|
|
40000
|
0
|
69179
|
my $self = shift; |
1268
|
40000
|
|
|
|
|
1097852
|
$self->price + $self->tax; |
1269
|
|
|
|
|
|
|
} |
1270
|
|
|
|
|
|
|
} |
1271
|
|
|
|
|
|
|
|
1272
|
|
|
|
|
|
|
1; |