← Index
NYTProf Performance Profile   « line view »
For ../prof.pl
  Run on Thu Dec 15 15:23:56 2022
Reported on Thu Dec 15 15:27:01 2022

Filename/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Mojo/Base.pm
StatementsExecuted 6147571 statements in 5.70s
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
112623744877ms877msMojo::Base::::new Mojo::Base::new
7236172511557ms557msMojo::URL::::fragment Mojo::URL::fragment
45172141403ms403msMojo::URL::::scheme Mojo::URL::scheme
42076521376ms376msMojo::Path::::charset Mojo::Path::charset
25534411360ms360msMojo::Parameters::::charset Mojo::Parameters::charset
43964441292ms292msMojo::URL::::host Mojo::URL::host
30332421189ms189msMojo::URL::::port Mojo::URL::port
336831151.9ms51.9msMojo::URL::::base Mojo::URL::base
696832141.1ms41.1msMojo::URL::::userinfo Mojo::URL::userinfo
1113.35ms3.51msMojo::Base::::BEGIN@17 Mojo::Base::BEGIN@17
111668µs709µsMojo::Base::::BEGIN@5 Mojo::Base::BEGIN@5
12128196µs723µsMojo::Base::::import Mojo::Base::import
111102µs129µsMojo::Base::::BEGIN@20 Mojo::Base::BEGIN@20
51178µs160µsMojo::Base::::attr Mojo::Base::attr
11124µs28µsMojo::Base::::BEGIN@3 Mojo::Base::BEGIN@3
152120µs20µsMojo::Base::::CORE:match Mojo::Base::CORE:match (opcode)
1119µs73µsMojo::Base::::BEGIN@6 Mojo::Base::BEGIN@6
1118µs12µsMojo::Base::::BEGIN@133 Mojo::Base::BEGIN@133
2217µs82µsMojo::URL::::has Mojo::URL::has
1117µs8µsMojo::Base::::BEGIN@7 Mojo::Base::BEGIN@7
1116µs11µsMojo::Base::::BEGIN@45 Mojo::Base::BEGIN@45
1115µs33µsMojo::Base::::BEGIN@4 Mojo::Base::BEGIN@4
1114µs34µsMojo::JSON::Pointer::::hasMojo::JSON::Pointer::has
1114µs39µsMojo::Parameters::::has Mojo::Parameters::has
1114µs24µsMojo::Path::::has Mojo::Path::has
1113µs3µsMojo::Base::::BEGIN@10 Mojo::Base::BEGIN@10
1113µs3µsMojo::Base::::BEGIN@11 Mojo::Base::BEGIN@11
0000s0sMojo::Base::::DESTROY Mojo::Base::DESTROY
0000s0sMojo::Base::::__ANON__[:113] Mojo::Base::__ANON__[:113]
0000s0sMojo::Base::::__ANON__[:136] Mojo::Base::__ANON__[:136]
0000s0sMojo::Base::::__ANON__[:43] Mojo::Base::__ANON__[:43]
0000s0sMojo::Base::::__ANON__[:66] Mojo::Base::__ANON__[:66]
0000s0sMojo::Base::::__ANON__[:73] Mojo::Base::__ANON__[:73]
0000s0sMojo::Base::::__ANON__[:81] Mojo::Base::__ANON__[:81]
0000s0sMojo::Base::::__ANON__[:88] Mojo::Base::__ANON__[:88]
0000s0sMojo::Base::::__ANON__[:91] Mojo::Base::__ANON__[:91]
0000s0sMojo::Base::::tap Mojo::Base::tap
0000s0sMojo::Base::::with_roles Mojo::Base::with_roles
0000s0sMojo::JSON::Pointer::::dataMojo::JSON::Pointer::data
0000s0sMojo::Util::_Guard::::has Mojo::Util::_Guard::has
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1package Mojo::Base;
2
3235µs232µs
# spent 28µs (24+4) within Mojo::Base::BEGIN@3 which was called: # once (24µs+4µs) by Mojo::URL::BEGIN@2 at line 3
use strict;
# spent 28µs making 1 call to Mojo::Base::BEGIN@3 # spent 4µs making 1 call to strict::import
4214µs261µs
# spent 33µs (5+28) within Mojo::Base::BEGIN@4 which was called: # once (5µs+28µs) by Mojo::URL::BEGIN@2 at line 4
use warnings;
# spent 33µs making 1 call to Mojo::Base::BEGIN@4 # spent 28µs making 1 call to warnings::import
52605µs2711µs
# spent 709µs (668+41) within Mojo::Base::BEGIN@5 which was called: # once (668µs+41µs) by Mojo::URL::BEGIN@2 at line 5
use utf8;
# spent 709µs making 1 call to Mojo::Base::BEGIN@5 # spent 2µs making 1 call to utf8::import
6220µs2137µs
# spent 73µs (9+64) within Mojo::Base::BEGIN@6 which was called: # once (9µs+64µs) by Mojo::URL::BEGIN@2 at line 6
use feature ':5.16';
# spent 73µs making 1 call to Mojo::Base::BEGIN@6 # spent 64µs making 1 call to feature::import
7232µs29µs
# spent 8µs (7+1000ns) within Mojo::Base::BEGIN@7 which was called: # once (7µs+1000ns) by Mojo::URL::BEGIN@2 at line 7
use mro;
# spent 8µs making 1 call to Mojo::Base::BEGIN@7 # spent 1µs making 1 call to mro::import
8
9# No imports because we get subclassed, a lot!
10220µs13µs
# spent 3µs within Mojo::Base::BEGIN@10 which was called: # once (3µs+0s) by Mojo::URL::BEGIN@2 at line 10
use Carp ();
# spent 3µs making 1 call to Mojo::Base::BEGIN@10
11260µs13µs
# spent 3µs within Mojo::Base::BEGIN@11 which was called: # once (3µs+0s) by Mojo::URL::BEGIN@2 at line 11
use Scalar::Util ();
# spent 3µs making 1 call to Mojo::Base::BEGIN@11
12
13# Defer to runtime so Mojo::Util can use "-strict"
141528µsrequire Mojo::Util;
15
16# Role support requires Role::Tiny 2.000001+
1751.11ms33.55ms
# spent 3.51ms (3.35+161µs) within Mojo::Base::BEGIN@17 which was called: # once (3.35ms+161µs) by Mojo::URL::BEGIN@2 at line 17
use constant ROLES => !!(eval { require Role::Tiny; Role::Tiny->VERSION('2.000001'); 1 });
# spent 3.51ms making 1 call to Mojo::Base::BEGIN@17 # spent 39µs making 1 call to constant::import # spent 6µs making 1 call to UNIVERSAL::VERSION
18
19# async/await support requires Future::AsyncAwait 0.52+
20
# spent 129µs (102+27) within Mojo::Base::BEGIN@20 which was called: # once (102µs+27µs) by Mojo::URL::BEGIN@2 at line 22
use constant ASYNC => $ENV{MOJO_NO_ASYNC}
21 ? 0
223247µs2156µs : !!(eval { require Future::AsyncAwait; Future::AsyncAwait->VERSION('0.52'); 1 });
# spent 129µs making 1 call to Mojo::Base::BEGIN@20 # spent 27µs making 1 call to constant::import
23
24# Protect subclasses using AUTOLOAD
25sub DESTROY { }
26
27
# spent 160µs (78+82) within Mojo::Base::attr which was called 5 times, avg 32µs/call: # 5 times (78µs+82µs) by Mojo::JSON::Pointer::has or Mojo::Parameters::has or Mojo::Path::has or Mojo::URL::has at line 136, avg 32µs/call
sub attr {
2854µs my ($self, $attrs, $value, %kv) = @_;
2954µs return unless (my $class = ref $self || $self) && $attrs;
30
3153µs Carp::croak 'Default has to be a code reference or constant value' if ref $value && ref $value ne 'CODE';
3254µs Carp::croak 'Unsupported attribute option' if grep { $_ ne 'weak' } keys %kv;
33
34 # Weaken
3552µs if ($kv{weak}) {
36 state %weak_names;
37 unless ($weak_names{$class}) {
38 my $names = $weak_names{$class} = [];
39 my $sub = sub {
40 my $self = shift->next::method(@_);
41 ref $self->{$_} and Scalar::Util::weaken $self->{$_} for @$names;
42 return $self;
43 };
44 Mojo::Util::monkey_patch(my $base = $class . '::_Base', 'new', $sub);
452571µs216µs
# spent 11µs (6+5) within Mojo::Base::BEGIN@45 which was called: # once (6µs+5µs) by Mojo::URL::BEGIN@2 at line 45
no strict 'refs';
# spent 11µs making 1 call to Mojo::Base::BEGIN@45 # spent 5µs making 1 call to strict::unimport
46 unshift @{"${class}::ISA"}, $base;
47 }
48 push @{$weak_names{$class}}, ref $attrs eq 'ARRAY' ? @$attrs : $attrs;
49 }
50
51518µs for my $attr (@{ref $attrs eq 'ARRAY' ? $attrs : [$attrs]}) {
52932µs915µs Carp::croak qq{Attribute "$attr" invalid} unless $attr =~ /^[a-zA-Z_]\w*$/;
# spent 15µs making 9 calls to Mojo::Base::CORE:match, avg 2µs/call
53
54 # Very performance-sensitive code with lots of micro-optimizations
5591µs my $sub;
5695µs if ($kv{weak}) {
57 if (ref $value) {
58 $sub = sub {
59 return
60 exists $_[0]{$attr}
61 ? $_[0]{$attr}
62 : (ref($_[0]{$attr} = $value->($_[0])) && Scalar::Util::weaken($_[0]{$attr}), $_[0]{$attr})
63 if @_ == 1;
64 ref($_[0]{$attr} = $_[1]) and Scalar::Util::weaken($_[0]{$attr});
65 $_[0];
66 };
67 }
68 else {
69 $sub = sub {
70 return $_[0]{$attr} if @_ == 1;
71 ref($_[0]{$attr} = $_[1]) and Scalar::Util::weaken($_[0]{$attr});
72 $_[0];
73 };
74 }
75 }
76 elsif (ref $value) {
77
# spent 51.9ms within Mojo::URL::base which was called 33683 times, avg 2µs/call: # 33683 times (51.9ms+0s) by Mojo::URL::to_abs at line 128 of Mojo/URL.pm, avg 2µs/call
$sub = sub {
783368310.6ms return exists $_[0]{$attr} ? $_[0]{$attr} : ($_[0]{$attr} = $value->($_[0])) if @_ == 1;
793368318.5ms $_[0]{$attr} = $_[1];
803368336.4ms $_[0];
8112µs };
82 }
83 elsif (defined $value) {
84
# spent 360ms within Mojo::Parameters::charset which was called 255344 times, avg 1µs/call: # 255344 times (360ms+0s) by Mojo::Parameters::to_string at line 150 of Mojo/Parameters.pm, avg 1µs/call # spent 376ms within Mojo::Path::charset which was called 420765 times, avg 893ns/call: # 293229 times (238ms+0s) by Mojo::Path::to_string at line 84 of Mojo/Path.pm, avg 812ns/call # 127536 times (138ms+0s) by Mojo::Path::_parse at line 106 of Mojo/Path.pm, avg 1µs/call
$sub = sub {
856761091.16s return exists $_[0]{$attr} ? $_[0]{$attr} : ($_[0]{$attr} = $value) if @_ == 1;
86 $_[0]{$attr} = $_[1];
87 $_[0];
8824µs };
89 }
90 else {
9131177692.79s
# spent 41.1ms within Mojo::URL::userinfo which was called 69683 times, avg 589ns/call: # 67366 times (39.7ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 589ns/call # 2317 times (1.35ms+0s) by Mojo::URL::_string at line 171 of Mojo/URL.pm, avg 585ns/call # spent 189ms within Mojo::URL::port which was called 303324 times, avg 623ns/call: # 235958 times (128ms+0s) by Mojo::URL::host_port at line 30 of Mojo/URL.pm, avg 544ns/call # 67366 times (60.5ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 898ns/call # spent 292ms within Mojo::URL::host which was called 439644 times, avg 663ns/call: # 239553 times (144ms+0s) by Mojo::URL::ihost at line 41 of Mojo/URL.pm, avg 601ns/call # 99042 times (79.0ms+0s) by Mojo::URL::host_port at line 26 of Mojo/URL.pm, avg 798ns/call # 67366 times (50.5ms+0s) by Mojo::URL::to_abs at line 132 of Mojo/URL.pm, avg 749ns/call # 33683 times (18.1ms+0s) by Mojo::URL::to_abs at line 131 of Mojo/URL.pm, avg 538ns/call # spent 403ms within Mojo::URL::scheme which was called 451721 times, avg 893ns/call: # 239553 times (183ms+0s) by Mojo::URL::protocol at line 96 of Mojo/URL.pm, avg 763ns/call # 99042 times (124ms+0s) by Mojo::URL::parse at line 57 of Mojo/URL.pm, avg 1µs/call # 67366 times (54.4ms+0s) by Mojo::URL::to_abs at line 128 of Mojo/URL.pm, avg 808ns/call # 45760 times (42.2ms+0s) by Mojo::URL::is_abs at line 48 of Mojo/URL.pm, avg 922ns/call # spent 557ms within Mojo::URL::fragment which was called 723617 times, avg 769ns/call: # 239553 times (153ms+0s) by Mojo::URL::_string at line 181 of Mojo/URL.pm, avg 639ns/call # 88516 times (50.4ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 874 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 570ns/call # 68091 times (63.8ms+0s) by JSON::Schema::Modern::Utilities::canonical_uri at line 195 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Utilities.pm, avg 937ns/call # 68091 times (59.7ms+0s) by JSON::Schema::Modern::Utilities::canonical_uri at line 193 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Utilities.pm, avg 877ns/call # 64346 times (37.3ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 879 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 579ns/call # 58250 times (55.3ms+0s) by Mojo::URL::parse at line 60 of Mojo/URL.pm, avg 949ns/call # 46451 times (33.8ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 862 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 727ns/call # 38783 times (59.3ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 878 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 2µs/call # 38783 times (35.7ms+0s) by JSON::Schema::Modern::_fetch_from_uri at line 865 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 921ns/call # 5112 times (3.42ms+0s) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 243 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Vocabulary/Core.pm, avg 668ns/call # 4196 times (2.19ms+0s) by JSON::Schema::Modern::Utilities::E at line 218 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Utilities.pm, avg 521ns/call # 2556 times (2.08ms+0s) by JSON::Schema::Modern::Vocabulary::Core::_eval_keyword_dynamicRef at line 249 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Vocabulary/Core.pm, avg 812ns/call # 756 times (369µs+0s) by JSON::Schema::Modern::traverse at line 259 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 488ns/call # 36 times (22µs+0s) by JSON::Schema::Modern::Document::__ANON__[/Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm:135] at line 131 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm, avg 611ns/call # 18 times (30µs+0s) by JSON::Schema::Modern::__ANON__[/Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm:685] at line 676 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 2µs/call # 15 times (13µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_anchor at line 177 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Vocabulary/Core.pm, avg 867ns/call # 14 times (19µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id at line 66 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Vocabulary/Core.pm, avg 1µs/call # 14 times (7µs+0s) by JSON::Schema::Modern::Vocabulary::Core::_traverse_keyword_id at line 62 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Vocabulary/Core.pm, avg 500ns/call # 10 times (4µs+0s) by JSON::Schema::Modern::Document::_set_canonical_uri at line 39 of (eval 268)[Sub/Quote.pm:3], avg 400ns/call # 9 times (4µs+0s) by JSON::Schema::Modern::add_schema at line 143 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm, avg 444ns/call # 8 times (8µs+0s) by JSON::Schema::Modern::Document::canonical_uri at line 44 of (eval 267)[Sub/Quote.pm:3], avg 1µs/call # 6 times (4µs+0s) by JSON::Schema::Modern::Document::new at line 74 of (eval 428)[Sub/Quote.pm:3], avg 667ns/call # once (2µs+0s) by JSON::Schema::Modern::Document::OpenAPI::traverse at line 115 of JSON/Schema/Modern/Document/OpenAPI.pm # once (2µs+0s) by JSON::Schema::Modern::Document::OpenAPI::new at line 77 of (eval 421)[Sub/Quote.pm:3] # once (1µs+0s) by Type::Tiny::__ANON__[(eval 425)[/Users/ether/.perlbrew/libs/36.0@std/lib/perl5/Sub/Quote.pm:3]:16] at line 16 of (eval 425)[Sub/Quote.pm:3]
$sub = sub { return $_[0]{$attr} if @_ == 1; $_[0]{$attr} = $_[1]; $_[0] };
92 }
9398µs967µs Mojo::Util::monkey_patch($class, $attr, $sub);
# spent 67µs making 9 calls to Mojo::Util::monkey_patch, avg 7µs/call
94 }
95}
96
97
# spent 723µs (196+527) within Mojo::Base::import which was called 12 times, avg 60µs/call: # once (37µs+100µs) by Mojo::URL::BEGIN@2 at line 2 of Mojo/URL.pm # once (30µs+101µs) by Mojo::JSON::Pointer::BEGIN@2 at line 2 of Mojo/JSON/Pointer.pm # once (32µs+90µs) by Mojo::Parameters::BEGIN@2 at line 2 of Mojo/Parameters.pm # once (36µs+79µs) by Mojo::Util::_Guard::BEGIN@538 at line 538 of Mojo/Util.pm # once (22µs+79µs) by Mojo::Util::BEGIN@2 at line 2 of Mojo/Util.pm # once (21µs+78µs) by Mojo::Path::BEGIN@2 at line 2 of Mojo/Path.pm # once (4µs+0s) by JSON::Schema::Modern::BEGIN@35 at line 35 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (4µs+0s) by OpenAPI::Modern::BEGIN@28 at line 28 of OpenAPI/Modern.pm # once (3µs+0s) by JSON::Schema::Modern::BEGIN@23 at line 23 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern.pm # once (3µs+0s) by Mojo::URL::BEGIN@6 at line 6 of Mojo/URL.pm # once (2µs+0s) by JSON::Schema::Modern::Document::BEGIN@17 at line 17 of /Users/ether/git/JSON-Schema-Modern/lib/JSON/Schema/Modern/Document.pm # once (2µs+0s) by Mojo::URL::BEGIN@5 at line 5 of Mojo/URL.pm
sub import {
981221µs my ($class, $caller) = (shift, caller);
991226µs return unless my @flags = @_;
100
101 # Mojo modules are strict!
102660µs18165µs $_->import for qw(strict warnings utf8);
# spent 145µs making 6 calls to warnings::import, avg 24µs/call # spent 13µs making 6 calls to strict::import, avg 2µs/call # spent 7µs making 6 calls to utf8::import, avg 1µs/call
103612µs6294µs feature->import(':5.16');
# spent 294µs making 6 calls to feature::import, avg 49µs/call
104
105621µs while (my $flag = shift @flags) {
106
107 # Base
1081124µs65µs if ($flag eq '-base') { push @flags, $class }
# spent 5µs making 6 calls to Mojo::Base::CORE:match, avg 833ns/call
109
110 # Role
111 elsif ($flag eq '-role') {
112 Carp::croak 'Role::Tiny 2.000001+ is required for roles' unless ROLES;
113 Mojo::Util::monkey_patch($caller, 'has', sub { attr($caller, @_) });
114 eval "package $caller; use Role::Tiny; 1" or die $@;
115 }
116
117 # async/await
118 elsif ($flag eq '-async_await') {
119 Carp::croak 'Future::AsyncAwait 0.52+ is required for async/await' unless ASYNC;
120 require Mojo::Promise;
121 Future::AsyncAwait->import_into($caller, future_class => 'Mojo::Promise');
122 }
123
124 # Signatures (Perl 5.20+)
125 elsif ($flag eq '-signatures') {
126 Carp::croak 'Subroutine signatures require Perl 5.20+' if $] < 5.020;
127 require experimental;
128 experimental->import($_) for qw(signatures postderef);
129 }
130
131 # Module
132 elsif ($flag !~ /^-/) {
1332777µs216µs
# spent 12µs (8+4) within Mojo::Base::BEGIN@133 which was called: # once (8µs+4µs) by Mojo::URL::BEGIN@2 at line 133
no strict 'refs';
# spent 12µs making 1 call to Mojo::Base::BEGIN@133 # spent 4µs making 1 call to strict::unimport
134526µs59µs require(Mojo::Util::class_to_path($flag)) unless $flag->can('new');
# spent 9µs making 5 calls to UNIVERSAL::can, avg 2µs/call
135524µs push @{"${caller}::ISA"}, $flag;
1361036µs10214µs
# spent 82µs (7+75) within Mojo::URL::has which was called 2 times, avg 41µs/call: # once (2µs+43µs) by JSON::Schema::Modern::BEGIN@23 at line 10 of Mojo/URL.pm # once (5µs+32µs) by JSON::Schema::Modern::BEGIN@23 at line 9 of Mojo/URL.pm # spent 34µs (4+30) within Mojo::JSON::Pointer::has which was called: # once (4µs+30µs) by Moo::_Utils::_require at line 4 of Mojo/JSON/Pointer.pm # spent 24µs (4+20) within Mojo::Path::has which was called: # once (4µs+20µs) by Mojo::URL::BEGIN@6 at line 7 of Mojo/Path.pm # spent 39µs (4+35) within Mojo::Parameters::has which was called: # once (4µs+35µs) by Mojo::URL::BEGIN@5 at line 7 of Mojo/Parameters.pm
Mojo::Util::monkey_patch($caller, 'has', sub { attr($caller, @_) });
# spent 160µs making 5 calls to Mojo::Base::attr, avg 32µs/call # spent 54µs making 5 calls to Mojo::Util::monkey_patch, avg 11µs/call
137 }
138
139 elsif ($flag ne '-strict') { Carp::croak "Unsupported flag: $flag" }
140 }
141}
142
143
# spent 877ms within Mojo::Base::new which was called 1126237 times, avg 779ns/call: # 482139 times (330ms+0s) by Mojo::Path::new at line 53 of Mojo/Path.pm, avg 685ns/call # 392623 times (364ms+0s) by Mojo::URL::new at line 50 of Mojo/URL.pm, avg 928ns/call # 251460 times (182ms+0s) by Mojo::Parameters::new at line 63 of Mojo/Parameters.pm, avg 725ns/call # 15 times (27µs+0s) by Mojo::JSON::Pointer::new at line 9 of Mojo/JSON/Pointer.pm, avg 2µs/call
sub new {
1441126237135ms my $class = shift;
14511262371.55s bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, ref $class || $class;
146}
147
148sub tap {
149 my ($self, $cb) = (shift, shift);
150 $_->$cb(@_) for $self;
151 return $self;
152}
153
154sub with_roles {
155 Carp::croak 'Role::Tiny 2.000001+ is required for roles' unless ROLES;
156 my ($self, @roles) = @_;
157 return $self unless @roles;
158
159 return Role::Tiny->create_class_with_roles($self, map { /^\+(.+)$/ ? "${self}::Role::$1" : $_ } @roles)
160 unless my $class = Scalar::Util::blessed $self;
161
162 return Role::Tiny->apply_roles_to_object($self, map { /^\+(.+)$/ ? "${class}::Role::$1" : $_ } @roles);
163}
164
16513µs1;
166
167=encoding utf8
168
169=head1 NAME
170
171Mojo::Base - Minimal base class for Mojo projects
172
173=head1 SYNOPSIS
174
175 package Cat;
176 use Mojo::Base -base;
177
178 has name => 'Nyan';
179 has ['age', 'weight'] => 4;
180
181 package Tiger;
182 use Mojo::Base 'Cat';
183
184 has friend => sub { Cat->new };
185 has stripes => 42;
186
187 package main;
188 use Mojo::Base -strict;
189
190 my $mew = Cat->new(name => 'Longcat');
191 say $mew->age;
192 say $mew->age(3)->weight(5)->age;
193
194 my $rawr = Tiger->new(stripes => 38, weight => 250);
195 say $rawr->tap(sub { $_->friend->name('Tacgnol') })->weight;
196
197=head1 DESCRIPTION
198
199L<Mojo::Base> is a simple base class for L<Mojo> projects with fluent interfaces.
200
201 # Automatically enables "strict", "warnings", "utf8" and Perl 5.16 features
202 use Mojo::Base -strict;
203 use Mojo::Base -base;
204 use Mojo::Base 'SomeBaseClass';
205 use Mojo::Base -role;
206
207All four forms save a lot of typing. Note that role support depends on L<Role::Tiny> (2.000001+).
208
209 # use Mojo::Base -strict;
210 use strict;
211 use warnings;
212 use utf8;
213 use feature ':5.16';
214 use mro;
215
216 # use Mojo::Base -base;
217 use strict;
218 use warnings;
219 use utf8;
220 use feature ':5.16';
221 use mro;
222 push @ISA, 'Mojo::Base';
223 sub has { Mojo::Base::attr(__PACKAGE__, @_) }
224
225 # use Mojo::Base 'SomeBaseClass';
226 use strict;
227 use warnings;
228 use utf8;
229 use feature ':5.16';
230 use mro;
231 require SomeBaseClass;
232 push @ISA, 'SomeBaseClass';
233 sub has { Mojo::Base::attr(__PACKAGE__, @_) }
234
235 # use Mojo::Base -role;
236 use strict;
237 use warnings;
238 use utf8;
239 use feature ':5.16';
240 use mro;
241 use Role::Tiny;
242 sub has { Mojo::Base::attr(__PACKAGE__, @_) }
243
244On Perl 5.20+ you can also use the C<-signatures> flag with all four forms and enable support for L<subroutine
245signatures|perlsub/"Signatures">.
246
247 # Also enable signatures
248 use Mojo::Base -strict, -signatures;
249 use Mojo::Base -base, -signatures;
250 use Mojo::Base 'SomeBaseClass', -signatures;
251 use Mojo::Base -role, -signatures;
252
253If you have L<Future::AsyncAwait> 0.52+ installed you can also use the C<-async_await> flag to activate the C<async>
254and C<await> keywords to deal much more efficiently with promises. Note that this feature is B<EXPERIMENTAL> and might
255change without warning!
256
257 # Also enable async/await
258 use Mojo::Base -strict, -async_await;
259 use Mojo::Base -base, -signatures, -async_await;
260
261This will also disable experimental warnings on versions of Perl where this feature was still experimental.
262
263=head1 FLUENT INTERFACES
264
265Fluent interfaces are a way to design object-oriented APIs around method chaining to create domain-specific languages,
266with the goal of making the readability of the source code close to written prose.
267
268 package Duck;
269 use Mojo::Base -base, -signatures;
270
271 has 'name';
272
273 sub quack ($self) {
274 my $name = $self->name;
275 say "$name: Quack!"
276 }
277
278L<Mojo::Base> will help you with this by having all attribute accessors created with L</"has"> (or L</"attr">) return
279their invocant (C<$self>) whenever they are used to assign a new attribute value.
280
281 Duck->new->name('Donald')->quack;
282
283In this case the C<name> attribute accessor is called on the object created by C<Duck-E<gt>new>. It assigns a new
284attribute value and then returns the C<Duck> object, so the C<quack> method can be called on it afterwards. These
285method chains can continue until one of the methods called does not return the C<Duck> object.
286
287=head1 FUNCTIONS
288
289L<Mojo::Base> implements the following functions, which can be imported with the C<-base> flag or by setting a base
290class.
291
292=head2 has
293
294 has 'name';
295 has ['name1', 'name2', 'name3'];
296 has name => 'foo';
297 has name => sub {...};
298 has ['name1', 'name2', 'name3'] => 'foo';
299 has ['name1', 'name2', 'name3'] => sub {...};
300 has name => sub {...}, weak => 1;
301 has name => undef, weak => 1;
302 has ['name1', 'name2', 'name3'] => sub {...}, weak => 1;
303
304Create attributes for hash-based objects, just like the L</"attr"> method.
305
306=head1 METHODS
307
308L<Mojo::Base> implements the following methods.
309
310=head2 attr
311
312 $object->attr('name');
313 SubClass->attr('name');
314 SubClass->attr(['name1', 'name2', 'name3']);
315 SubClass->attr(name => 'foo');
316 SubClass->attr(name => sub {...});
317 SubClass->attr(['name1', 'name2', 'name3'] => 'foo');
318 SubClass->attr(['name1', 'name2', 'name3'] => sub {...});
319 SubClass->attr(name => sub {...}, weak => 1);
320 SubClass->attr(name => undef, weak => 1);
321 SubClass->attr(['name1', 'name2', 'name3'] => sub {...}, weak => 1);
322
323Create attribute accessors for hash-based objects, an array reference can be used to create more than one at a time.
324Pass an optional second argument to set a default value, it should be a constant or a callback. The callback will be
325executed at accessor read time if there's no set value, and gets passed the current instance of the object as first
326argument. Accessors can be chained, that means they return their invocant when they are called with an argument.
327
328These options are currently available:
329
330=over 2
331
332=item weak
333
334 weak => $bool
335
336Weaken attribute reference to avoid L<circular references|perlref/"Circular-References"> and memory leaks.
337
338=back
339
340=head2 new
341
342 my $object = SubClass->new;
343 my $object = SubClass->new(name => 'value');
344 my $object = SubClass->new({name => 'value'});
345
346This base class provides a basic constructor for hash-based objects. You can pass it either a hash or a hash reference
347with attribute values.
348
349=head2 tap
350
351 $object = $object->tap(sub {...});
352 $object = $object->tap('some_method');
353 $object = $object->tap('some_method', @args);
354
355Tap into a method chain to perform operations on an object within the chain (also known as a K combinator or Kestrel).
356The object will be the first argument passed to the callback, and is also available as C<$_>. The callback's return
357value will be ignored; instead, the object (the callback's first argument) will be the return value. In this way,
358arbitrary code can be used within (i.e., spliced or tapped into) a chained set of object method calls.
359
360 # Longer version
361 $object = $object->tap(sub { $_->some_method(@args) });
362
363 # Inject side effects into a method chain
364 $object->foo('A')->tap(sub { say $_->foo })->foo('B');
365
366=head2 with_roles
367
368 my $new_class = SubClass->with_roles('SubClass::Role::One');
369 my $new_class = SubClass->with_roles('+One', '+Two');
370 $object = $object->with_roles('+One', '+Two');
371
372Create a new class with one or more L<Role::Tiny> roles. If called on a class returns the new class, or if called on an
373object reblesses the object into the new class. For roles following the naming scheme C<MyClass::Role::RoleName> you
374can use the shorthand C<+RoleName>. Note that role support depends on L<Role::Tiny> (2.000001+).
375
376 # Create a new class with the role "SubClass::Role::Foo" and instantiate it
377 my $new_class = SubClass->with_roles('+Foo');
378 my $object = $new_class->new;
379
380=head1 SEE ALSO
381
382L<Mojolicious>, L<Mojolicious::Guides>, L<https://mojolicious.org>.
383
384=cut
 
# spent 20µs within Mojo::Base::CORE:match which was called 15 times, avg 1µs/call: # 9 times (15µs+0s) by Mojo::Base::attr at line 52, avg 2µs/call # 6 times (5µs+0s) by Mojo::Base::import at line 108, avg 833ns/call
sub Mojo::Base::CORE:match; # opcode