← Index
NYTProf Performance Profile   « line view »
For index.cgi
  Run on Sat May 9 17:18:47 2020
Reported on Sat May 9 17:19:07 2020

Filename/usr/local/share/perl/5.18.2/String/Markov.pm
StatementsExecuted 57171 statements in 95.4ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
3861132.3ms42.8msString::Markov::::add_sampleString::Markov::add_sample
27031127.1ms28.7msString::Markov::::split_probString::Markov::split_prob
21120.8ms49.5msString::Markov::::split_all_probString::Markov::split_all_prob
386113.96ms10.5msString::Markov::::split_lineString::Markov::split_line
1113.36ms4.50msString::Markov::::BEGIN@11String::Markov::BEGIN@11
2212.91ms96.9msString::Markov::::add_filesString::Markov::add_files
1112.38ms20.2msString::Markov::::BEGIN@8String::Markov::BEGIN@8
136111.71ms1.71msString::Markov::::sample_next_stateString::Markov::sample_next_state
388111.65ms1.65msString::Markov::::CORE:readlineString::Markov::CORE:readline (opcode)
2703111.58ms1.58msString::Markov::::CORE:sortString::Markov::CORE:sort (opcode)
1111.15ms14.9msString::Markov::::BEGIN@9String::Markov::BEGIN@9
721635µs2.35msString::Markov::::generate_sampleString::Markov::generate_sample
38611301µs301µsString::Markov::::CORE:regcompString::Markov::CORE:regcomp (opcode)
21144µs60µsString::Markov::::__ANON__[:45]String::Markov::__ANON__[:45]
11133µs33µsString::Markov::::BEGIN@7String::Markov::BEGIN@7
21116µs23µsString::Markov::::__ANON__[:20]String::Markov::__ANON__[:20]
11116µs91µsString::Markov::::BEGIN@12String::Markov::BEGIN@12
21114µs14µsString::Markov::::__ANON__[:14]String::Markov::__ANON__[:14]
11112µs12µsString::Markov::::do_chompString::Markov::do_chomp (xsub)
4217µs7µsString::Markov::::__ANON__[:29]String::Markov::__ANON__[:29]
2117µs7µsString::Markov::::CORE:matchString::Markov::CORE:match (opcode)
4216µs6µsString::Markov::::__ANON__[:30]String::Markov::__ANON__[:30]
2115µs5µsString::Markov::::__ANON__[:15]String::Markov::__ANON__[:15]
2115µs5µsString::Markov::::__ANON__[:16]String::Markov::__ANON__[:16]
4413µs3µsString::Markov::::join_sepString::Markov::join_sep (xsub)
2113µs3µsString::Markov::::__ANON__[:17]String::Markov::__ANON__[:17]
2213µs3µsString::Markov::::nullString::Markov::null (xsub)
3313µs3µsString::Markov::::orderString::Markov::order (xsub)
3313µs3µsString::Markov::::transition_countString::Markov::transition_count (xsub)
2212µs2µsString::Markov::::split_sepString::Markov::split_sep (xsub)
2212µs2µsString::Markov::::row_sumString::Markov::row_sum (xsub)
1111µs1µsString::Markov::::stableString::Markov::stable (xsub)
111700ns700nsString::Markov::::normalizeString::Markov::normalize (xsub)
0000s0sString::Markov::::__ANON__[:24]String::Markov::__ANON__[:24]
0000s0sString::Markov::::join_probString::Markov::join_prob
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package String::Markov;
2
3# ABSTRACT: A Moo-based, text-oriented Markov Chain module
4
51500nsour $VERSION = 0.009;
6
7278µs133µs
# spent 33µs within String::Markov::BEGIN@7 which was called: # once (33µs+0s) by main::BEGIN@7 at line 7
use 5.010;
# spent 33µs making 1 call to String::Markov::BEGIN@7
82115µs221.3ms
# spent 20.2ms (2.38+17.9) within String::Markov::BEGIN@8 which was called: # once (2.38ms+17.9ms) by main::BEGIN@7 at line 8
use Moo;
# spent 20.2ms making 1 call to String::Markov::BEGIN@8 # spent 1.08ms making 1 call to Moo::import
92118µs215.0ms
# spent 14.9ms (1.15+13.8) within String::Markov::BEGIN@9 which was called: # once (1.15ms+13.8ms) by main::BEGIN@7 at line 9
use namespace::autoclean;
# spent 14.9ms making 1 call to String::Markov::BEGIN@9 # spent 38µs making 1 call to namespace::autoclean::import
10
112196µs24.68ms
# spent 4.50ms (3.36+1.14) within String::Markov::BEGIN@11 which was called: # once (3.36ms+1.14ms) by main::BEGIN@7 at line 11
use Unicode::Normalize qw(normalize);
# spent 4.50ms making 1 call to String::Markov::BEGIN@11 # spent 185µs making 1 call to Exporter::import
1221.94ms2135µs
# spent 91µs (16+75) within String::Markov::BEGIN@12 which was called: # once (16µs+75µs) by main::BEGIN@7 at line 12
use List::Util qw(sum);
# spent 91µs making 1 call to String::Markov::BEGIN@12 # spent 44µs making 1 call to List::Util::import
13
14321µs122.5ms
# spent 14µs within String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:14] which was called 2 times, avg 7µs/call: # 2 times (14µs+0s) by String::Markov::new at line 111 of (eval 33)[Sub/Quote.pm:3], avg 7µs/call
has normalize => (is => 'rw', default => sub { 'C' });
# spent 22.5ms making 1 call to Moo::has
15313µs1208µs
# spent 5µs within String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:15] which was called 2 times, avg 3µs/call: # 2 times (5µs+0s) by String::Markov::new at line 111 of (eval 33)[Sub/Quote.pm:3], avg 3µs/call
has do_chomp => (is => 'rw', default => sub { 1 });
# spent 208µs making 1 call to Moo::has
16311µs1230µs
# spent 5µs within String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:16] which was called 2 times, avg 2µs/call: # 2 times (5µs+0s) by String::Markov::new at line 111 of (eval 33)[Sub/Quote.pm:3], avg 2µs/call
has null => (is => 'ro', default => sub { "\0" });
# spent 230µs making 1 call to Moo::has
17312µs1208µs
# spent 3µs within String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:17] which was called 2 times, avg 2µs/call: # 2 times (3µs+0s) by String::Markov::new at line 111 of (eval 33)[Sub/Quote.pm:3], avg 2µs/call
has stable => (is => 'ro', default => sub { 1 });
# spent 208µs making 1 call to Moo::has
18has order => (is => 'ro', isa => sub {
19225µs27µs die "Need an integer greater than zero" if !$_[0] || $_[0] =~ /\D/;
# spent 7µs making 2 calls to String::Markov::CORE:match, avg 4µs/call
2016µs1209µs
# spent 23µs (16+7) within String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:20] which was called 2 times, avg 12µs/call: # 2 times (16µs+7µs) by String::Markov::new at line 71 of (eval 33)[Sub/Quote.pm:3], avg 12µs/call
}, default => sub { 2 });
# spent 209µs making 1 call to Moo::has
21
22has ['split_sep','join_sep'] => (
23 is => 'rw',
24 default => sub { undef }
25110µs1384µs);
# spent 384µs making 1 call to Moo::has
26
27has ['transition_count','row_sum'] => (
28 is => 'ro',
29413µs
# spent 7µs within String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:29] which was called 4 times, avg 2µs/call: # 2 times (5µs+0s) by String::Markov::new at line 94 of (eval 33)[Sub/Quote.pm:3], avg 3µs/call # 2 times (2µs+0s) by String::Markov::new at line 123 of (eval 33)[Sub/Quote.pm:3], avg 1µs/call
isa => sub { die "Need a hash ref" if ref $_[0] ne 'HASH'; },
30412µs
# spent 6µs within String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:30] which was called 4 times, avg 1µs/call: # 2 times (4µs+0s) by String::Markov::new at line 82 of (eval 33)[Sub/Quote.pm:3], avg 2µs/call # 2 times (2µs+0s) by String::Markov::new at line 111 of (eval 33)[Sub/Quote.pm:3], avg 1µs/call
default => sub { {} }
3117µs1425µs);
# spent 425µs making 1 call to Moo::has
32
33
# spent 60µs (44+15) within String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:45] which was called 2 times, avg 30µs/call: # 2 times (44µs+15µs) by String::Markov::__ANON__[(eval 16)[/usr/local/share/perl/5.18.2/Class/Method/Modifiers.pm:93]:1] at line 1 of (eval 16)[Class/Method/Modifiers.pm:93], avg 30µs/call
around BUILDARGS => sub {
3425µs my ($orig, $class, @arg) = @_;
3521µs my %ahash;
36
3727µs %ahash = @arg == 1 ? %{$arg[0]} : @arg;
38
3924µs my $sep = delete $ahash{sep} // '';
4021µs die "ERR: sep argument must be scalar; did you mean to set split_sep instead?" if ref $sep;
4123µs $ahash{split_sep} //= $sep;
4222µs $ahash{join_sep} //= $sep;
43
44216µs216µs return $class->$orig(\%ahash);
# spent 16µs making 2 calls to Moo::Object::BUILDARGS, avg 8µs/call
4516µs12.17ms};
# spent 2.17ms making 1 call to Moo::around
46
47sub join_prob {
48 my ($self, $orig_prob) = @_;
49 my %p;
50
51 @p{@{$orig_prob->[0]}} = @{$orig_prob->[1]};
52
53 return \%p;
54}
55
56
# spent 28.7ms (27.1+1.58) within String::Markov::split_prob which was called 2703 times, avg 11µs/call: # 2703 times (27.1ms+1.58ms) by String::Markov::split_all_prob at line 78, avg 11µs/call
sub split_prob {
572703794µs my ($self, $orig_prob) = @_;
58
5927031.13ms11µs if ($self->stable) {
# spent 1µs making 1 call to String::Markov::stable
60270318.7ms27031.58ms my @k = sort keys %$orig_prob;
# spent 1.58ms making 2703 calls to String::Markov::CORE:sort, avg 585ns/call
61 return [
62 \@k,
63270317.0ms [@{$orig_prob}{@k}],
64 ];
65 } else {
66 return [
67 [keys %$orig_prob],
68 [values %$orig_prob],
69 ];
70 }
71}
72
73
# spent 49.5ms (20.8+28.7) within String::Markov::split_all_prob which was called 2 times, avg 24.7ms/call: # 2 times (20.8ms+28.7ms) by String::Markov::add_files at line 139, avg 24.7ms/call
sub split_all_prob {
7422µs my $self = shift;
7528µs11µs my $tc = $self->transition_count;
# spent 1µs making 1 call to String::Markov::transition_count
7622µs my $nt = {};
77
7828.33ms270328.7ms while (my ($state, $prob) = each %$tc) {
# spent 28.7ms making 2703 calls to String::Markov::split_prob, avg 11µs/call
79 $nt->{$state} = $self->split_prob($prob);
80 }
81
8223.56ms %$tc = %$nt;
83}
84
85
# spent 10.5ms (3.96+6.57) within String::Markov::split_line which was called 386 times, avg 27µs/call: # 386 times (3.96ms+6.57ms) by String::Markov::add_sample at line 105, avg 27µs/call
sub split_line {
86386211µs my ($self, $sample) = @_;
87386823µs3876.27ms if (my $norm = $self->normalize) {
# spent 6.27ms making 386 calls to Unicode::Normalize::normalize, avg 16µs/call # spent 700ns making 1 call to String::Markov::normalize
88 $sample = normalize($norm, $sample);
89 }
903863.42ms387302µs return split($self->split_sep, $sample);
# spent 301µs making 386 calls to String::Markov::CORE:regcomp, avg 779ns/call # spent 900ns making 1 call to String::Markov::split_sep
91}
92
93
# spent 42.8ms (32.3+10.5) within String::Markov::add_sample which was called 386 times, avg 111µs/call: # 386 times (32.3ms+10.5ms) by String::Markov::add_files at line 136, avg 111µs/call
sub add_sample {
94386237µs my ($self, $sample) = @_;
95386292µs11µs my $n = $self->order;
# spent 1µs making 1 call to String::Markov::order
96386194µs1700ns my $null = $self->null;
# spent 700ns making 1 call to String::Markov::null
97
98386130µs my $sref = ref $sample;
99386347µs my @nms = ($null,) x $n;
100
101386423µs if ($sref eq 'ARRAY') {
102 push @nms, @$sample;
103 } elsif (!$sref) {
104386219µs11µs die 'ERR: missing split separator,' if !defined $self->split_sep;
# spent 1µs making 1 call to String::Markov::split_sep
1053861.06ms38610.5ms push @nms, $self->split_line($sample);
# spent 10.5ms making 386 calls to String::Markov::split_line, avg 27µs/call
106 } else {
107 die "ERR: bad sample type $sref";
108 }
109
110386225µs push @nms, $null;
111
112386281µs11µs my $sep = $self->join_sep // '';
# spent 1µs making 1 call to String::Markov::join_sep
113386180µs1800ns my $count = $self->transition_count;
# spent 800ns making 1 call to String::Markov::transition_count
114386166µs1900ns my $sum = $self->row_sum;
# spent 900ns making 1 call to String::Markov::row_sum
115386642µs for my $i (0 .. ($#nms - $n)) {
11661425.87ms my $cur = join($sep, @nms[$i .. ($i + $n - 1)]);
11761422.20ms my $nxt = $nms[$i + $n];
11861423.28ms my $prob = $count->{$cur};
11961421.92ms if ($prob && ref $prob ne 'HASH') {
120 $count->{$cur} = $self->join_prob($prob);
121 }
12261427.78ms ++$count->{$cur}{$nxt};
12361425.38ms ++$sum->{$cur};
124 }
125
1263861.65ms return $self;
127}
128
129
# spent 96.9ms (2.91+94.0) within String::Markov::add_files which was called 2 times, avg 48.4ms/call: # once (1.96ms+51.3ms) by main::RUNTIME at line 18 of index.cgi # once (950µs+42.6ms) by main::RUNTIME at line 43 of index.cgi
sub add_files {
13023µs my ($self, @files) = @_;
131220µs112µs my $do_chomp = $self->do_chomp;
# spent 12µs making 1 call to String::Markov::do_chomp
132
13324µs local @ARGV = @files;
13422.66ms3881.65ms while(my $sample = <>) {
# spent 1.65ms making 388 calls to String::Markov::CORE:readline, avg 4µs/call
135386186µs chomp $sample if $do_chomp;
136386750µs38642.8ms $self->add_sample($sample);
# spent 42.8ms making 386 calls to String::Markov::add_sample, avg 111µs/call
137 }
138
1392283µs249.5ms $self->split_all_prob();
# spent 49.5ms making 2 calls to String::Markov::split_all_prob, avg 24.7ms/call
140
141219µs return $self;
142}
143
144
# spent 1.71ms (1.71+3µs) within String::Markov::sample_next_state which was called 136 times, avg 13µs/call: # 136 times (1.71ms+3µs) by String::Markov::generate_sample at line 180, avg 13µs/call
sub sample_next_state {
14513697µs my ($self, @cur_state) = @_;
14613680µs1600ns die "ERR: wrong amount of state" if @cur_state != $self->order;
# spent 600ns making 1 call to String::Markov::order
147
14813654µs1800ns my $count = $self->transition_count;
# spent 800ns making 1 call to String::Markov::transition_count
14913643µs1800ns my $sum = $self->row_sum;
# spent 800ns making 1 call to String::Markov::row_sum
150
151136108µs1600ns my $cur = join($self->join_sep // '', @cur_state);
# spent 600ns making 1 call to String::Markov::join_sep
152136115µs my $thresh = $sum->{$cur};
15313625µs return undef if !$thresh;
154
155136121µs $thresh *= rand();
156
15713665µs my $prob = $count->{$cur};
15813650µs if (ref $prob ne 'ARRAY') {
159 $prob = $self->split_prob($prob);
160 $count->{$cur} = $prob;
161 }
162
16313626µs my $s = 0;
16413622µs my $i = 0;
16513678µs my ($k, $v) = @{$prob};
166136594µs do {
167 $s += $v->[$i];
168 } while ($thresh > $s && ++$i);
169136403µs return $k->[$i];
170}
171
172
# spent 2.35ms (635µs+1.72) within String::Markov::generate_sample which was called 7 times, avg 336µs/call: # 6 times (580µs+1.55ms) by main::RUNTIME at line 46 of index.cgi, avg 355µs/call # once (54µs+167µs) by main::RUNTIME at line 19 of index.cgi
sub generate_sample {
17374µs my ($self) = @_;
174
175713µs12µs my $null = $self->null;
# spent 2µs making 1 call to String::Markov::null
176710µs1800ns my $n = $self->order;
# spent 800ns making 1 call to String::Markov::order
177710µs11µs my $sep = $self->join_sep // '';
# spent 1µs making 1 call to String::Markov::join_sep
17879µs my @nm = ($null,) x $n;
179
1807317µs1361.71ms do {
# spent 1.71ms making 136 calls to String::Markov::sample_next_state, avg 13µs/call
181 push @nm, $self->sample_next_state(@nm[-$n .. -1]);
182 } while ($nm[-1] ne $null);
183
184763µs @nm = @nm[$n .. ($#nm-1)];
185
186 return wantarray ?
187752µs1800ns @nm :
# spent 800ns making 1 call to String::Markov::join_sep
188 defined $self->join_sep ?
189 join($sep, @nm) :
190 \@nm;
191
192}
193
194110µs2440µs__PACKAGE__->meta->make_immutable;
# spent 438µs making 1 call to Moo::Object::meta # spent 2µs making 1 call to Moo::HandleMoose::FakeMetaClass::make_immutable
195
196115µs1;
197
198132µs12.39ms__END__
 
# spent 7µs within String::Markov::CORE:match which was called 2 times, avg 4µs/call: # 2 times (7µs+0s) by String::Markov::__ANON__[/usr/local/share/perl/5.18.2/String/Markov.pm:20] at line 19, avg 4µs/call
sub String::Markov::CORE:match; # opcode
# spent 1.65ms within String::Markov::CORE:readline which was called 388 times, avg 4µs/call: # 388 times (1.65ms+0s) by String::Markov::add_files at line 134, avg 4µs/call
sub String::Markov::CORE:readline; # opcode
# spent 301µs within String::Markov::CORE:regcomp which was called 386 times, avg 779ns/call: # 386 times (301µs+0s) by String::Markov::split_line at line 90, avg 779ns/call
sub String::Markov::CORE:regcomp; # opcode
# spent 1.58ms within String::Markov::CORE:sort which was called 2703 times, avg 585ns/call: # 2703 times (1.58ms+0s) by String::Markov::split_prob at line 60, avg 585ns/call
sub String::Markov::CORE:sort; # opcode
# spent 12µs within String::Markov::do_chomp which was called: # once (12µs+0s) by String::Markov::add_files at line 131
sub String::Markov::do_chomp; # xsub
# spent 3µs within String::Markov::join_sep which was called 4 times, avg 875ns/call: # once (1µs+0s) by String::Markov::generate_sample at line 177 # once (1µs+0s) by String::Markov::add_sample at line 112 # once (800ns+0s) by String::Markov::generate_sample at line 187 # once (600ns+0s) by String::Markov::sample_next_state at line 151
sub String::Markov::join_sep; # xsub
# spent 700ns within String::Markov::normalize which was called: # once (700ns+0s) by String::Markov::split_line at line 87
sub String::Markov::normalize; # xsub
# spent 3µs within String::Markov::null which was called 2 times, avg 1µs/call: # once (2µs+0s) by String::Markov::generate_sample at line 175 # once (700ns+0s) by String::Markov::add_sample at line 96
sub String::Markov::null; # xsub
# spent 3µs within String::Markov::order which was called 3 times, avg 867ns/call: # once (1µs+0s) by String::Markov::add_sample at line 95 # once (800ns+0s) by String::Markov::generate_sample at line 176 # once (600ns+0s) by String::Markov::sample_next_state at line 146
sub String::Markov::order; # xsub
# spent 2µs within String::Markov::row_sum which was called 2 times, avg 850ns/call: # once (900ns+0s) by String::Markov::add_sample at line 114 # once (800ns+0s) by String::Markov::sample_next_state at line 149
sub String::Markov::row_sum; # xsub
# spent 2µs within String::Markov::split_sep which was called 2 times, avg 950ns/call: # once (1µs+0s) by String::Markov::add_sample at line 104 # once (900ns+0s) by String::Markov::split_line at line 90
sub String::Markov::split_sep; # xsub
# spent 1µs within String::Markov::stable which was called: # once (1µs+0s) by String::Markov::split_prob at line 59
sub String::Markov::stable; # xsub
# spent 3µs within String::Markov::transition_count which was called 3 times, avg 867ns/call: # once (1µs+0s) by String::Markov::split_all_prob at line 75 # once (800ns+0s) by String::Markov::add_sample at line 113 # once (800ns+0s) by String::Markov::sample_next_state at line 148
sub String::Markov::transition_count; # xsub