Perl Language

Memory usage optimization

Reading files: foreach vs. while

When reading a potentially large file, a while loop has a significant memory advantage over foreach. The following will read the file record by record (by default, “record” means “a line”, as specified by $/), assigning each one to $_ as it is read:

while(<$fh>) {
    print;
}

The diamond operator does some magic here to make sure the loop only terminates at end-of-file and not e.g. on lines that contain only a “0” character.

The following loop seems to work just the same, however it evaluates the diamond operator in list context, causing the entire file to be read in one go:

foreach(<$fh>) {
    print;
}

If you are operating on one record at a time anyway, this can result in a huge waste of memory and should thus be avoided.

Processing long lists

If you have a list in memory already, the straightforward and usually sufficient way to process it is a simple foreach loop:

foreach my $item (@items) {
    ...
}

This is fine e.g. for the common case of doing some processing on $item and then writing it out to a file without keeping the data around. However, if you build up some other data structure from the items, a while loop is more memory efficient:

my @result;
while(@items) {
    my $item = shift @items;
    push @result, process_item($item);
}

Unless a reference to $item directly ends up in your result list, items you shifted off the @items array can be freed and the memory reused by the interpreter when you enter the next loop iteration.


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow