Isaac Clarke
Isaac Clarke

Reputation: 727

Is « my » overwriting memory when called in a loop?

A simple but relevant question: Is « my » overwriting memory when called in a loop?
For instance, is it "better" (in terms of memory leaks, performance, speed) to declare it outside of 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 made that code up, it's not meant to do anything nor be used - as it is - in real life)
Will Perl allocate a new space in memory for each and every one of the for iterations ?

Upvotes: 2

Views: 739

Answers (5)

Sinan Ünür
Sinan Ünür

Reputation: 118138

You can benchmark the difference between the two uses using the Benchmark module which is made for these types of micro-benchmarking comparisons:

#!/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%      --

Predictably, the difference is less pronounced when the body of the loop is executed only once.

That said, I would not declare $x outside the loop unless I needed outside the loop what is assigned to $x inside the loop.

Upvotes: 2

brian d foy
brian d foy

Reputation: 132822

These are things you aren't supposed to think about with a dynamic language such as Perl. Even though you might get an answer about what the current implementation does, that's not a feature and it isn't something you should rely on.

Define your variables in the shortest scope possible.

However, to be merely curious, you can use the Devel::Peek module to cheat a bit to see the internal (not physical) memory address:

 use Devel::Peek;

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

In this small case, the address ends up being the same. That's no 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

Upvotes: 3

Ether
Ether

Reputation: 53976

You are totally safe using "my" inside a for loop or any other block. In general you don't have to worry about memory leaks in perl, but you would be equally safe in this circumstance with a non-garbage-collecting language like C++. A normal variable is deallocated at the end of the block in which it has scope.

Upvotes: 1

innaM
innaM

Reputation: 47839

Aamir already told you what will happen.

I recommend to stick to the second version unless there is some reason to use the first. You don't want to care about the previous state of $variable. It's simplest to start each iteration with a fresh variable. And if variable contains a reference you might actually shoot yourself in the foot if you push that onto an array.

Edit:

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

Upvotes: 9

Aamir
Aamir

Reputation: 15566

From your examples above:

  1. A new space for variable will not be allocated everytime, the previous one will be used.

  2. A new space will be allocated for every iteration of loop and will be de-allocated as well in the same iteration.

Upvotes: 3

Related Questions