Memchmark - Check memory consumption


Memchmark documentation Contained in the Memchmark distribution.

Index


Code Index:

NAME

Top

Memchmark - Check memory consumption

SYNOPSIS

Top

  use Memchmark qw(cmpthese);
  my @data = map { rand($_) } 0..10000;
  cmpthese( -init => sub { my @s =  @data },
            nsort => sub { my @s = sort { $a <=> $b } @data },
            rnsort => sub { my @s = sort { -($a <=> $b) } @data } );

DESCRIPTION

Top

Memchmark is similar to Benchmark but compares memory comsumptions instead of times.

To measure memory comsumption for some subroutine, Memchmark forks a new process to run the sub and then monitors its memory usage every 100ms (aprox.) recording the maximum amount used.

The obtained quantities are only approximate, you can expect errors around 30%.

It is not reliable for small quantities (useles for anything below 1MB).

EXPORT_OK

These are the subroutines available from Memchmark:

cmpthese(foo => sub { ... }, bar => sub { ... }, ...)

prints statistics about the memory comsumption for the different subs.

An entry with the name -init can be used for a do nothing entry which memory comsumption will be substracted to the results from the rest of the tests.

memchmark { &code() };

returns the memory used by &code().

BUGS

Top

This is a very early release, alpha software, expect bugs on it.

The API is not stable. I will change it when required for improvement.

It will not work under Windows (ever).

SEE ALSO

Top

Benchmark, Proc::ProcessTable, Proc::ProcessTable::Process, fork.

AUTHOR

Top

Salvador Fandiño, <sfandino@yahoo.com>

COPYRIGHT AND LICENSE

Top


Memchmark documentation Contained in the Memchmark distribution.

package Memchmark;

our $VERSION = '0.01';

use 5.008;

use strict;
use warnings;

require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(memchmark cmpthese);

use Carp;
use Proc::ProcessTable;
use POSIX qw(:sys_wait_h);
use Time::HiRes qw(usleep);

sub _find_process {
    my $pid = shift || $$;
    my $p=Proc::ProcessTable->new;
    for (@{$p->table}) {
	return $_ if $_->pid == $pid;
    }
}

sub memchmark (&) {
    my $sub = shift;
    ref $sub eq 'CODE'
	or croak "invalid type for memchmark arg ($sub), CODE ref expected";
    my $size0 = _find_process->size;
    my $pid = fork;

    if (defined $pid and $pid==0) {
	eval { &$sub() };
	$@ and print STDERR $@;
	sleep 1;
	exit(0);
    }
    defined $pid or croak "unable to fork";

    my $ecode;
    my $size1 = $size0;
    do {
	usleep(100000);
	my $size = _find_process($pid)->size;
	$size1 = $size if $size > $size1;
	$ecode = waitpid($pid, WNOHANG);
    } until $ecode > 0;
    return $size1-$size0;
}

sub cmpthese {
    my %test = @_;
    my $init = delete $test{-init} || sub {};
    my $size0 = &memchmark($init);
    my %size;
    for my $test (sort keys %test) {
	$test=~/^-/ and croak "invalid test name";
	$size{$test} = &memchmark($test{$test}) - $size0;
	print "test: $test, memory used: $size{$test} bytes\n";
    }
}

1;

__END__