1Test::MemoryGrowth(3) User Contributed Perl DocumentationTest::MemoryGrowth(3)
2
3
4

NAME

6       "Test::MemoryGrowth" - assert that code does not cause growth in memory
7       usage
8

SYNOPSIS

10          use Test::More;
11          use Test::MemoryGrowth;
12
13          use Some::Class;
14
15          no_growth {
16             my $obj = Some::Class->new;
17          } 'Constructing Some::Class does not grow memory';
18
19          my $obj = Some::Class->new;
20          no_growth {
21             $obj->do_thing;
22          } 'Some::Class->do_thing does not grow memory';
23
24
25          #### This test will fail ####
26          my @list;
27          no_growth {
28             push @list, "Hello world";
29          } 'pushing to an array does not grow memory';
30
31          done_testing;
32

DESCRIPTION

34       This module provides a function to check that a given block of code
35       does not result in the process consuming extra memory once it has
36       finished. Despite the name of this module it does not, in the strictest
37       sense of the word, test for a memory leak: that term is specifically
38       applied to cases where memory has been allocated but all record of it
39       has been lost, so it cannot possibly be reclaimed. While the method
40       employed by this module can detect such bugs, it can also detect cases
41       where memory is still referenced and reachable, but the usage has grown
42       more than would be expected or necessary.
43
44       The block of code will be run a large number of times (by default
45       10,000), and the difference in memory usage by the process before and
46       after is compared. If the memory usage has now increased by more than
47       one byte per call, then the test fails.
48
49       In order to give the code a chance to load initial resources it needs,
50       it will be run a few times first (by default 10); giving it a chance to
51       load files, AUTOLOADs, caches, or any other information that it
52       requires. Any extra memory usage here will not count against it.
53
54       This simple method is not a guaranteed indicator of the absence of
55       memory resource bugs from a piece of code; it has the possibility to
56       fail in both a false-negative and a false-positive way.
57
58       False Negative
59           It is possible that a piece of code causes memory usage growth that
60           this module does not detect. Because it only detects memory growth
61           of at least one byte per call, it cannot detect cases of linear
62           memory growth at lower rates than this. Most memory usage growth
63           comes either from Perl-level or C-level bugs where memory objects
64           are created at every call and not reclaimed again.  (These are
65           either genuine memory leaks, or needless allocations of objects
66           that are stored somewhere and never reclaimed). It is unlikely such
67           a bug would result in a growth rate smaller than one byte per call.
68
69           A second failure case comes from the fact that memory usage is
70           taken from the Operating System's measure of the process's Virtual
71           Memory size, so as to be able to detect memory usage growth in C
72           libraries or XS-level wrapping code, as well as Perl functions.
73           Because Perl does not aggressively return unused memory to the
74           Operating System, it is possible that a piece of code could use un-
75           allocated but un-reclaimed memory to grow into; resulting in an
76           increase in its requirements despite not requesting extra memory
77           from the Operating System.
78
79       False Positive
80           It is possible that the test will claim that a function grows in
81           memory, when the behaviour is in fact perfectly normal for the code
82           in question. For example, the code could simply be some function
83           whose behaviour is required to store extra state; for example,
84           adding a new item into a list. In this case it is in fact expected
85           that the memory usage of the process will increase.
86
87       By careful use of this test module, false indications can be minimised.
88       By splitting tests across many test scripts, each one can be started in
89       a new process state, where most of the memory assigned from the
90       Operating System is in use by Perl, so anything extra that the code
91       requires will have to request more. This should reduce the false
92       negative indications.
93
94       By keeping in mind that the module simply measures the change in
95       allocated memory size, false positives can be minimised, by not
96       attempting to assert that certain pieces of code do not grow in memory,
97       when in fact it would be expected that they do.
98
99   Devel::Gladiator Integration
100       Since version 0.04.
101
102       If Devel::Gladiator is installed, this test module will use it as a
103       second potential source of detecting memory growth. A walk of the Perl
104       memory heap is taken before running the code, in order to count the
105       number of every kind of object present. This is then compared to a
106       second count taken afterwards. Any object types that have increased by
107       at least one per call are reported.
108
109       For example, the output might contain the following extra lines of
110       diagnostic output:
111
112          # Growths in arena object counts:
113          #   ARRAY 1735 -> 11735 (1.00 per call)
114          #   HASH 459 -> 10459 (1.00 per call)
115          #   REF 1387 -> 21387 (2.00 per call)
116          #   REF-ARRAY 163 -> 10163 (1.00 per call)
117          #   REF-HASH 66 -> 10066 (1.00 per call)
118          #   WithContainerSlots 10 -> 10010 (1.00 per call)
119
120   Devel::MAT Integration
121       If Devel::MAT is installed, this test module will use it to dump the
122       state of the memory after a failure. It will create a .pmat file named
123       the same as the unit test, but with the trailing .t suffix replaced
124       with -TEST.pmat where "TEST" is the number of the test that failed (in
125       case there was more than one). It will then run the code under test one
126       more time, before writing another file whose name is suffixed with
127       -TEST-after.pmat.  This pair of files may be useful for differential
128       analysis.
129

FUNCTIONS

131   no_growth
132          no_growth { CODE } %opts, $name
133
134       Assert that the code block does not consume extra memory.
135
136       Takes the following named arguments:
137
138       calls => INT
139               The number of times to call the code during growth testing.
140
141       burn_in => INT
142               The number of times to call the code initially, before watching
143               for memory usage.
144

TODO

146       •       Don't be Linux Specific
147
148               Currently, this module uses a very Linux-specific method of
149               determining process memory usage (namely, by inspecting
150               /proc/self/status). This should really be fixed to some OS-
151               neutral abstraction. Currently I am unaware of a simple
152               portable mechanism to query this. Patches very much welcome. :)
153

AUTHOR

155       Paul Evans <leonerd@leonerd.org.uk>
156
157
158
159perl v5.36.0                      2022-07-22             Test::MemoryGrowth(3)
Impressum