"My" memory overwrite when called in a loop?

Simple but relevant question: "my" memory overwrite when called in a loop?
For example, it is "better" (in terms of memory leaks, performance, speed) to declare it outside the loop:

my $variable;
for my $number ( @array ) {
    $variable = $number * 5;
    _sub($variable);   
}

      

Or should I declare it inside the loop:

for my $number ( @array ) {
    my $variable = $number * 5;
    _sub($variable);
}

      

(I just did this code, it didn't want to do or use anything - as it is - in real life)
Will Perl allocate new memory space for each iteration for iterations?

+2


source to share


5 answers


Aamir has already told you what will happen.

I recommend sticking with the second version unless there is a reason to use the first. You don't want to worry about the previous condition $variable

. The easiest way is to start each iteration with a fresh variable. And if the variable contains a reference, you can shoot yourself in the foot if you push it to the array.



Edit:

Yes, there is a performance hit. Using the recycled variable will be faster. However, heck, how much faster it will be, as it will depend on your specific situation. No matter how much faster it happens, always remember: Premature optimization is the root of all evil .

+9


source


From the examples above:



  • The new space for the variable will not be allocated each time, the previous one will be used.

  • New space will be allocated for each iteration of the loop and will also be allocated in the same iteration.

+3


source


These are things you shouldn't be thinking about with a dynamic language like Perl. Even if you can get an answer as to what the current implementation is doing, it is not a function and you should not rely on it.

Define your variables in the shortest scope possible.

However, to be just curious, you can use the Devel :: Peek module to cheat a little to see the inner (not physical):

 use Devel::Peek;

 foreach ( 0 .. 5 ) {
      my $var = $_;
      Dump( $var );
      }

      

In this small case, the address ends up being the same. This does not guarantee that it will always be the same for different situations or even the same program:

SV = IV (0x9ca968) at 0x9ca96c
  REFCNT = 1
  FLAGS = (PADMY, IOK, pIOK)
  IV = 0
SV = IV (0x9ca968) at 0x9ca96c
  REFCNT = 1
  FLAGS = (PADMY, IOK, pIOK)
  IV = 1
SV = IV (0x9ca968) at 0x9ca96c
  REFCNT = 1
  FLAGS = (PADMY, IOK, pIOK)
  IV = 2
SV = IV (0x9ca968) at 0x9ca96c
  REFCNT = 1
  FLAGS = (PADMY, IOK, pIOK)
  IV = 3
SV = IV (0x9ca968) at 0x9ca96c
  REFCNT = 1
  FLAGS = (PADMY, IOK, pIOK)
  IV = 4
SV = IV (0x9ca968) at 0x9ca96c
  REFCNT = 1
  FLAGS = (PADMY, IOK, pIOK)
  IV = 5
+3


source


You can compare the difference between these two uses with the Benchmark module that is generated for these types of comparisons using micro-benchmarking:

#!/usr/bin/perl

use strict;
use warnings;

use Benchmark qw( cmpthese );

sub outside {
    my $x;

    for my $y ( 1 .. 1_000_000 ) {
        $x = $y;
    }

    return;
}

sub inside {
    for my $y ( 1 .. 1_000_000 ) {
        my $x = $y;
    }

    return;
}

cmpthese -1 => {
    inside => \&inside,
    outside => \&outside,
};

      

Results on my Windows XP SP3 laptop:

          Rate inside outside
inside 4.44 / s - -25%
outside 5.91 / s 33% -

As expected, the difference is less pronounced when the loop body is only executed once.

However, I would not declare $x

outside the loop unless I needed outside of the loop what is assigned $x

inside the loop.

+2


source


You are completely safe using "mine" inside a for loop or any other block. In general, you don't need to worry about memory leaks in perl, but in this case, you will be equally safe with a non-garbage-related language like C ++. A normal variable is freed at the end of the block in which it has scope.

+1


source







All Articles