in reply to Emptying (and refilling) an array.

It looks like your trying to benchmark preallocation, but you failed at doing that. The array already has at least 101 elements allocated before you attempt to initialize it. The array is not freed from pass to pass. That means you're basically benchmarking the fastest way to do nothing. Obviously, actually doing nothing ("my @working;") will be at least as fast as everything else.

"my @working = undef" doesn't make sense. It assigns one element to the array. Maybe you were thinking of "undef @working" which frees the internal buffer of the array?

It's curious that assign_length and x_with_value preallocate 100 elements then proceed to store 101 elements. Not that it matters, because the array already has at least 101 elements from the previous pass of the loop.

It's curious that your didn't test "$#working = 100;" to preallocate the array. Not that it matters, because the array already has at least 101 elements from the previous pass of the loop.

"my @working = ();" can be written as just "my @working;"

Replies are listed 'Best First'.
Re^2: Emptying (and refilling) an array.
by DStaal (Chaplain) on Jan 12, 2009 at 16:22 UTC

    Thanks for the critique: I've updated my benchmarks with something hopefully a little better.

    Yes, I was thinking of undef @working. Fixed.

    I kept meaning to get those off-by-one errors matched up, but I knew it didn't actually make a difference... My bad.

    $#working = 100; actually isn't part of what I was looking at: I was specifically looking at an array that (usually) already has a length.

    my @working; is the same as my @working = (); when @working doesn't exist. Once it does, the latter does seem to actually clear the array. (As far as I can tell: My code that should throw errors if it didn't.)

      my @working; is the same as my @working = (); when @working doesn't exist. Once it does, the latter does seem to actually clear the array.

      Not all. It's already cleared (but not deallocated) at the end of the last pass by the run-time effect of my. my @working = (); will never result in something different than my @working;.

      (my @working = () if $x; is not necessarily the same as my @working if $x;, but that code is a buggy to begin with.)

      Are you confusing my @working; with just @working;? I noticed you removed the "my". Removing the "my" is silly. It's not something you should do. At least add this test, please:

      'my' => 'my @working; $working[$_] = $_ foreach ( 0...1 +00 );',
      If you want to benchmark explicitely clearing of the array, you should do that - and not start with a "new" array (although, behind the scenes, the array isn't quite new) each time. Move the declaration of the array outside of the loops. Something like:
      our @working; cmpthese -20, { one => '@working = (); $working[$_] = $_ foreach 0 .. 100', ... };
      Of course, if you're going to fill in all the elements anyway, why bother clearing them?