| Filename | /home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm |
| Statements | Executed 300132 statements in 1.28s |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 30000 | 1 | 1 | 1.12s | 132s | Hailo::reply |
| 30002 | 3 | 1 | 64.0ms | 117ms | Hailo::_storage (xsub) |
| 30000 | 1 | 1 | 46.3ms | 94.2ms | Hailo::_tokenizer (xsub) |
| 30000 | 1 | 1 | 45.8ms | 63.0ms | Hailo::_engine (xsub) |
| 3 | 1 | 1 | 5.67ms | 117ms | Hailo::_new_class |
| 1 | 1 | 1 | 2.24ms | 20.4ms | Hailo::BEGIN@11 |
| 1 | 1 | 1 | 937µs | 20.3ms | Hailo::BEGIN@15 |
| 1 | 1 | 1 | 435µs | 20.9ms | Hailo::BEGIN@10 |
| 1 | 1 | 1 | 259µs | 279µs | Hailo::BEGIN@184 |
| 3 | 3 | 1 | 166µs | 117ms | Hailo::__ANON__[:176] |
| 13 | 1 | 1 | 58µs | 58µs | Hailo::CORE:regcomp (opcode) |
| 16 | 2 | 1 | 42µs | 42µs | Hailo::CORE:match (opcode) |
| 1 | 1 | 1 | 37µs | 107µs | Hailo::BEGIN@9 |
| 1 | 1 | 1 | 26µs | 3.92s | Hailo::DEMOLISH |
| 3 | 1 | 1 | 19µs | 19µs | Hailo::CORE:sort (opcode) |
| 1 | 1 | 1 | 18µs | 3.92s | Hailo::save |
| 1 | 1 | 1 | 18µs | 18µs | Hailo::BEGIN@2 |
| 1 | 1 | 1 | 15µs | 101µs | Hailo::BEGIN@14 |
| 1 | 1 | 1 | 14µs | 92µs | Hailo::BEGIN@17 |
| 3 | 1 | 1 | 11µs | 11µs | Hailo::__ANON__[:117] |
| 1 | 1 | 1 | 11µs | 36µs | Hailo::BEGIN@129 |
| 1 | 1 | 1 | 11µs | 64µs | Hailo::BEGIN@13 |
| 1 | 1 | 1 | 11µs | 70µs | Hailo::BEGIN@9.2 |
| 3 | 2 | 1 | 10µs | 12µs | Hailo::brain (xsub) |
| 1 | 1 | 1 | 10µs | 768µs | Hailo::BEGIN@12 |
| 1 | 1 | 1 | 10µs | 18µs | Hailo::__ANON__[:71] |
| 3 | 1 | 1 | 5µs | 5µs | Hailo::PLUGINS (xsub) |
| 1 | 1 | 1 | 5µs | 5µs | Hailo::BEGIN@5 |
| 2 | 1 | 1 | 4µs | 4µs | Hailo::tokenizer_class (xsub) |
| 2 | 1 | 1 | 3µs | 3µs | Hailo::order (xsub) |
| 1 | 1 | 1 | 2µs | 2µs | Hailo::engine_class (xsub) |
| 1 | 1 | 1 | 2µs | 2µs | Hailo::engine_args (xsub) |
| 1 | 1 | 1 | 2µs | 2µs | Hailo::save_on_exit (xsub) |
| 1 | 1 | 1 | 2µs | 2µs | Hailo::storage_class (xsub) |
| 1 | 1 | 1 | 2µs | 2µs | Hailo::tokenizer_args (xsub) |
| 1 | 1 | 1 | 1µs | 1µs | Hailo::storage_args (xsub) |
| 0 | 0 | 0 | 0s | 0s | Hailo::__ANON__[:108] |
| 0 | 0 | 0 | 0s | 0s | Hailo::__ANON__[:151] |
| 0 | 0 | 0 | 0s | 0s | Hailo::__ANON__[:152] |
| 0 | 0 | 0 | 0s | 0s | Hailo::__ANON__[:157] |
| 0 | 0 | 0 | 0s | 0s | Hailo::__ANON__[:161] |
| 0 | 0 | 0 | 0s | 0s | Hailo::__ANON__[:188] |
| 0 | 0 | 0 | 0s | 0s | Hailo::__ANON__[:39] |
| 0 | 0 | 0 | 0s | 0s | Hailo::_is_interactive |
| 0 | 0 | 0 | 0s | 0s | Hailo::_learn_one |
| 0 | 0 | 0 | 0s | 0s | Hailo::_train_fh |
| 0 | 0 | 0 | 0s | 0s | Hailo::learn |
| 0 | 0 | 0 | 0s | 0s | Hailo::learn_reply |
| 0 | 0 | 0 | 0s | 0s | Hailo::stats |
| 0 | 0 | 0 | 0s | 0s | Hailo::train |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Hailo; | ||||
| 2 | # spent 18µs within Hailo::BEGIN@2 which was called:
# once (18µs+0s) by main::BEGIN@6 at line 4 | ||||
| 3 | 1 | 6µs | $Hailo::AUTHORITY = 'cpan:AVAR'; | ||
| 4 | 1 | 24µs | 1 | 18µs | } # spent 18µs making 1 call to Hailo::BEGIN@2 |
| 5 | # spent 5µs within Hailo::BEGIN@5 which was called:
# once (5µs+0s) by main::BEGIN@6 at line 7 | ||||
| 6 | 1 | 9µs | $Hailo::VERSION = '0.57'; | ||
| 7 | 1 | 16µs | 1 | 5µs | } # spent 5µs making 1 call to Hailo::BEGIN@5 |
| 8 | |||||
| 9 | 4 | 65µs | 3 | 235µs | use 5.010; # spent 107µs making 1 call to Hailo::BEGIN@9
# spent 70µs making 1 call to Hailo::BEGIN@9.2
# spent 59µs making 1 call to feature::import |
| 10 | 2 | 165µs | 2 | 20.9ms | # spent 20.9ms (435µs+20.4) within Hailo::BEGIN@10 which was called:
# once (435µs+20.4ms) by main::BEGIN@6 at line 10 # spent 20.9ms making 1 call to Hailo::BEGIN@10
# spent 7µs making 1 call to autodie::import |
| 11 | 2 | 216µs | 2 | 21.1ms | # spent 20.4ms (2.24+18.1) within Hailo::BEGIN@11 which was called:
# once (2.24ms+18.1ms) by main::BEGIN@6 at line 11 # spent 20.4ms making 1 call to Hailo::BEGIN@11
# spent 725µs making 1 call to Any::Moose::import |
| 12 | 2 | 28µs | 2 | 1.53ms | # spent 768µs (10+759) within Hailo::BEGIN@12 which was called:
# once (10µs+759µs) by main::BEGIN@6 at line 12 # spent 768µs making 1 call to Hailo::BEGIN@12
# spent 759µs making 1 call to Any::Moose::import |
| 13 | 2 | 28µs | 2 | 116µs | # spent 64µs (11+53) within Hailo::BEGIN@13 which was called:
# once (11µs+53µs) by main::BEGIN@6 at line 13 # spent 64µs making 1 call to Hailo::BEGIN@13
# spent 53µs making 1 call to Exporter::import |
| 14 | 2 | 33µs | 2 | 186µs | # spent 101µs (15+85) within Hailo::BEGIN@14 which was called:
# once (15µs+85µs) by main::BEGIN@6 at line 14 # spent 101µs making 1 call to Hailo::BEGIN@14
# spent 85µs making 1 call to Exporter::import |
| 15 | 2 | 169µs | 2 | 21.8ms | # spent 20.3ms (937µs+19.4) within Hailo::BEGIN@15 which was called:
# once (937µs+19.4ms) by main::BEGIN@6 at line 15 # spent 20.3ms making 1 call to Hailo::BEGIN@15
# spent 1.55ms making 1 call to namespace::clean::import |
| 16 | |||||
| 17 | 1 | 10µs | 1 | 78µs | # spent 92µs (14+78) within Hailo::BEGIN@17 which was called:
# once (14µs+78µs) by main::BEGIN@6 at line 25 # spent 78µs making 1 call to constant::import |
| 18 | Hailo::Engine::Default | ||||
| 19 | Hailo::Storage::MySQL | ||||
| 20 | Hailo::Storage::PostgreSQL | ||||
| 21 | Hailo::Storage::SQLite | ||||
| 22 | Hailo::Tokenizer::Chars | ||||
| 23 | Hailo::Tokenizer::Words | ||||
| 24 | Hailo::UI::ReadLine | ||||
| 25 | 1 | 342µs | 1 | 92µs | ] ]; # spent 92µs making 1 call to Hailo::BEGIN@17 |
| 26 | |||||
| 27 | 1 | 5µs | 1 | 431µs | has brain => ( # spent 431µs making 1 call to Mouse::has |
| 28 | isa => 'Str', | ||||
| 29 | is => 'rw', | ||||
| 30 | ); | ||||
| 31 | |||||
| 32 | has order => ( | ||||
| 33 | isa => 'Int', | ||||
| 34 | is => 'rw', | ||||
| 35 | default => 2, | ||||
| 36 | trigger => sub { | ||||
| 37 | my ($self, $order) = @_; | ||||
| 38 | $self->_custom_order(1); | ||||
| 39 | }, | ||||
| 40 | 1 | 6µs | 1 | 276µs | ); # spent 276µs making 1 call to Mouse::has |
| 41 | |||||
| 42 | 1 | 4µs | 1 | 262µs | has _custom_order => ( # spent 262µs making 1 call to Mouse::has |
| 43 | isa => 'Bool', | ||||
| 44 | is => 'rw', | ||||
| 45 | default => 0, | ||||
| 46 | init_arg => undef, | ||||
| 47 | documentation => "Here so we can differentiate between the default value of order being explictly set and being set by default", | ||||
| 48 | ); | ||||
| 49 | |||||
| 50 | 1 | 4µs | 1 | 286µs | has _custom_tokenizer_class => ( # spent 286µs making 1 call to Mouse::has |
| 51 | isa => 'Bool', | ||||
| 52 | is => 'rw', | ||||
| 53 | default => 0, | ||||
| 54 | init_arg => undef, | ||||
| 55 | documentation => "Here so we can differentiate between the default value of tokenizer_class being explictly set and being set by default", | ||||
| 56 | ); | ||||
| 57 | |||||
| 58 | 1 | 4µs | 1 | 262µs | has save_on_exit => ( # spent 262µs making 1 call to Mouse::has |
| 59 | isa => 'Bool', | ||||
| 60 | is => 'rw', | ||||
| 61 | default => 1, | ||||
| 62 | ); | ||||
| 63 | |||||
| 64 | has brain_resource => ( | ||||
| 65 | documentation => "Alias for `brain' for backwards compatibility", | ||||
| 66 | isa => 'Str', | ||||
| 67 | is => 'rw', | ||||
| 68 | # spent 18µs (10+8) within Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:71] which was called:
# once (10µs+8µs) by Mouse::Object::new at line 9 of reply.pl | ||||
| 69 | 1 | 2µs | my ($self, $brain) = @_; | ||
| 70 | 1 | 18µs | 2 | 10µs | $self->brain($brain); # spent 8µs making 1 call to Hailo::brain
# spent 2µs making 1 call to Mouse::Meta::TypeConstraint::_compiled_type_constraint |
| 71 | }, | ||||
| 72 | 1 | 5µs | 1 | 266µs | ); # spent 266µs making 1 call to Mouse::has |
| 73 | |||||
| 74 | 1 | 5µs | my %has = ( | ||
| 75 | engine => { | ||||
| 76 | name => 'Engine', | ||||
| 77 | default => 'Default', | ||||
| 78 | }, | ||||
| 79 | storage => { | ||||
| 80 | name => 'Storage', | ||||
| 81 | default => 'SQLite', | ||||
| 82 | }, | ||||
| 83 | tokenizer => { | ||||
| 84 | name => 'Tokenizer', | ||||
| 85 | default => 'Words', | ||||
| 86 | }, | ||||
| 87 | ui => { | ||||
| 88 | name => 'UI', | ||||
| 89 | default => 'ReadLine', | ||||
| 90 | }, | ||||
| 91 | ); | ||||
| 92 | |||||
| 93 | 1 | 3µs | for my $k (keys %has) { | ||
| 94 | 4 | 7µs | my $name = $has{$k}->{name}; | ||
| 95 | 4 | 5µs | my $default = $has{$k}->{default}; | ||
| 96 | 4 | 5µs | my $method_class = "${k}_class"; | ||
| 97 | 4 | 4µs | my $method_args = "${k}_args"; | ||
| 98 | |||||
| 99 | # working classes | ||||
| 100 | has "${k}_class" => ( | ||||
| 101 | isa => 'Str', | ||||
| 102 | is => "rw", | ||||
| 103 | default => $default, | ||||
| 104 | ($k ~~ 'tokenizer' | ||||
| 105 | ? (trigger => sub { | ||||
| 106 | my ($self, $class) = @_; | ||||
| 107 | $self->_custom_tokenizer_class(1); | ||||
| 108 | }) | ||||
| 109 | 4 | 23µs | 4 | 1.07ms | : ()) # spent 1.07ms making 4 calls to Mouse::has, avg 268µs/call |
| 110 | ); | ||||
| 111 | |||||
| 112 | # Object arguments | ||||
| 113 | has "${k}_args" => ( | ||||
| 114 | documentation => "Arguments for the $name class", | ||||
| 115 | isa => 'HashRef', | ||||
| 116 | is => "ro", | ||||
| 117 | 3 | 15µs | # spent 11µs within Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:117] which was called 3 times, avg 4µs/call:
# 3 times (11µs+0s) by Mouse::Object::new at line 9 of reply.pl, avg 4µs/call | ||
| 118 | 4 | 28µs | 4 | 1.08ms | ); # spent 1.08ms making 4 calls to Mouse::has, avg 269µs/call |
| 119 | |||||
| 120 | # Working objects | ||||
| 121 | 4 | 16µs | 4 | 2.12ms | has "_${k}" => ( # spent 2.12ms making 4 calls to Mouse::has, avg 531µs/call |
| 122 | does => "Hailo::Role::$name", | ||||
| 123 | lazy_build => 1, | ||||
| 124 | is => 'ro', | ||||
| 125 | init_arg => undef, | ||||
| 126 | ); | ||||
| 127 | |||||
| 128 | # Generate the object itself | ||||
| 129 | 2 | 333µs | 2 | 60µs | # spent 36µs (11+25) within Hailo::BEGIN@129 which was called:
# once (11µs+25µs) by main::BEGIN@6 at line 129 # spent 36µs making 1 call to Hailo::BEGIN@129
# spent 25µs making 1 call to strict::unimport |
| 130 | # spent 117ms (166µs+117) within Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] which was called 3 times, avg 39.1ms/call:
# once (84µs+52.5ms) by Hailo::_storage at line 309
# once (30µs+47.8ms) by Hailo::_tokenizer at line 317
# once (53µs+17.0ms) by Hailo::_engine at line 316 | ||||
| 131 | 3 | 6µs | my ($self) = @_; | ||
| 132 | |||||
| 133 | my $obj = $self->_new_class( | ||||
| 134 | $name, | ||||
| 135 | $self->$method_class, | ||||
| 136 | { | ||||
| 137 | arguments => $self->$method_args, | ||||
| 138 | ($k ~~ [ qw< engine storage > ] | ||||
| 139 | ? (order => $self->order) | ||||
| 140 | : ()), | ||||
| 141 | ($k ~~ [ qw< engine > ] | ||||
| 142 | ? (storage => $self->_storage) | ||||
| 143 | : ()), | ||||
| 144 | (($k ~~ [ qw< storage > ] and defined $self->brain) | ||||
| 145 | ? ( | ||||
| 146 | 3 | 143µs | 15 | 117ms | hailo => do { # spent 117ms making 3 calls to Hailo::_new_class, avg 39.1ms/call
# spent 4µs making 2 calls to Hailo::tokenizer_class, avg 2µs/call
# spent 3µs making 2 calls to Hailo::brain, avg 2µs/call
# spent 3µs making 2 calls to Hailo::order, avg 2µs/call
# spent 2µs making 1 call to Hailo::engine_class
# spent 2µs making 1 call to Hailo::_storage
# spent 2µs making 1 call to Hailo::engine_args
# spent 2µs making 1 call to Hailo::storage_class
# spent 2µs making 1 call to Hailo::tokenizer_args
# spent 1µs making 1 call to Hailo::storage_args |
| 147 | 1 | 2µs | require Scalar::Util; | ||
| 148 | 1 | 8µs | 1 | 3µs | Scalar::Util::weaken(my $s = $self); # spent 3µs making 1 call to Scalar::Util::weaken |
| 149 | |||||
| 150 | my %callback = ( | ||||
| 151 | has_custom_order => sub { $s->_custom_order }, | ||||
| 152 | has_custom_tokenizer_class => sub { $s->_custom_tokenizer_class }, | ||||
| 153 | set_order => sub { | ||||
| 154 | my ($db_order) = @_; | ||||
| 155 | $s->order($db_order); | ||||
| 156 | $s->_engine->order($db_order); | ||||
| 157 | }, | ||||
| 158 | set_tokenizer_class => sub { | ||||
| 159 | my ($db_tokenizer_class) = @_; | ||||
| 160 | $s->tokenizer_class($db_tokenizer_class); | ||||
| 161 | }, | ||||
| 162 | 1 | 12µs | ); | ||
| 163 | |||||
| 164 | 1 | 2µs | \%callback; | ||
| 165 | }, | ||||
| 166 | brain => $self->brain | ||||
| 167 | ) | ||||
| 168 | : ()), | ||||
| 169 | (($k ~~ [ qw< storage > ] | ||||
| 170 | ? (tokenizer_class => $self->tokenizer_class) | ||||
| 171 | : ())) | ||||
| 172 | }, | ||||
| 173 | ); | ||||
| 174 | |||||
| 175 | 3 | 17µs | return $obj; | ||
| 176 | 4 | 34µs | }; | ||
| 177 | } | ||||
| 178 | |||||
| 179 | # spent 117ms (5.67+112) within Hailo::_new_class which was called 3 times, avg 39.1ms/call:
# 3 times (5.67ms+112ms) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146, avg 39.1ms/call | ||||
| 180 | 3 | 7µs | my ($self, $type, $class, $args) = @_; | ||
| 181 | |||||
| 182 | 3 | 2µs | my $pkg; | ||
| 183 | 3 | 29µs | 3 | 10µs | if ($class =~ m[^\+(?<custom_plugin>.+)$]) { # spent 10µs making 3 calls to Hailo::CORE:match, avg 3µs/call |
| 184 | 2 | 1.18ms | 1 | 279µs | # spent 279µs (259+19) within Hailo::BEGIN@184 which was called:
# once (259µs+19µs) by main::BEGIN@6 at line 184 # spent 279µs making 1 call to Hailo::BEGIN@184 |
| 185 | } else { | ||||
| 186 | 3 | 35µs | 3 | 5µs | my @plugins = @{ $self->PLUGINS }; # spent 5µs making 3 calls to Hailo::PLUGINS, avg 2µs/call |
| 187 | # Be fuzzy about includes, e.g. DBD::SQLite or SQLite or sqlite will go | ||||
| 188 | 13 | 191µs | 26 | 90µs | $pkg = first { / $type : .* : $class /ix } # spent 58µs making 13 calls to Hailo::CORE:regcomp, avg 4µs/call
# spent 32µs making 13 calls to Hailo::CORE:match, avg 2µs/call |
| 189 | 3 | 54µs | 6 | 204µs | sort { length $a <=> length $b } # spent 185µs making 3 calls to List::Util::first, avg 62µs/call
# spent 19µs making 3 calls to Hailo::CORE:sort, avg 6µs/call |
| 190 | @plugins; | ||||
| 191 | |||||
| 192 | 3 | 6µs | unless ($pkg) { | ||
| 193 | local $" = ', '; | ||||
| 194 | my @p = grep { /$type/ } @plugins; | ||||
| 195 | die "Couldn't find a class name matching '$class' in plugins '@p'"; | ||||
| 196 | } | ||||
| 197 | } | ||||
| 198 | |||||
| 199 | 3 | 28µs | 3 | 15µs | if (Any::Moose::moose_is_preferred()) { # spent 15µs making 3 calls to Any::Moose::moose_is_preferred, avg 5µs/call |
| 200 | require Class::MOP; | ||||
| 201 | eval { Class::MOP::load_class($pkg) }; | ||||
| 202 | } else { | ||||
| 203 | 3 | 151µs | eval qq[require $pkg]; # spent 242µs executing statements in string eval
# spent 164µs executing statements in string eval
# spent 152µs executing statements in string eval | ||
| 204 | } | ||||
| 205 | 3 | 4µs | die $@ if $@; | ||
| 206 | |||||
| 207 | 3 | 230µs | 30 | 1.05ms | return $pkg->new(%$args); # spent 614µs making 3 calls to Mouse::Object::new, avg 205µs/call
# spent 296µs making 3 calls to Mouse::Meta::Class::_calculate_all_attributes, avg 99µs/call
# spent 79µs making 1 call to Hailo::Engine::Default::BUILD
# spent 26µs making 1 call to Hailo::Role::Tokenizer::BUILD
# spent 15µs making 10 calls to Mouse::Meta::TypeConstraint::_compiled_type_constraint, avg 1µs/call
# spent 7µs making 3 calls to Mouse::Meta::Class::strict_constructor, avg 2µs/call
# spent 5µs making 1 call to Hailo::Role::Tokenizer::__ANON__[Hailo/Role/Tokenizer.pm:21]
# spent 5µs making 3 calls to Mouse::Meta::Class::is_immutable, avg 2µs/call
# spent 4µs making 3 calls to Mouse::Meta::Class::is_anon_class, avg 1µs/call
# spent 3µs making 2 calls to Mouse::Meta::Attribute::default, avg 1µs/call |
| 208 | } | ||||
| 209 | |||||
| 210 | # spent 3.92s (18µs+3.92) within Hailo::save which was called:
# once (18µs+3.92s) by Hailo::DEMOLISH at line 340 | ||||
| 211 | 1 | 2µs | my ($self, @args) = @_; | ||
| 212 | 1 | 10µs | 2 | 3.92s | $self->_storage->save(@args); # spent 3.92s making 1 call to Hailo::Storage::SQLite::save
# spent 2µs making 1 call to Hailo::_storage |
| 213 | 1 | 7µs | return; | ||
| 214 | } | ||||
| 215 | |||||
| 216 | sub train { | ||||
| 217 | my ($self, $input) = @_; | ||||
| 218 | |||||
| 219 | $self->_storage->start_training(); | ||||
| 220 | |||||
| 221 | given ($input) { | ||||
| 222 | # With STDIN | ||||
| 223 | when (not ref and defined and $_ eq '-') { | ||||
| 224 | die "You must provide STDIN when training from '-'" if $self->_is_interactive(*STDIN); | ||||
| 225 | $self->_train_fh(*STDIN); | ||||
| 226 | } | ||||
| 227 | # With a filehandle | ||||
| 228 | when (ref eq 'GLOB') { | ||||
| 229 | $self->_train_fh($input); | ||||
| 230 | } | ||||
| 231 | # With a file | ||||
| 232 | when (not ref) { | ||||
| 233 | open my $fh, '<:encoding(utf8)', $input; | ||||
| 234 | $self->_train_fh($fh, $input); | ||||
| 235 | } | ||||
| 236 | # With an Array | ||||
| 237 | when (ref eq 'ARRAY') { | ||||
| 238 | $self->_learn_one($_) for @$input; | ||||
| 239 | } | ||||
| 240 | # With something naughty | ||||
| 241 | default { | ||||
| 242 | die "Unknown input: $input"; | ||||
| 243 | } | ||||
| 244 | } | ||||
| 245 | |||||
| 246 | $self->_storage->stop_training(); | ||||
| 247 | |||||
| 248 | return; | ||||
| 249 | } | ||||
| 250 | |||||
| 251 | sub _train_fh { | ||||
| 252 | my ($self, $fh, $filename) = @_; | ||||
| 253 | |||||
| 254 | while (my $line = <$fh>) { | ||||
| 255 | chomp $line; | ||||
| 256 | $self->_learn_one($line); | ||||
| 257 | } | ||||
| 258 | |||||
| 259 | return; | ||||
| 260 | } | ||||
| 261 | |||||
| 262 | sub learn { | ||||
| 263 | my ($self, $input) = @_; | ||||
| 264 | my $inputs; | ||||
| 265 | |||||
| 266 | given ($input) { | ||||
| 267 | when (not defined) { | ||||
| 268 | die "Cannot learn from undef input"; | ||||
| 269 | } | ||||
| 270 | when (not ref) { | ||||
| 271 | $inputs = [$input]; | ||||
| 272 | } | ||||
| 273 | # With an Array | ||||
| 274 | when (ref eq 'ARRAY') { | ||||
| 275 | $inputs = $input | ||||
| 276 | } | ||||
| 277 | default { | ||||
| 278 | die "Unknown input: $input"; | ||||
| 279 | } | ||||
| 280 | } | ||||
| 281 | |||||
| 282 | my $storage = $self->_storage; | ||||
| 283 | |||||
| 284 | $storage->start_learning(); | ||||
| 285 | $self->_learn_one($_) for @$inputs; | ||||
| 286 | $storage->stop_learning(); | ||||
| 287 | return; | ||||
| 288 | } | ||||
| 289 | |||||
| 290 | sub _learn_one { | ||||
| 291 | my ($self, $input) = @_; | ||||
| 292 | my $engine = $self->_engine; | ||||
| 293 | |||||
| 294 | my $tokens = $self->_tokenizer->make_tokens($input); | ||||
| 295 | $engine->learn($tokens); | ||||
| 296 | |||||
| 297 | return; | ||||
| 298 | } | ||||
| 299 | |||||
| 300 | sub learn_reply { | ||||
| 301 | my ($self, $input) = @_; | ||||
| 302 | $self->learn($input); | ||||
| 303 | return $self->reply($input); | ||||
| 304 | } | ||||
| 305 | |||||
| 306 | # spent 132s (1.12+131) within Hailo::reply which was called 30000 times, avg 4.40ms/call:
# 30000 times (1.12s+131s) by main::RUNTIME at line 17 of reply.pl, avg 4.40ms/call | ||||
| 307 | 30000 | 48.9ms | my ($self, $input) = @_; | ||
| 308 | |||||
| 309 | 30000 | 183ms | 30004 | 169ms | my $storage = $self->_storage; # spent 117ms making 30000 calls to Hailo::_storage, avg 4µs/call
# spent 52.6ms making 1 call to Hailo::__ANON__[Hailo.pm:176]
# spent 117µs making 1 call to Mouse::Util::TypeConstraints::__ANON__[Mouse/Util/TypeConstraints.pm:217]
# spent 2µs making 1 call to Mouse::Meta::Attribute::builder
# spent 2µs making 1 call to Mouse::Meta::TypeConstraint::_compiled_type_constraint |
| 310 | # start_training() hasn't been called so we can't guarentee that | ||||
| 311 | # the storage has been engaged at this point. This must be called | ||||
| 312 | # before ->_engine() is called anywhere to ensure that the | ||||
| 313 | # lazy-loading in the engine works. | ||||
| 314 | 30000 | 160ms | 30001 | 441ms | $storage->_engage() unless $storage->_engaged; # spent 389ms making 1 call to Hailo::Storage::SQLite::_engage
# spent 52.0ms making 30000 calls to Hailo::Storage::_engaged, avg 2µs/call |
| 315 | |||||
| 316 | 30000 | 157ms | 30004 | 80.2ms | my $engine = $self->_engine; # spent 63.0ms making 30000 calls to Hailo::_engine, avg 2µs/call
# spent 17.1ms making 1 call to Hailo::__ANON__[Hailo.pm:176]
# spent 115µs making 1 call to Mouse::Util::TypeConstraints::__ANON__[Mouse/Util/TypeConstraints.pm:217]
# spent 2µs making 1 call to Mouse::Meta::Attribute::builder
# spent 2µs making 1 call to Mouse::Meta::TypeConstraint::_compiled_type_constraint |
| 317 | 30000 | 153ms | 30004 | 142ms | my $tokenizer = $self->_tokenizer; # spent 94.2ms making 30000 calls to Hailo::_tokenizer, avg 3µs/call
# spent 47.8ms making 1 call to Hailo::__ANON__[Hailo.pm:176]
# spent 115µs making 1 call to Mouse::Util::TypeConstraints::__ANON__[Mouse/Util/TypeConstraints.pm:217]
# spent 2µs making 1 call to Mouse::Meta::Attribute::builder
# spent 1µs making 1 call to Mouse::Meta::TypeConstraint::_compiled_type_constraint |
| 318 | |||||
| 319 | 30000 | 25.9ms | my $reply; | ||
| 320 | 30000 | 75.6ms | if (defined $input) { | ||
| 321 | my $tokens = $tokenizer->make_tokens($input); | ||||
| 322 | $reply = $engine->reply($tokens); | ||||
| 323 | } | ||||
| 324 | else { | ||||
| 325 | 30000 | 127ms | 30000 | 120s | $reply = $engine->reply(); # spent 120s making 30000 calls to Hailo::Engine::Default::reply, avg 4.00ms/call |
| 326 | } | ||||
| 327 | |||||
| 328 | 30000 | 34.1ms | return unless defined $reply; | ||
| 329 | 30000 | 315ms | 30000 | 10.4s | return $tokenizer->make_output($reply); # spent 10.4s making 30000 calls to Hailo::Tokenizer::Words::make_output, avg 346µs/call |
| 330 | } | ||||
| 331 | |||||
| 332 | sub stats { | ||||
| 333 | my ($self) = @_; | ||||
| 334 | |||||
| 335 | return $self->_storage->totals(); | ||||
| 336 | } | ||||
| 337 | |||||
| 338 | # spent 3.92s (26µs+3.92) within Hailo::DEMOLISH which was called:
# once (26µs+3.92s) by Mouse::Object::DESTROY at line 0 of reply.pl | ||||
| 339 | 1 | 2µs | my ($self) = @_; | ||
| 340 | 1 | 21µs | 3 | 3.92s | $self->save() if blessed $self->{_storage} and $self->save_on_exit; # spent 3.92s making 1 call to Hailo::save
# spent 3µs making 1 call to Scalar::Util::blessed
# spent 2µs making 1 call to Hailo::save_on_exit |
| 341 | 1 | 16µs | return; | ||
| 342 | } | ||||
| 343 | |||||
| 344 | sub _is_interactive { | ||||
| 345 | require IO::Interactive; | ||||
| 346 | return IO::Interactive::is_interactive(); | ||||
| 347 | } | ||||
| 348 | |||||
| 349 | 1 | 32µs | 2 | 157µs | __PACKAGE__->meta->make_immutable; # spent 142µs making 1 call to Mouse::Meta::Class::make_immutable
# spent 14µs making 1 call to Hailo::meta |
| 350 | |||||
| 351 | =encoding utf8 | ||||
| 352 | |||||
| 353 | =head1 NAME | ||||
| 354 | |||||
| 355 | Hailo - A pluggable Markov engine analogous to MegaHAL | ||||
| 356 | |||||
| 357 | =head1 SYNOPSIS | ||||
| 358 | |||||
| 359 | This is the synopsis for using Hailo as a module. See L<hailo> for | ||||
| 360 | command-line invocation. | ||||
| 361 | |||||
| 362 | # Hailo requires Perl 5.10 | ||||
| 363 | use 5.010; | ||||
| 364 | use Any::Moose; | ||||
| 365 | use Hailo; | ||||
| 366 | |||||
| 367 | # Construct a new in-memory Hailo using the SQLite backend. See | ||||
| 368 | # backend documentation for other options. | ||||
| 369 | my $hailo = Hailo->new; | ||||
| 370 | |||||
| 371 | # Various ways to learn | ||||
| 372 | my @train_this = ("I like big butts", "and I can not lie"); | ||||
| 373 | $hailo->learn(\@train_this); | ||||
| 374 | $hailo->learn($_) for @train_this; | ||||
| 375 | |||||
| 376 | # Heavy-duty training interface. Backends may drop some safety | ||||
| 377 | # features like journals or synchronous IO to train faster using | ||||
| 378 | # this mode. | ||||
| 379 | $hailo->train("megahal.trn"); | ||||
| 380 | $hailo->train($filehandle); | ||||
| 381 | |||||
| 382 | # Make the brain babble | ||||
| 383 | say $hailo->reply("hello good sir."); | ||||
| 384 | # Just say something at random | ||||
| 385 | say $hailo->reply(); | ||||
| 386 | |||||
| 387 | =head1 DESCRIPTION | ||||
| 388 | |||||
| 389 | Hailo is a fast and lightweight markov engine intended to replace | ||||
| 390 | L<AI::MegaHAL|AI::MegaHAL>. It has a L<Mouse|Mouse> (or | ||||
| 391 | L<Moose|Moose>) based core with pluggable | ||||
| 392 | L<storage|Hailo::Role::Storage>, L<tokenizer|Hailo::Role::Tokenizer> | ||||
| 393 | and L<engine|Hailo::Role::Engine> backends. | ||||
| 394 | |||||
| 395 | It is similar to MegaHAL in functionality, the main differences (with the | ||||
| 396 | default backends) being better scalability, drastically less memory usage, | ||||
| 397 | an improved tokenizer, and tidier output. | ||||
| 398 | |||||
| 399 | With this distribution, you can create, modify, and query Hailo brains. To | ||||
| 400 | use Hailo in event-driven POE applications, you can use the | ||||
| 401 | L<POE::Component::Hailo|POE::Component::Hailo> wrapper. One example is | ||||
| 402 | L<POE::Component::IRC::Plugin::Hailo|POE::Component::IRC::Plugin::Hailo>, | ||||
| 403 | which implements an IRC chat bot. | ||||
| 404 | |||||
| 405 | =head2 Etymology | ||||
| 406 | |||||
| 407 | I<Hailo> is a portmanteau of I<HAL> (as in MegaHAL) and | ||||
| 408 | L<failo|http://identi.ca/failo>. | ||||
| 409 | |||||
| 410 | =head1 Backends | ||||
| 411 | |||||
| 412 | Hailo supports pluggable L<storage|Hailo::Role::Storage> and | ||||
| 413 | L<tokenizer|Hailo::Role::Tokenizer> backends, it also supports a | ||||
| 414 | pluggable L<UI|Hailo::Role::UI> backend which is used by the L<hailo> | ||||
| 415 | command-line utility. | ||||
| 416 | |||||
| 417 | =head2 Storage | ||||
| 418 | |||||
| 419 | Hailo can currently store its data in either a | ||||
| 420 | L<SQLite|Hailo::Storage::SQLite>, | ||||
| 421 | L<PostgreSQL|Hailo::Storage::PostgreSQL> or | ||||
| 422 | L<MySQL|Hailo::Storage::MySQL> database. Some NoSQL backends were | ||||
| 423 | supported in earlier versions, but they were removed as they had no | ||||
| 424 | redeeming quality. | ||||
| 425 | |||||
| 426 | SQLite is the primary target for Hailo. It's much faster and uses less | ||||
| 427 | resources than the other two. It's highly recommended that you use it. | ||||
| 428 | |||||
| 429 | See L<Hailo::Storage/"Comparison of backends"> for benchmarks showing | ||||
| 430 | how the various backends compare under different workloads, and how | ||||
| 431 | you can create your own. | ||||
| 432 | |||||
| 433 | =head2 Tokenizer | ||||
| 434 | |||||
| 435 | By default Hailo will use L<the word | ||||
| 436 | tokenizer|Hailo::Tokenizer::Words> to split up input by whitespace, | ||||
| 437 | taking into account things like quotes, sentence terminators and more. | ||||
| 438 | |||||
| 439 | There's also a L<the character | ||||
| 440 | tokenizer|Hailo::Tokenizer::Chars>. It's not generally useful for a | ||||
| 441 | conversation bot but can be used to e.g. generate new words given a | ||||
| 442 | list of existing words. | ||||
| 443 | |||||
| 444 | =head1 UPGRADING | ||||
| 445 | |||||
| 446 | Hailo makes no promises about brains generated with earlier versions | ||||
| 447 | being compatable with future version and due to the way Hailo works | ||||
| 448 | there's no practical way to make that promise. Learning in Hailo is | ||||
| 449 | lossy so an accurate conversion is impossible. | ||||
| 450 | |||||
| 451 | If you're maintaining a Hailo brain that you want to keep using you | ||||
| 452 | should save the input you trained it on and re-train when you upgrade. | ||||
| 453 | |||||
| 454 | Hailo is always going to lose information present in the input you | ||||
| 455 | give it. How input tokens get split up and saved to the storage | ||||
| 456 | backend depends on the version of the tokenizer being used and how | ||||
| 457 | that input gets saved to the database. | ||||
| 458 | |||||
| 459 | For instance if an earlier version of Hailo tokenized C<"foo+bar"> | ||||
| 460 | simply as C<"foo+bar"> but a later version split that up into | ||||
| 461 | C<"foo", "+", "bar">, then an input of C<"foo+bar are my favorite | ||||
| 462 | metasyntactic variables"> wouldn't take into account the existing | ||||
| 463 | C<"foo+bar"> string in the database. | ||||
| 464 | |||||
| 465 | Tokenizer changes like this would cause the brains to accumulate | ||||
| 466 | garbage and would leave other parts in a state they wouldn't otherwise | ||||
| 467 | have gotten into. | ||||
| 468 | |||||
| 469 | There have been more drastic changes to the database format itself in | ||||
| 470 | the past. | ||||
| 471 | |||||
| 472 | Having said all that the database format and the tokenizer are | ||||
| 473 | relatively stable. At the time of writing 0.33 is the latest release | ||||
| 474 | and it's compatable with brains down to at least 0.17. If you're | ||||
| 475 | upgrading and there isn't a big notice about the storage format being | ||||
| 476 | incompatable in the F<Changes> file your old brains will probably work | ||||
| 477 | just fine. | ||||
| 478 | |||||
| 479 | =head1 ATTRIBUTES | ||||
| 480 | |||||
| 481 | =head2 C<brain> | ||||
| 482 | |||||
| 483 | The name of the brain (file name, database name) to use as storage. | ||||
| 484 | There is no default. Whether this gets used at all depends on the | ||||
| 485 | storage backend, currently only SQLite uses it. | ||||
| 486 | |||||
| 487 | =head2 C<save_on_exit> | ||||
| 488 | |||||
| 489 | A boolean value indicating whether Hailo should save its state before | ||||
| 490 | its object gets destroyed. This defaults to true and will simply call | ||||
| 491 | L<save|/save> at C<DEMOLISH> time. | ||||
| 492 | |||||
| 493 | See L<Hailo::Storage::SQLite/"in_memory"> for how the SQLite backend | ||||
| 494 | uses this option in conjunction with its C<in_memory> option. | ||||
| 495 | |||||
| 496 | =head2 C<order> | ||||
| 497 | |||||
| 498 | The Markov order (chain length) you want to use for an empty brain. | ||||
| 499 | The default is 2. | ||||
| 500 | |||||
| 501 | =head2 C<engine_class> | ||||
| 502 | |||||
| 503 | =head2 C<storage_class> | ||||
| 504 | |||||
| 505 | =head2 C<tokenizer_class> | ||||
| 506 | |||||
| 507 | =head2 C<ui_class> | ||||
| 508 | |||||
| 509 | A a short name name of the class we use for the engine, storage, | ||||
| 510 | tokenizer or ui backends. | ||||
| 511 | |||||
| 512 | By default this is B<Default> for the engine, B<SQLite> for storage, | ||||
| 513 | B<Words> for the tokenizer and B<ReadLine> for the UI. The UI backend | ||||
| 514 | is only used by the L<hailo> command-line interface. | ||||
| 515 | |||||
| 516 | You can only specify the short name of one of the packages Hailo | ||||
| 517 | itself ships with. If you need another class then just prefix the | ||||
| 518 | package with a plus (Catalyst style), e.g. C<+My::Foreign::Tokenizer>. | ||||
| 519 | |||||
| 520 | =head2 C<engine_args> | ||||
| 521 | |||||
| 522 | =head2 C<storage_args> | ||||
| 523 | |||||
| 524 | =head2 C<tokenizer_args> | ||||
| 525 | |||||
| 526 | =head2 C<ui_args> | ||||
| 527 | |||||
| 528 | A C<HashRef> of arguments for engine/storage/tokenizer/ui | ||||
| 529 | backends. See the documentation for the backends for what sort of | ||||
| 530 | arguments they accept. | ||||
| 531 | |||||
| 532 | =head1 METHODS | ||||
| 533 | |||||
| 534 | =head2 C<new> | ||||
| 535 | |||||
| 536 | This is the constructor. It accepts the attributes specified in | ||||
| 537 | L</ATTRIBUTES>. | ||||
| 538 | |||||
| 539 | =head2 C<learn> | ||||
| 540 | |||||
| 541 | Takes a string or an array reference of strings and learns from them. | ||||
| 542 | |||||
| 543 | =head2 C<train> | ||||
| 544 | |||||
| 545 | Takes a filename, filehandle or array reference and learns from all its | ||||
| 546 | lines. If a filename is passed, the file is assumed to be UTF-8 encoded. | ||||
| 547 | Unlike L<C<learn>|/learn>, this method sacrifices some safety (disables | ||||
| 548 | the database journal, fsyncs, etc) for speed while learning. | ||||
| 549 | |||||
| 550 | =head2 C<reply> | ||||
| 551 | |||||
| 552 | Takes an optional line of text and generates a reply that might be relevant. | ||||
| 553 | |||||
| 554 | =head2 C<learn_reply> | ||||
| 555 | |||||
| 556 | Takes a string argument, learns from it, and generates a reply that | ||||
| 557 | might be relevant. This is equivalent to calling L<learn|/learn> | ||||
| 558 | followed by L<reply|/reply>. | ||||
| 559 | |||||
| 560 | =head2 C<save> | ||||
| 561 | |||||
| 562 | Tells the underlying storage backend to L<save its | ||||
| 563 | state|Hailo::Role::Storage/"save">, any arguments to this method will | ||||
| 564 | be passed as-is to the backend. | ||||
| 565 | |||||
| 566 | =head2 C<stats> | ||||
| 567 | |||||
| 568 | Takes no arguments. Returns the number of tokens, expressions, previous | ||||
| 569 | token links and next token links. | ||||
| 570 | |||||
| 571 | =head1 SUPPORT | ||||
| 572 | |||||
| 573 | You can join the IRC channel I<#hailo> on FreeNode if you have questions. | ||||
| 574 | |||||
| 575 | =head1 BUGS | ||||
| 576 | |||||
| 577 | Bugs, feature requests and other issues are tracked in L<Hailo's RT on | ||||
| 578 | rt.cpan.org|https://rt.cpan.org/Dist/Display.html?Name=Hailo> | ||||
| 579 | |||||
| 580 | =head1 SEE ALSO | ||||
| 581 | |||||
| 582 | =over | ||||
| 583 | |||||
| 584 | =item * L<POE::Component::Hailo> - A non-blocking POE wrapper around Hailo | ||||
| 585 | |||||
| 586 | =item * L<POE::Component::IRC::Plugin::Hailo> - A Hailo IRC bot plugin | ||||
| 587 | |||||
| 588 | =item * L<http://github.com/hinrik/failo> - Failo, an IRC bot that uses Hailo | ||||
| 589 | |||||
| 590 | =item * L<http://github.com/bingos/gumbybrain> - GumbyBRAIN, a more famous IRC bot that uses Hailo | ||||
| 591 | |||||
| 592 | =item * L<Hailo::UI::Web> - A L<Catalyst> and jQuery powered web | ||||
| 593 | interface to Hailo available at L<hailo.nix.is|http://hailo.nix.is> | ||||
| 594 | and as L<hailo-ui-web|http://github.com/avar/hailo-ui-web> on | ||||
| 595 | L<GitHub|http://github.com> | ||||
| 596 | |||||
| 597 | =item * L<HALBot> - Another L<Catalyst> Dojo powered web interface to | ||||
| 598 | Hailo available at L<bifurcat.es|http://bifurcat.es/> and as | ||||
| 599 | L<halbot-on-the-web|http://gitorious.org/halbot-on-the-web/halbot-on-the-web> | ||||
| 600 | at L<gitorious|http://gitorious.org> | ||||
| 601 | |||||
| 602 | =item * L<http://github.com/pteichman/cobe> - cobe, a Python port of MegaHAL "inspired by the success of Hailo" | ||||
| 603 | |||||
| 604 | =back | ||||
| 605 | |||||
| 606 | =head1 LINKS | ||||
| 607 | |||||
| 608 | =over | ||||
| 609 | |||||
| 610 | =item * L<hailo.org|http://hailo.org> - Hailo's website | ||||
| 611 | |||||
| 612 | =item * L<http://bit.ly/hailo_rewrite_of_megahal> - Hailo: A Perl rewrite of | ||||
| 613 | MegaHAL, A blog posting about the motivation behind Hailo | ||||
| 614 | |||||
| 615 | =item * L<http://blogs.perl.org/users/aevar_arnfjor_bjarmason/hailo/> - | ||||
| 616 | More blog posts about Hailo on E<AElig>var ArnfjE<ouml>rE<eth> | ||||
| 617 | Bjarmason's L<blogs.perl.org|http://blogs.perl.org> blog | ||||
| 618 | |||||
| 619 | =item * Hailo on L<freshmeat|http://freshmeat.net/projects/hailo> and | ||||
| 620 | L<ohloh|https://www.ohloh.net/p/hailo> | ||||
| 621 | |||||
| 622 | =back | ||||
| 623 | |||||
| 624 | =head1 AUTHORS | ||||
| 625 | |||||
| 626 | Hinrik E<Ouml>rn SigurE<eth>sson, hinrik.sig@gmail.com | ||||
| 627 | |||||
| 628 | E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avar@cpan.org> | ||||
| 629 | |||||
| 630 | =head1 LICENSE AND COPYRIGHT | ||||
| 631 | |||||
| 632 | Copyright 2010 Hinrik E<Ouml>rn SigurE<eth>sson and | ||||
| 633 | E<AElig>var ArnfjE<ouml>rE<eth> Bjarmason <avar@cpan.org> | ||||
| 634 | |||||
| 635 | This program is free software, you can redistribute it and/or modify | ||||
| 636 | it under the same terms as Perl itself. | ||||
| 637 | |||||
| 638 | 1 | 21µs | 1 | 4.66ms | =cut # spent 4.66ms making 1 call to B::Hooks::EndOfScope::__ANON__[B/Hooks/EndOfScope.pm:26] |
sub Hailo::CORE:match; # opcode | |||||
# spent 58µs within Hailo::CORE:regcomp which was called 13 times, avg 4µs/call:
# 13 times (58µs+0s) by List::Util::first at line 188, avg 4µs/call | |||||
# spent 19µs within Hailo::CORE:sort which was called 3 times, avg 6µs/call:
# 3 times (19µs+0s) by Hailo::_new_class at line 189, avg 6µs/call | |||||
# spent 5µs within Hailo::PLUGINS which was called 3 times, avg 2µs/call:
# 3 times (5µs+0s) by Hailo::_new_class at line 186, avg 2µs/call | |||||
# spent 63.0ms (45.8+17.2) within Hailo::_engine which was called 30000 times, avg 2µs/call:
# 30000 times (45.8ms+17.2ms) by Hailo::reply at line 316, avg 2µs/call | |||||
# spent 117ms (64.0+52.7) within Hailo::_storage which was called 30002 times, avg 4µs/call:
# 30000 times (64.0ms+52.7ms) by Hailo::reply at line 309, avg 4µs/call
# once (2µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146
# once (2µs+0s) by Hailo::save at line 212 | |||||
# spent 94.2ms (46.3+47.9) within Hailo::_tokenizer which was called 30000 times, avg 3µs/call:
# 30000 times (46.3ms+47.9ms) by Hailo::reply at line 317, avg 3µs/call | |||||
# spent 12µs (10+2) within Hailo::brain which was called 3 times, avg 4µs/call:
# 2 times (3µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146, avg 2µs/call
# once (7µs+2µs) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:71] at line 70 | |||||
# spent 2µs within Hailo::engine_args which was called:
# once (2µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146 | |||||
# spent 2µs within Hailo::engine_class which was called:
# once (2µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146 | |||||
# spent 3µs within Hailo::order which was called 2 times, avg 2µs/call:
# 2 times (3µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146, avg 2µs/call | |||||
# spent 2µs within Hailo::save_on_exit which was called:
# once (2µs+0s) by Hailo::DEMOLISH at line 340 | |||||
# spent 1µs within Hailo::storage_args which was called:
# once (1µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146 | |||||
# spent 2µs within Hailo::storage_class which was called:
# once (2µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146 | |||||
# spent 2µs within Hailo::tokenizer_args which was called:
# once (2µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146 | |||||
# spent 4µs within Hailo::tokenizer_class which was called 2 times, avg 2µs/call:
# 2 times (4µs+0s) by Hailo::__ANON__[/home/hinrik/perl5/perlbrew/perls/perl-5.13.5/lib/site_perl/5.13.5/Hailo.pm:176] at line 146, avg 2µs/call |