The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Benchmark::Thread::Size - report size of threads for different code approaches

SYNOPSIS

  use Benchmark::Thread::Size times => 5, noexport => <<'E1', export => <<'E2';
  use threads::shared ();
  E1
  use threads::shared;
  E2

DESCRIPTION

                  *** A note of CAUTION ***

 This module only functions on Perl versions 5.8.0 and later.
 And then only when threads are enabled with -Dusethreads.  It
 is of no use with any version of Perl before 5.8.0 or without
 threads enabled.

                  *************************

The Benchmark::Thread::Size module reports how much memory is used by different pieces of source code within a threaded application. This allows you to test different approaches to coding a specific threaded application or to find ways how to reduce memory usage of threads in general.

It achieves this goal by running the indicated code with a varying number of threads and asking the operating system how much memory is in use. This is an empirical process that may take quite some time on slower machines.

One or more approaches can be checked at a time, each tested 10 times by default. Each approach is compared to an empty piece of code (the reference) to allow you to easily determine how much memory each different approach has taken. Testing is done for 0, 1, 2, 5, 10, 20, 50 and 100 threads. The code you specify is only entered once in the main thread and consequently cloned to all threads when they are created (which is where it becomes very important to reduce as much as possible.

The final report is sent to STDOUT. This is an example report:

   #   (ref)        bare        full        vars         our      unique
   0    2172          +0          +0          +0          +0          +0    
   1    2624 ± 4      +4 ± 4      +4 ± 4     +27          +4 ± 4     +27    
   2    3004 ± 4      +2 ± 6      +2 ± 6     +33 ± 4      +8         +36 ± 6
   5    4126 ± 6      -2 ± 6      -3 ± 8     +29 ± 4     +10 ± 2     +27 ± 4
  10    5984 ± 8      -1 ± 8      +0 ± 4      +0 ± 6     +17 ± 4     +43 ± 6
  20    9694 ± 4     +15 ± 4     +15 ± 2     +13 ± 6     +32 ± 6     +58 ± 6
  50   20832 ± 4     +51 ±10     +50 ± 8     +50 ± 8     +68 ±12     +96 ± 6
 100   39392 ± 8    +106 ±10    +156 ±12    +108 ±10    +131 ±10    +155 ±12
 
 ==== bare ========================================================
 $VERSION = '0.01';
 
 ==== full ========================================================
 $main::VERSION = '0.01';
 
 ==== vars ========================================================
 use vars qw($VERSION);
 $VERSION = '0.01';
 
 ==== our =========================================================
 our $VERSION = '0.01';
 
 ==== unique ======================================================
 our $VERSION : unique = '0.01';
 
 ==================================================================

The first column shows the reference amount (the amount of memory used without adding any specific code). All other columns show the difference with the amounts from the first column.

The sizes given are the numbers that were obtained from the system for the size of the process. This is usually in Kbytes but could be anything, depending on how the information about the memory usage is obtained.

Since starting threads can have non-deterministic effects on the amount of memory used, each number of threads is tried 10 times by default. The average of the amount of memory used is shown. If the amount was not always the same for the same piece of code and number of threads, a deviation (in the form ±10) is also shown.

So, what does this report tell us? That it seems that it is better to use a bare $VERSION in a module in a Perl module that is going to be used with threads. And that contrary from what you would like to believe, the ":unique" attribute does not save any memory: it even causes threads to use more memory. And that strangely enough using a fully qualified $module::VERSION seems to be equivalent to using a bare $VERSION upto 50 threads. At 100 threads however, the fully qualified $module::VERSION seems to use as much as with the ":unique" attribute. Who knows what's going on there.

SUBROUTINES

There are no subroutines to call: all values need to be specified with the use command.

WHAT IT DOES

This module started life as just a number of scripts. In order to facilitate distribution I decided to bundle them together into this module. So, what does happen exactly when you execute this module?

create ramthread

This is the main script that does the testing. It collects the data that is written out to STDOUT by ramthread1.

create ramthread1

This is the script that gets called for each seperate test. It creates a special test-script "_test_ramthread" for each test and each number of threads to be checked (to avoid artefacts from previous runs in the same interpreter), then measures the size of memory for each number of threads running simultaneously and writes out the result to STDOUT.

create files for each piece of code

For several (historical) reasons, a seperate file is created for each piece of code given. These files are used by ramthread1 to measure the amount of memory used. The identification of the code is used as the filename, so be sure that this will not overwrite stuff you might need later.

The actual code is functionally equivalent to:

 use threads ();
 # your code comes here
 for ($i = 0; $i < (number of threads to test) ; $i++) {
   threads->new( sub {sleep( 86400 )} );
 }
run ramthread

The ramthread script is then run with the appropriate parameters. The output is sent to STDERR (progress indication) and STDOUT (final report).

remove all files that were created

Then all of the files (including the ramthread and ramthread1 script) are removed, so that no files are left behind.

All files are created in the current directory. This may not be the best place, but it was the easiest thing to code.

HOW TO MEASURE SIZE?

Currently the size of the process is measured by doing a:

  ps --no-heading -o rss $pid

However, this may not be as portable as I would like. If you would like to use Benchmark::Thread::Size on your system and the above doesn't work, please send me a string for your system that writes out the size of the given process to STDOUT and the condition that should be used to determine that that string should be used instead of the above default.

AUTHOR

Elizabeth Mattijsen, <liz@dijkmat.nl>.

Please report bugs to <perlbugs@dijkmat.nl>.

COPYRIGHT

Copyright (c) 2002 Elizabeth Mattijsen <liz@dijkmat.nl>. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

Benchmark.

1 POD Error

The following errors were encountered while parsing the POD:

Around line 310:

Non-ASCII character seen before =encoding in '±'. Assuming CP1252