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

NAME

6       Test::LeakTrace::JA - メモリリークを追跡する
7

VERSION

9       This document describes Test::LeakTrace version 0.16.
10

SYNOPSIS

12               use Test::LeakTrace;
13
14               # simple report
15               leaktrace{
16                       # ...
17               };
18
19               # verbose output
20               leaktrace{
21                       # ...
22               } -verbose;
23
24               # with callback
25               leaktrace{
26                       # ...
27               } sub {
28                       my($ref, $file, $line) = @_;
29                       warn "leaked $ref from $file line\n";
30               };
31
32               my @refs = leaked_refs{
33                       # ...
34               };
35               my @info = leaked_info{
36                       # ...
37               };
38
39               my $count = leaked_count{
40                       # ...
41               };
42
43               # standard test interface
44               use Test::LeakTrace;
45
46               no_leaks_ok{
47                       # ...
48               } "description";
49
50               leaks_cmp_ok{
51                       # ...
52               } '<', 10;
53

DESCRIPTION

55       PerlのGCはリファレンスカウンタを用いたものなので,オブジェクトが開放されるタイミングが明確であることや体感速度が高速であることなど数々の利点があります。
56       その一方で,循環参照を開放できないこと,Cレベルでの操作でミスしやすいなど,問題点がいくつかあります。それらの問題点のほとんどはメモリリークに関することですから,メモリリークを追跡することは非常に重要な課題です。
57
58       "Test::LeakTrce"はメモリリークを追跡するためのいくつかのユーティリティと"Test::Builder"ベースのテスト関数を提供します。このモジュールはPerlのメモリアロケーションシステムであるアリーナを走査するため,SVに関することであれば与えられたコードのどんなメモリリークでも検出できます。つまり,Perlレベルでの循環参照を始めとして,XSモジュールやPerl自身のバグによるメモリリークを追跡することができます。
59
60       ここでリークとは,特定のスコープ内で新たに作成されて,そのスコープ終了後にも残っている値を意味します。これは,新たに作成されたグローバルな値やPerlが暗黙のうちに作成するキャッシュの値も含みます。たとえば,リーク追跡を行っている最中に新たに名前つきサブルーチンを定義すれば,それはリークとみなされます。また,継承したメソッドを呼び出したり,オブジェクトを作成したりするだけで様々なキャッシュが生成され,リークが報告される可能性があります。
61

INTERFACE

63   Exported functions
64       "leaked_info { BLOCK }"
65
66       BLOCKを実行し,追跡結果をリストで返します。
67       結果はリークした値のリファレンス,ファイル名,行番号の三要素を持つ配列,つまり"[$ref,
68       $file, $line]"のリストとなっています。
69
70       なお,この関数はPerl内部で使用する値を返す可能性があります。そのような内部用の値を変更するとPerl実行環境に致命的な影響を与える可能性があるので注意してください。また,配列やハッシュの要素として,リファレンスではない配列やハッシュそれ自体が含まれる可能性があります。そのような値は通常Perlレベルで操作することができません。たとえば"Data::Dumper"などで出力することはできません。
71
72       "leaked_refs { BLOCK }"
73
74       BLOCKを実行し,リークしたSVのリファレンスのリストを返します。
75
76       "map{ $_->[0] } leaked_info{ BLOCK }"と同じですが,より高速です。
77
78       "leaked_count { BLOCK }"
79
80       BLOCKを実行し,リークしたSVのリファレンスの個数を返します。
81
82       "leaked_info()"と"leaked_refs()"もスカラコンテキストでは個数を返しますが,
83       "leaked_count()"はコンテキストに依存しません。
84
85       "leaktrace { BLOCK } ?($mode | \&callback)"
86
87       BLOCKを実行し,その中で起きたメモリリークを*STDERRに報告します。
88
89       メモリリークの報告は$modeで指定したモードに従います。
90       受け付ける$modeは以下の通りです:
91
92       -simple
93           デフォルトのモードです。リークしたSVの型とアドレス,ファイル名,行番号を報告します。
94
95       -sv_dump
96           -simpleに加えて,"sv_dump()"でSVの中身をダンプします。
97           これは,"Devel::Peek::Dump()"の出力とほぼ同じです。
98
99       -lines
100           -simpleに加えて,リークしていると見られる行の周辺を出力します。
101
102       -verbose
103           -simple-sv_dump-linesの全てを出力します。
104
105       より細かな制御のためにコールバックを指定することもできます。
106       \&callbackはリークしたSV毎に呼び出され,その引数はリークしたSVのリファレンス,ファイル名,行番号の3つです。
107
108       "no_leaks_ok { BLOCK } ?$description"
109
110       BLOCKにメモリリークがないことテストします。
111       これは"Test::Builder"ベースのテスト関数です。
112
113       なお,BLOCKは複数回実行されます。これは,初回の実行でキャッシュを用意する可能性を考慮するためです。
114
115       "leaks_cmp_ok { BLOCK } $cmp_op, $count, ?$description"
116
117       BLOCKのメモリリーク数と特定の数値を比較するテストを行います。
118       これは"Test::Builder"ベースのテスト関数です。
119
120       なお,BLOCKは複数回実行されます。これは,初回の実行でキャッシュを用意する可能性を考慮するためです。
121
122   Script interface
123       "Devel::LeakTrace"と同様に,スクリプトのリーク追跡のために"Test::LeakTrace::Script"が提供されます。"use
124       Test::LeakTrace::Script"宣言の引数は"leaktrace()"と同じです。
125
126               $ TEST_LEAKTRACE=-sv_dump perl -MTest::LeakTrace::Script script.pl
127               $ perl -MTest::LeakTrace::Script=-verbose script.pl
128
129               #!perl
130               # ...
131
132               use Test::LeakTrace::Script sub{
133                       my($ref, $file, $line) = @_;
134                       # ...
135               };
136
137               # ...
138

EXAMPLES

140   Testing modules
141       以下はモジュールのメモリリークをチェックするテストスクリプトのテンプレートです。
142
143               #!perl -w
144               use strict;
145               use constant HAS_LEAKTRACE => eval{ require Test::LeakTrace };
146               use Test::More HAS_LEAKTRACE ? (tests => 1) : (skip_all => 'require Test::LeakTrace');
147               use Test::LeakTrace;
148
149               use Some::Module;
150
151               leaks_cmp_ok{
152                       my $o = Some::Module->new();
153                       $o->something();
154                       $o->something_else();
155               } '<', 1;
156

GUTS

158       "Test::LeakTrace"はアリーナを走査します。アリーナとは,Perlが作成するSVのためのメモリアロケーションシステムであり,sv.cで実装されています。
159       アリーナの走査にはsv.cにある"S_visit()"のコードを元にしたマクロを用いています。
160
161       さて,アリーナを走査すれば,メモリリークの検出そのものは簡単にできるように思えます。まず,コードブロックを実行する前に一度アリーナを走査し,全てのSVに「使用済み」の印を付けておきます。次に,コードブロック実行後にもう一度アリーナを走査し,使用済みの印がついていないSVがあれば,それはコードブロック内で作成され,開放されなかったSVだと考えます。あとはそれを報告するだけです。実際には,SVに対して使用済みの印を付けるスペースがないため,インサイドアウト法を応用して外部のコンテナに使用済みの印を保存します。
162       これを仮にPerlコードで書くと以下のようになります。
163
164               my %used_sv;
165               foreach my $sv(@ARENA){
166                       $used_sv{$sv}++;
167               }
168               $block->();
169
170               my @leaked
171               foreach my $sv(@ARENA){
172                       if(not exists $used_sv{$sv}){
173                               push @leaked, $sv;
174                       }
175               }
176               say 'leaked count: ', scalar @leaked;
177
178       リークしたSVを得るだけならこの方法で十分です。実際,"leaked_refs()"と"leaked_count()"はこのような方法でリークしたSVやその個数を調べています。
179
180       しかし,リークしたSVのステートメントの情報,つまりファイル名や行番号を得るためにはこれだけでは不十分です。Perl
181       5.10以降にはSVが作成されたときのステートメント情報を追跡する機能があるのですが,この機能を利用するためには,コンパイラオプションとしてに"-DDEBUG_LEAKING_SCALARS"を与えてPerlをビルドしなければなりません。
182
183       そこで,"Test::LeakTrace"では拡張可能な"PL_runops"を利用して,Perl
184       VMがOPコードを実行する1ステートメント毎にアリーナを走査し,ステートメント情報を記録します。これは,1ステートメント毎にマーク&スイープのような処理を行うのに等しく,非常に時間が掛かります。しかし,Perlを特殊な条件の下でビルドする必要もなく,バージョンに依存した機能もほとんど使用しないため,多くの環境で動かすことができます。
185
186       また,"no_leaks_ok()"のようなテスト関数はまず"leaked_count()"でリークしたSVの個数を得てから,必要に応じてリークした位置を特定するために"leaktrace()"を実行するため,テストが成功する限りは時間の掛かる追跡処理はしません。
187

DEPENDENCIES

189       Perl 5.8.1 or later, and a C compiler.
190

CAVEATS

192       "Test::LeakTrace"は"Devel::Cover"と一緒に動かすことはできません。
193       したがって,"Devel::Cover"の元で動いていることが検出されると,テスト関数は何も行わずにテストをパスさせます。
194

BUGS

196       No bugs have been reported.
197
198       Please report any bugs or feature requests to the author.
199

SEE ALSO

201       Devel::LeakTrace.
202
203       Devel::LeakTrace::Fast.
204
205       Test::TraceObject.
206
207       Test::Weak.
208
209       For guts:
210
211       perlguts.
212
213       perlhack.
214
215       sv.c.
216

AUTHOR

218       Goro Fuji <gfuji(at)cpan.org>.
219
221       Copyright (c) 2009, Goro Fuji. Some rights reserved.
222
223       This library is free software; you can redistribute it and/or modify it
224       under the same terms as Perl itself.
225
226
227
228perl v5.32.0                      2020-07-28            Test::LeakTrace::JA(3)
Impressum