| Filename | /home/hejohns/perl5/lib/perl5/Carp/Assert.pm |
| Statements | Executed 42 statements in 743µs |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 313µs | 512µs | Carp::Assert::BEGIN@8 |
| 3 | 3 | 3 | 25µs | 189µs | Carp::Assert::import |
| 3 | 1 | 1 | 20µs | 162µs | Carp::Assert::_export_to_level |
| 1 | 1 | 1 | 13µs | 1.09ms | Carp::Assert::BEGIN@10 |
| 1 | 1 | 1 | 10µs | 15µs | Carp::Assert::BEGIN@4 |
| 1 | 1 | 1 | 4µs | 22µs | Carp::Assert::BEGIN@5 |
| 1 | 1 | 1 | 4µs | 13µs | Carp::Assert::BEGIN@6 |
| 3 | 1 | 1 | 2µs | 2µs | Carp::Assert::CORE:match (opcode) |
| 0 | 0 | 0 | 0s | 0s | Carp::Assert::_fail_msg |
| 0 | 0 | 0 | 0s | 0s | Carp::Assert::affirm |
| 0 | 0 | 0 | 0s | 0s | Carp::Assert::assert |
| 0 | 0 | 0 | 0s | 0s | Carp::Assert::noop |
| 0 | 0 | 0 | 0s | 0s | Carp::Assert::noop_affirm |
| 0 | 0 | 0 | 0s | 0s | Carp::Assert::should |
| 0 | 0 | 0 | 0s | 0s | Carp::Assert::shouldnt |
| 0 | 0 | 0 | 0s | 0s | Carp::Assert::unimport |
| 0 | 0 | 0 | 0s | 0s | shouldn::t |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package Carp::Assert; | ||||
| 2 | |||||
| 3 | 1 | 8µs | require 5.006; | ||
| 4 | 2 | 24µs | 2 | 20µs | # spent 15µs (10+5) within Carp::Assert::BEGIN@4 which was called:
# once (10µs+5µs) by main::BEGIN@12 at line 4 # spent 15µs making 1 call to Carp::Assert::BEGIN@4
# spent 5µs making 1 call to strict::import |
| 5 | 2 | 14µs | 2 | 41µs | # spent 22µs (4+18) within Carp::Assert::BEGIN@5 which was called:
# once (4µs+18µs) by main::BEGIN@12 at line 5 # spent 22µs making 1 call to Carp::Assert::BEGIN@5
# spent 18µs making 1 call to warnings::import |
| 6 | 2 | 17µs | 2 | 21µs | # spent 13µs (4+9) within Carp::Assert::BEGIN@6 which was called:
# once (4µs+9µs) by main::BEGIN@12 at line 6 # spent 13µs making 1 call to Carp::Assert::BEGIN@6
# spent 9µs making 1 call to Exporter::import |
| 7 | |||||
| 8 | 2 | 110µs | 2 | 536µs | # spent 512µs (313+199) within Carp::Assert::BEGIN@8 which was called:
# once (313µs+199µs) by main::BEGIN@12 at line 8 # spent 512µs making 1 call to Carp::Assert::BEGIN@8
# spent 24µs making 1 call to vars::import |
| 9 | |||||
| 10 | # spent 1.09ms (13µs+1.08) within Carp::Assert::BEGIN@10 which was called:
# once (13µs+1.08ms) by main::BEGIN@12 at line 20 | ||||
| 11 | 1 | 200ns | $VERSION = '0.21'; | ||
| 12 | |||||
| 13 | 1 | 6µs | @ISA = qw(Exporter); | ||
| 14 | |||||
| 15 | 1 | 900ns | %EXPORT_TAGS = ( | ||
| 16 | NDEBUG => [qw(assert affirm should shouldnt DEBUG)], | ||||
| 17 | ); | ||||
| 18 | 1 | 400ns | $EXPORT_TAGS{DEBUG} = $EXPORT_TAGS{NDEBUG}; | ||
| 19 | 1 | 3µs | 1 | 1.07ms | Exporter::export_tags(qw(NDEBUG DEBUG)); # spent 1.07ms making 1 call to Exporter::export_tags |
| 20 | 1 | 517µs | 1 | 1.09ms | } # spent 1.09ms making 1 call to Carp::Assert::BEGIN@10 |
| 21 | |||||
| 22 | # constant.pm, alas, adds too much load time (yes, I benchmarked it) | ||||
| 23 | sub REAL_DEBUG () { 1 } # CONSTANT | ||||
| 24 | sub NDEBUG () { 0 } # CONSTANT | ||||
| 25 | |||||
| 26 | # Export the proper DEBUG flag according to if :NDEBUG is set. | ||||
| 27 | # Also export noop versions of our routines if NDEBUG | ||||
| 28 | sub noop { undef } | ||||
| 29 | sub noop_affirm (&;$) { undef }; | ||||
| 30 | |||||
| 31 | # spent 189µs (25+164) within Carp::Assert::import which was called 3 times, avg 63µs/call:
# once (9µs+59µs) by Gradescope::Translate::BEGIN@16 at line 16 of /home/hejohns/documentsNoSync/22f/490/gradescope-utils/lib/Gradescope/Translate.pm
# once (9µs+57µs) by main::BEGIN@12 at line 12 of /home/hejohns/documentsNoSync/22f/490/gradescope-utils/bin/split.pl
# once (6µs+49µs) by Gradescope::Color::BEGIN@16 at line 16 of /home/hejohns/documentsNoSync/22f/490/gradescope-utils/lib/Gradescope/Color.pm | ||||
| 32 | my $env_ndebug = exists $ENV{PERL_NDEBUG} ? $ENV{PERL_NDEBUG} | ||||
| 33 | 3 | 3µs | : $ENV{'NDEBUG'}; | ||
| 34 | 3 | 16µs | 3 | 2µs | if( grep(/^:NDEBUG$/, @_) or $env_ndebug ) { # spent 2µs making 3 calls to Carp::Assert::CORE:match, avg 533ns/call |
| 35 | my $caller = caller; | ||||
| 36 | foreach my $func (grep !/^DEBUG$/, @{$EXPORT_TAGS{'NDEBUG'}}) { | ||||
| 37 | if( $func eq 'affirm' ) { | ||||
| 38 | *{$caller.'::'.$func} = \&noop_affirm; | ||||
| 39 | } else { | ||||
| 40 | *{$caller.'::'.$func} = \&noop; | ||||
| 41 | } | ||||
| 42 | } | ||||
| 43 | *{$caller.'::DEBUG'} = \&NDEBUG; | ||||
| 44 | } | ||||
| 45 | else { | ||||
| 46 | 3 | 3µs | *DEBUG = *REAL_DEBUG; | ||
| 47 | 3 | 4µs | 3 | 162µs | Carp::Assert->_export_to_level(1, @_); # spent 162µs making 3 calls to Carp::Assert::_export_to_level, avg 54µs/call |
| 48 | } | ||||
| 49 | } | ||||
| 50 | |||||
| 51 | |||||
| 52 | # 5.004's Exporter doesn't have export_to_level. | ||||
| 53 | sub _export_to_level | ||||
| 54 | # spent 162µs (20+142) within Carp::Assert::_export_to_level which was called 3 times, avg 54µs/call:
# 3 times (20µs+142µs) by Carp::Assert::import at line 47, avg 54µs/call | ||||
| 55 | 3 | 800ns | my $pkg = shift; | ||
| 56 | 3 | 800ns | my $level = shift; | ||
| 57 | 3 | 1µs | (undef) = shift; # XXX redundant arg | ||
| 58 | 3 | 2µs | my $callpkg = caller($level); | ||
| 59 | 3 | 11µs | 3 | 29µs | $pkg->export($callpkg, @_); # spent 29µs making 3 calls to Exporter::export, avg 10µs/call |
| 60 | } | ||||
| 61 | |||||
| 62 | |||||
| 63 | sub unimport { | ||||
| 64 | *DEBUG = *NDEBUG; | ||||
| 65 | push @_, ':NDEBUG'; | ||||
| 66 | goto &import; | ||||
| 67 | } | ||||
| 68 | |||||
| 69 | |||||
| 70 | # Can't call confess() here or the stack trace will be wrong. | ||||
| 71 | sub _fail_msg { | ||||
| 72 | my($name) = shift; | ||||
| 73 | my $msg = 'Assertion'; | ||||
| 74 | $msg .= " ($name)" if defined $name; | ||||
| 75 | $msg .= " failed!\n"; | ||||
| 76 | return $msg; | ||||
| 77 | } | ||||
| 78 | |||||
| 79 | |||||
| 80 | =head1 NAME | ||||
| 81 | |||||
| 82 | Carp::Assert - executable comments | ||||
| 83 | |||||
| 84 | =head1 SYNOPSIS | ||||
| 85 | |||||
| 86 | # Assertions are on. | ||||
| 87 | use Carp::Assert; | ||||
| 88 | |||||
| 89 | $next_sunrise_time = sunrise(); | ||||
| 90 | |||||
| 91 | # Assert that the sun must rise in the next 24 hours. | ||||
| 92 | assert(($next_sunrise_time - time) < 24*60*60) if DEBUG; | ||||
| 93 | |||||
| 94 | # Assert that your customer's primary credit card is active | ||||
| 95 | affirm { | ||||
| 96 | my @cards = @{$customer->credit_cards}; | ||||
| 97 | $cards[0]->is_active; | ||||
| 98 | }; | ||||
| 99 | |||||
| 100 | |||||
| 101 | # Assertions are off. | ||||
| 102 | no Carp::Assert; | ||||
| 103 | |||||
| 104 | $next_pres = divine_next_president(); | ||||
| 105 | |||||
| 106 | # Assert that if you predict Dan Quayle will be the next president | ||||
| 107 | # your crystal ball might need some polishing. However, since | ||||
| 108 | # assertions are off, IT COULD HAPPEN! | ||||
| 109 | shouldnt($next_pres, 'Dan Quayle') if DEBUG; | ||||
| 110 | |||||
| 111 | |||||
| 112 | =head1 DESCRIPTION | ||||
| 113 | |||||
| 114 | =begin testing | ||||
| 115 | |||||
| 116 | BEGIN { | ||||
| 117 | local %ENV = %ENV; | ||||
| 118 | delete @ENV{qw(PERL_NDEBUG NDEBUG)}; | ||||
| 119 | require Carp::Assert; | ||||
| 120 | Carp::Assert->import; | ||||
| 121 | } | ||||
| 122 | |||||
| 123 | local %ENV = %ENV; | ||||
| 124 | delete @ENV{qw(PERL_NDEBUG NDEBUG)}; | ||||
| 125 | |||||
| 126 | =end testing | ||||
| 127 | |||||
| 128 | "We are ready for any unforseen event that may or may not | ||||
| 129 | occur." | ||||
| 130 | - Dan Quayle | ||||
| 131 | |||||
| 132 | Carp::Assert is intended for a purpose like the ANSI C library | ||||
| 133 | L<assert.h|http://en.wikipedia.org/wiki/Assert.h>. | ||||
| 134 | If you're already familiar with assert.h, then you can | ||||
| 135 | probably skip this and go straight to the FUNCTIONS section. | ||||
| 136 | |||||
| 137 | Assertions are the explicit expressions of your assumptions about the | ||||
| 138 | reality your program is expected to deal with, and a declaration of | ||||
| 139 | those which it is not. They are used to prevent your program from | ||||
| 140 | blissfully processing garbage inputs (garbage in, garbage out becomes | ||||
| 141 | garbage in, error out) and to tell you when you've produced garbage | ||||
| 142 | output. (If I was going to be a cynic about Perl and the user nature, | ||||
| 143 | I'd say there are no user inputs but garbage, and Perl produces | ||||
| 144 | nothing but...) | ||||
| 145 | |||||
| 146 | An assertion is used to prevent the impossible from being asked of | ||||
| 147 | your code, or at least tell you when it does. For example: | ||||
| 148 | |||||
| 149 | =for example begin | ||||
| 150 | |||||
| 151 | # Take the square root of a number. | ||||
| 152 | sub my_sqrt { | ||||
| 153 | my($num) = shift; | ||||
| 154 | |||||
| 155 | # the square root of a negative number is imaginary. | ||||
| 156 | assert($num >= 0); | ||||
| 157 | |||||
| 158 | return sqrt $num; | ||||
| 159 | } | ||||
| 160 | |||||
| 161 | =for example end | ||||
| 162 | |||||
| 163 | =for example_testing | ||||
| 164 | is( my_sqrt(4), 2, 'my_sqrt example with good input' ); | ||||
| 165 | ok( !eval{ my_sqrt(-1); 1 }, ' and pukes on bad' ); | ||||
| 166 | |||||
| 167 | The assertion will warn you if a negative number was handed to your | ||||
| 168 | subroutine, a reality the routine has no intention of dealing with. | ||||
| 169 | |||||
| 170 | An assertion should also be used as something of a reality check, to | ||||
| 171 | make sure what your code just did really did happen: | ||||
| 172 | |||||
| 173 | open(FILE, $filename) || die $!; | ||||
| 174 | @stuff = <FILE>; | ||||
| 175 | @stuff = do_something(@stuff); | ||||
| 176 | |||||
| 177 | # I should have some stuff. | ||||
| 178 | assert(@stuff > 0); | ||||
| 179 | |||||
| 180 | The assertion makes sure you have some @stuff at the end. Maybe the | ||||
| 181 | file was empty, maybe do_something() returned an empty list... either | ||||
| 182 | way, the assert() will give you a clue as to where the problem lies, | ||||
| 183 | rather than 50 lines down at when you wonder why your program isn't | ||||
| 184 | printing anything. | ||||
| 185 | |||||
| 186 | Since assertions are designed for debugging and will remove themelves | ||||
| 187 | from production code, your assertions should be carefully crafted so | ||||
| 188 | as to not have any side-effects, change any variables, or otherwise | ||||
| 189 | have any effect on your program. Here is an example of a bad | ||||
| 190 | assertation: | ||||
| 191 | |||||
| 192 | assert($error = 1 if $king ne 'Henry'); # Bad! | ||||
| 193 | |||||
| 194 | It sets an error flag which may then be used somewhere else in your | ||||
| 195 | program. When you shut off your assertions with the $DEBUG flag, | ||||
| 196 | $error will no longer be set. | ||||
| 197 | |||||
| 198 | Here's another example of B<bad> use: | ||||
| 199 | |||||
| 200 | assert($next_pres ne 'Dan Quayle' or goto Canada); # Bad! | ||||
| 201 | |||||
| 202 | This assertion has the side effect of moving to Canada should it fail. | ||||
| 203 | This is a very bad assertion since error handling should not be | ||||
| 204 | placed in an assertion, nor should it have side-effects. | ||||
| 205 | |||||
| 206 | In short, an assertion is an executable comment. For instance, instead | ||||
| 207 | of writing this | ||||
| 208 | |||||
| 209 | # $life ends with a '!' | ||||
| 210 | $life = begin_life(); | ||||
| 211 | |||||
| 212 | you'd replace the comment with an assertion which B<enforces> the comment. | ||||
| 213 | |||||
| 214 | $life = begin_life(); | ||||
| 215 | assert( $life =~ /!$/ ); | ||||
| 216 | |||||
| 217 | =for testing | ||||
| 218 | my $life = 'Whimper!'; | ||||
| 219 | ok( eval { assert( $life =~ /!$/ ); 1 }, 'life ends with a bang' ); | ||||
| 220 | |||||
| 221 | |||||
| 222 | =head1 FUNCTIONS | ||||
| 223 | |||||
| 224 | =over 4 | ||||
| 225 | |||||
| 226 | =item B<assert> | ||||
| 227 | |||||
| 228 | assert(EXPR) if DEBUG; | ||||
| 229 | assert(EXPR, $name) if DEBUG; | ||||
| 230 | |||||
| 231 | assert's functionality is effected by compile time value of the DEBUG | ||||
| 232 | constant, controlled by saying C<use Carp::Assert> or C<no | ||||
| 233 | Carp::Assert>. In the former case, assert will function as below. | ||||
| 234 | Otherwise, the assert function will compile itself out of the program. | ||||
| 235 | See L<Debugging vs Production> for details. | ||||
| 236 | |||||
| 237 | =for testing | ||||
| 238 | { | ||||
| 239 | package Some::Other; | ||||
| 240 | no Carp::Assert; | ||||
| 241 | ::ok( eval { assert(0) if DEBUG; 1 } ); | ||||
| 242 | } | ||||
| 243 | |||||
| 244 | Give assert an expression, assert will Carp::confess() if that | ||||
| 245 | expression is false, otherwise it does nothing. (DO NOT use the | ||||
| 246 | return value of assert for anything, I mean it... really!). | ||||
| 247 | |||||
| 248 | =for testing | ||||
| 249 | ok( eval { assert(1); 1 } ); | ||||
| 250 | ok( !eval { assert(0); 1 } ); | ||||
| 251 | |||||
| 252 | The error from assert will look something like this: | ||||
| 253 | |||||
| 254 | Assertion failed! | ||||
| 255 | Carp::Assert::assert(0) called at prog line 23 | ||||
| 256 | main::foo called at prog line 50 | ||||
| 257 | |||||
| 258 | =for testing | ||||
| 259 | eval { assert(0) }; | ||||
| 260 | like( $@, '/^Assertion failed!/', 'error format' ); | ||||
| 261 | like( $@, '/Carp::Assert::assert\(0\) called at/', ' with stack trace' ); | ||||
| 262 | |||||
| 263 | Indicating that in the file "prog" an assert failed inside the | ||||
| 264 | function main::foo() on line 23 and that foo() was in turn called from | ||||
| 265 | line 50 in the same file. | ||||
| 266 | |||||
| 267 | If given a $name, assert() will incorporate this into your error message, | ||||
| 268 | giving users something of a better idea what's going on. | ||||
| 269 | |||||
| 270 | assert( Dogs->isa('People'), 'Dogs are people, too!' ) if DEBUG; | ||||
| 271 | # Result - "Assertion (Dogs are people, too!) failed!" | ||||
| 272 | |||||
| 273 | =for testing | ||||
| 274 | eval { assert( Dogs->isa('People'), 'Dogs are people, too!' ); }; | ||||
| 275 | like( $@, '/^Assertion \(Dogs are people, too!\) failed!/', 'names' ); | ||||
| 276 | |||||
| 277 | =cut | ||||
| 278 | |||||
| 279 | sub assert ($;$) { | ||||
| 280 | unless($_[0]) { | ||||
| 281 | require Carp; | ||||
| 282 | Carp::confess( _fail_msg($_[1]) ); | ||||
| 283 | } | ||||
| 284 | return undef; | ||||
| 285 | } | ||||
| 286 | |||||
| 287 | |||||
| 288 | =item B<affirm> | ||||
| 289 | |||||
| 290 | affirm BLOCK if DEBUG; | ||||
| 291 | affirm BLOCK $name if DEBUG; | ||||
| 292 | |||||
| 293 | Very similar to assert(), but instead of taking just a simple | ||||
| 294 | expression it takes an entire block of code and evaluates it to make | ||||
| 295 | sure its true. This can allow more complicated assertions than | ||||
| 296 | assert() can without letting the debugging code leak out into | ||||
| 297 | production and without having to smash together several | ||||
| 298 | statements into one. | ||||
| 299 | |||||
| 300 | =for example begin | ||||
| 301 | |||||
| 302 | affirm { | ||||
| 303 | my $customer = Customer->new($customerid); | ||||
| 304 | my @cards = $customer->credit_cards; | ||||
| 305 | grep { $_->is_active } @cards; | ||||
| 306 | } "Our customer has an active credit card"; | ||||
| 307 | |||||
| 308 | =for example end | ||||
| 309 | |||||
| 310 | =for testing | ||||
| 311 | my $foo = 1; my $bar = 2; | ||||
| 312 | eval { affirm { $foo == $bar } }; | ||||
| 313 | like( $@, '/\$foo == \$bar/' ); | ||||
| 314 | |||||
| 315 | |||||
| 316 | affirm() also has the nice side effect that if you forgot the C<if DEBUG> | ||||
| 317 | suffix its arguments will not be evaluated at all. This can be nice | ||||
| 318 | if you stick affirm()s with expensive checks into hot loops and other | ||||
| 319 | time-sensitive parts of your program. | ||||
| 320 | |||||
| 321 | If the $name is left off and your Perl version is 5.6 or higher the | ||||
| 322 | affirm() diagnostics will include the code begin affirmed. | ||||
| 323 | |||||
| 324 | =cut | ||||
| 325 | |||||
| 326 | sub affirm (&;$) { | ||||
| 327 | unless( eval { &{$_[0]}; } ) { | ||||
| 328 | my $name = $_[1]; | ||||
| 329 | |||||
| 330 | if( !defined $name ) { | ||||
| 331 | eval { | ||||
| 332 | require B::Deparse; | ||||
| 333 | $name = B::Deparse->new->coderef2text($_[0]); | ||||
| 334 | }; | ||||
| 335 | $name = | ||||
| 336 | 'code display non-functional on this version of Perl, sorry' | ||||
| 337 | if $@; | ||||
| 338 | } | ||||
| 339 | |||||
| 340 | require Carp; | ||||
| 341 | Carp::confess( _fail_msg($name) ); | ||||
| 342 | } | ||||
| 343 | return undef; | ||||
| 344 | } | ||||
| 345 | |||||
| 346 | =item B<should> | ||||
| 347 | |||||
| 348 | =item B<shouldnt> | ||||
| 349 | |||||
| 350 | should ($this, $shouldbe) if DEBUG; | ||||
| 351 | shouldnt($this, $shouldntbe) if DEBUG; | ||||
| 352 | |||||
| 353 | Similar to assert(), it is specially for simple "this should be that" | ||||
| 354 | or "this should be anything but that" style of assertions. | ||||
| 355 | |||||
| 356 | Due to Perl's lack of a good macro system, assert() can only report | ||||
| 357 | where something failed, but it can't report I<what> failed or I<how>. | ||||
| 358 | should() and shouldnt() can produce more informative error messages: | ||||
| 359 | |||||
| 360 | Assertion ('this' should be 'that'!) failed! | ||||
| 361 | Carp::Assert::should('this', 'that') called at moof line 29 | ||||
| 362 | main::foo() called at moof line 58 | ||||
| 363 | |||||
| 364 | So this: | ||||
| 365 | |||||
| 366 | should($this, $that) if DEBUG; | ||||
| 367 | |||||
| 368 | is similar to this: | ||||
| 369 | |||||
| 370 | assert($this eq $that) if DEBUG; | ||||
| 371 | |||||
| 372 | except for the better error message. | ||||
| 373 | |||||
| 374 | Currently, should() and shouldnt() can only do simple eq and ne tests | ||||
| 375 | (respectively). Future versions may allow regexes. | ||||
| 376 | |||||
| 377 | =cut | ||||
| 378 | |||||
| 379 | sub should ($$) { | ||||
| 380 | unless($_[0] eq $_[1]) { | ||||
| 381 | require Carp; | ||||
| 382 | &Carp::confess( _fail_msg("'$_[0]' should be '$_[1]'!") ); | ||||
| 383 | } | ||||
| 384 | return undef; | ||||
| 385 | } | ||||
| 386 | |||||
| 387 | sub shouldnt ($$) { | ||||
| 388 | unless($_[0] ne $_[1]) { | ||||
| 389 | require Carp; | ||||
| 390 | &Carp::confess( _fail_msg("'$_[0]' shouldn't be that!") ); | ||||
| 391 | } | ||||
| 392 | return undef; | ||||
| 393 | } | ||||
| 394 | |||||
| 395 | # Sorry, I couldn't resist. | ||||
| 396 | sub shouldn't ($$) { # emacs cperl-mode madness #' sub { | ||||
| 397 | my $env_ndebug = exists $ENV{PERL_NDEBUG} ? $ENV{PERL_NDEBUG} | ||||
| 398 | : $ENV{'NDEBUG'}; | ||||
| 399 | if( $env_ndebug ) { | ||||
| 400 | return undef; | ||||
| 401 | } | ||||
| 402 | else { | ||||
| 403 | shouldnt($_[0], $_[1]); | ||||
| 404 | } | ||||
| 405 | } | ||||
| 406 | |||||
| 407 | =back | ||||
| 408 | |||||
| 409 | =head1 Debugging vs Production | ||||
| 410 | |||||
| 411 | Because assertions are extra code and because it is sometimes necessary to | ||||
| 412 | place them in 'hot' portions of your code where speed is paramount, | ||||
| 413 | Carp::Assert provides the option to remove its assert() calls from your | ||||
| 414 | program. | ||||
| 415 | |||||
| 416 | So, we provide a way to force Perl to inline the switched off assert() | ||||
| 417 | routine, thereby removing almost all performance impact on your production | ||||
| 418 | code. | ||||
| 419 | |||||
| 420 | no Carp::Assert; # assertions are off. | ||||
| 421 | assert(1==1) if DEBUG; | ||||
| 422 | |||||
| 423 | DEBUG is a constant set to 0. Adding the 'if DEBUG' condition on your | ||||
| 424 | assert() call gives perl the cue to go ahead and remove assert() call from | ||||
| 425 | your program entirely, since the if conditional will always be false. | ||||
| 426 | |||||
| 427 | # With C<no Carp::Assert> the assert() has no impact. | ||||
| 428 | for (1..100) { | ||||
| 429 | assert( do_some_really_time_consuming_check ) if DEBUG; | ||||
| 430 | } | ||||
| 431 | |||||
| 432 | If C<if DEBUG> gets too annoying, you can always use affirm(). | ||||
| 433 | |||||
| 434 | # Once again, affirm() has (almost) no impact with C<no Carp::Assert> | ||||
| 435 | for (1..100) { | ||||
| 436 | affirm { do_some_really_time_consuming_check }; | ||||
| 437 | } | ||||
| 438 | |||||
| 439 | Another way to switch off all asserts, system wide, is to define the | ||||
| 440 | NDEBUG or the PERL_NDEBUG environment variable. | ||||
| 441 | |||||
| 442 | You can safely leave out the "if DEBUG" part, but then your assert() | ||||
| 443 | function will always execute (and its arguments evaluated and time | ||||
| 444 | spent). To get around this, use affirm(). You still have the | ||||
| 445 | overhead of calling a function but at least its arguments will not be | ||||
| 446 | evaluated. | ||||
| 447 | |||||
| 448 | |||||
| 449 | =head1 Differences from ANSI C | ||||
| 450 | |||||
| 451 | assert() is intended to act like the function from ANSI C fame. | ||||
| 452 | Unfortunately, due to Perl's lack of macros or strong inlining, it's not | ||||
| 453 | nearly as unobtrusive. | ||||
| 454 | |||||
| 455 | Well, the obvious one is the "if DEBUG" part. This is cleanest way I could | ||||
| 456 | think of to cause each assert() call and its arguments to be removed from | ||||
| 457 | the program at compile-time, like the ANSI C macro does. | ||||
| 458 | |||||
| 459 | Also, this version of assert does not report the statement which | ||||
| 460 | failed, just the line number and call frame via Carp::confess. You | ||||
| 461 | can't do C<assert('$a == $b')> because $a and $b will probably be | ||||
| 462 | lexical, and thus unavailable to assert(). But with Perl, unlike C, | ||||
| 463 | you always have the source to look through, so the need isn't as | ||||
| 464 | great. | ||||
| 465 | |||||
| 466 | |||||
| 467 | =head1 EFFICIENCY | ||||
| 468 | |||||
| 469 | With C<no Carp::Assert> (or NDEBUG) and using the C<if DEBUG> suffixes | ||||
| 470 | on all your assertions, Carp::Assert has almost no impact on your | ||||
| 471 | production code. I say almost because it does still add some load-time | ||||
| 472 | to your code (I've tried to reduce this as much as possible). | ||||
| 473 | |||||
| 474 | If you forget the C<if DEBUG> on an C<assert()>, C<should()> or | ||||
| 475 | C<shouldnt()>, its arguments are still evaluated and thus will impact | ||||
| 476 | your code. You'll also have the extra overhead of calling a | ||||
| 477 | subroutine (even if that subroutine does nothing). | ||||
| 478 | |||||
| 479 | Forgetting the C<if DEBUG> on an C<affirm()> is not so bad. While you | ||||
| 480 | still have the overhead of calling a subroutine (one that does | ||||
| 481 | nothing) it will B<not> evaluate its code block and that can save | ||||
| 482 | a lot. | ||||
| 483 | |||||
| 484 | Try to remember the B<if DEBUG>. | ||||
| 485 | |||||
| 486 | |||||
| 487 | =head1 ENVIRONMENT | ||||
| 488 | |||||
| 489 | =over 4 | ||||
| 490 | |||||
| 491 | =item NDEBUG | ||||
| 492 | |||||
| 493 | Defining NDEBUG switches off all assertions. It has the same effect | ||||
| 494 | as changing "use Carp::Assert" to "no Carp::Assert" but it effects all | ||||
| 495 | code. | ||||
| 496 | |||||
| 497 | =item PERL_NDEBUG | ||||
| 498 | |||||
| 499 | Same as NDEBUG and will override it. Its provided to give you | ||||
| 500 | something which won't conflict with any C programs you might be | ||||
| 501 | working on at the same time. | ||||
| 502 | |||||
| 503 | =back | ||||
| 504 | |||||
| 505 | |||||
| 506 | =head1 BUGS, CAVETS and other MUSINGS | ||||
| 507 | |||||
| 508 | =head2 Conflicts with C<POSIX.pm> | ||||
| 509 | |||||
| 510 | The C<POSIX> module exports an C<assert> routine which will conflict with C<Carp::Assert> if both are used in the same namespace. If you are using both together, prevent C<POSIX> from exporting like so: | ||||
| 511 | |||||
| 512 | use POSIX (); | ||||
| 513 | use Carp::Assert; | ||||
| 514 | |||||
| 515 | Since C<POSIX> exports way too much, you should be using it like that anyway. | ||||
| 516 | |||||
| 517 | =head2 C<affirm> and C<$^S> | ||||
| 518 | |||||
| 519 | affirm() mucks with the expression's caller and it is run in an eval | ||||
| 520 | so anything that checks $^S will be wrong. | ||||
| 521 | |||||
| 522 | =head2 C<shouldn't> | ||||
| 523 | |||||
| 524 | Yes, there is a C<shouldn't> routine. It mostly works, but you B<must> | ||||
| 525 | put the C<if DEBUG> after it. | ||||
| 526 | |||||
| 527 | =head2 missing C<if DEBUG> | ||||
| 528 | |||||
| 529 | It would be nice if we could warn about missing C<if DEBUG>. | ||||
| 530 | |||||
| 531 | |||||
| 532 | =head1 SEE ALSO | ||||
| 533 | |||||
| 534 | L<assert.h|http://en.wikipedia.org/wiki/Assert.h> - the wikipedia | ||||
| 535 | page about C<assert.h>. | ||||
| 536 | |||||
| 537 | L<Carp::Assert::More> provides a set of convenience functions | ||||
| 538 | that are wrappers around C<Carp::Assert>. | ||||
| 539 | |||||
| 540 | L<Sub::Assert> provides support for subroutine pre- and post-conditions. | ||||
| 541 | The documentation says it's slow. | ||||
| 542 | |||||
| 543 | L<PerlX::Assert> provides compile-time assertions, which are usually | ||||
| 544 | optimised away at compile time. Currently part of the L<Moops> | ||||
| 545 | distribution, but may get its own distribution sometime in 2014. | ||||
| 546 | |||||
| 547 | L<Devel::Assert> also provides an C<assert> function, for Perl >= 5.8.1. | ||||
| 548 | |||||
| 549 | L<assertions> provides an assertion mechanism for Perl >= 5.9.0. | ||||
| 550 | |||||
| 551 | =head1 REPOSITORY | ||||
| 552 | |||||
| 553 | L<https://github.com/schwern/Carp-Assert> | ||||
| 554 | |||||
| 555 | =head1 COPYRIGHT | ||||
| 556 | |||||
| 557 | Copyright 2001-2007 by Michael G Schwern E<lt>schwern@pobox.comE<gt>. | ||||
| 558 | |||||
| 559 | This program is free software; you can redistribute it and/or | ||||
| 560 | modify it under the same terms as Perl itself. | ||||
| 561 | |||||
| 562 | See F<http://dev.perl.org/licenses/> | ||||
| 563 | |||||
| 564 | |||||
| 565 | =head1 AUTHOR | ||||
| 566 | |||||
| 567 | Michael G Schwern <schwern@pobox.com> | ||||
| 568 | |||||
| 569 | =cut | ||||
| 570 | |||||
| 571 | 1 | 3µs | return q|You don't just EAT the largest turnip in the world!|; | ||
# spent 2µs within Carp::Assert::CORE:match which was called 3 times, avg 533ns/call:
# 3 times (2µs+0s) by Carp::Assert::import at line 34, avg 533ns/call |