perlperf > 5.26.1 との差分

perlperf 5.26.1 と 5.38.0 の差分

11
2=encoding euc-jp
2=encoding utf8
33
44=head1 NAME
55
66=begin original
77
88perlperf - Perl Performance and Optimization Techniques
99
1010=end original
1111
1212perlperf - Perl の性能と最適化のテクニック
1313
1414=head1 DESCRIPTION
1515
1616=begin original
1717
1818This is an introduction to the use of performance and optimization techniques
1919which can be used with particular reference to perl programs. While many perl
2020developers have come from other languages, and can use their prior knowledge
2121where appropriate, there are many other people who might benefit from a few
2222perl specific pointers. If you want the condensed version, perhaps the best
2323advice comes from the renowned Japanese Samurai, Miyamoto Musashi, who said:
2424
2525=end original
2626
2727これは、perl プログラムへの個々の参考として使える性能と最適化の
2828テクニックの使用の紹介です。
2929多くの perl 開発者は他の言語から来ていて、適切な場所では以前の知識を
3030使えますが、いくつかの perl 特有の点から利益を得られるかもしれない多くの
3131人もいます。
3232要約版がほしいなら、おそらく最良のアドバイスは、有名な日本の侍である
3333宮本武蔵の言葉でしょう:
3434
3535=begin original
3636
3737 "Do Not Engage in Useless Activity"
3838
3939=end original
4040
4141 「役に立ぬ事をせざる事」
4242
4343=begin original
4444
4545in 1645.
4646
4747=end original
4848
4949と 1645 年に記しています。
5050
5151=head1 OVERVIEW
5252
5353(概観)
5454
5555=begin original
5656
5757Perhaps the most common mistake programmers make is to attempt to optimize
5858their code before a program actually does anything useful - this is a bad idea.
5959There's no point in having an extremely fast program that doesn't work. The
6060first job is to get a program to I<correctly> do something B<useful>, (not to
6161mention ensuring the test suite is fully functional), and only then to consider
6262optimizing it. Having decided to optimize existing working code, there are
6363several simple but essential steps to consider which are intrinsic to any
6464optimization process.
6565
6666=end original
6767
6868おそらくプログラマが犯す最もよくある間違いは、プログラムが実際に有用な
6969ものになる前にコードを最適化しようとすることです - これは悪い考えです。
7070うまく動かないすごく高速なプログラムには意味がありません。
7171最初の仕事はプログラムが I<正しく> 何か B<有用なこと> をするようにして
7272(テストスイートが完全に機能することを保証するという意味ではありません)、
7373それからそれを最適化することだけを考えます。
7474既に動作するコードを最適化すると決めたら、あらゆる最適化プロセスに内在すると
7575考えられる、いくつかの単純だけれども本質的なステップがあります。
7676
7777=head2 ONE STEP SIDEWAYS
7878
7979(一歩横に)
8080
8181=begin original
8282
8383Firstly, you need to establish a baseline time for the existing code, which
8484timing needs to be reliable and repeatable. You'll probably want to use the
8585C<Benchmark> or C<Devel::NYTProf> modules, or something similar, for this step,
8686or perhaps the Unix system C<time> utility, whichever is appropriate. See the
8787base of this document for a longer list of benchmarking and profiling modules,
8888and recommended further reading.
8989
9090=end original
9191
9292まず、既にあるコードの基準になる時間を決定する必要があります; ここで
9393時間は信頼性があって再現可能であるものです。
9494おそらく C<Benchmark> または C<Devel::NYTProf> モジュールやあるいは
9595似たようなものか、またはおそらく Unix システムの
9696C<time> ユーティリティのような、適切なものを使いたいでしょう。
9797ベンチマークとプロファイルのモジュールのより長い一覧および、さらに読むための
9898お勧めについてはこの文書の末尾を見てください。
9999
100100=head2 ONE STEP FORWARD
101101
102102(一歩前に)
103103
104104=begin original
105105
106106Next, having examined the program for I<hot spots>, (places where the code
107107seems to run slowly), change the code with the intention of making it run
108108faster. Using version control software, like C<subversion>, will ensure no
109109changes are irreversible. It's too easy to fiddle here and fiddle there -
110110don't change too much at any one time or you might not discover which piece of
111111code B<really> was the slow bit.
112112
113113=end original
114114
115115次に、プログラムの中の I<ホットスポット> (コード中で実行が遅くなっているらしい
116116場所) を調べ、より早く実行できるようにコードを変更します。
117117C<subversion> のようなバージョンコントロールソフトを使って、全ての変更を
118118差し戻せるようにします。
119119あちこちをいじるのはとても簡単です - 一度にたくさん変更しないようにします;
120120さもないとどこコードが B<本当に> 遅かったのかが分からなくなるかもしれません。
121121
122122=head2 ANOTHER STEP SIDEWAYS
123123
124124(もう一歩横に)
125125
126126=begin original
127127
128128It's not enough to say: "that will make it run faster", you have to check it.
129129Rerun the code under control of the benchmarking or profiling modules, from the
130130first step above, and check that the new code executed the B<same task> in
131131I<less time>. Save your work and repeat...
132132
133133=end original
134134
135135次のように言うだけでは不十分です: 「これでもっと速く動作する」;
136136これをチェックする必要があります。
137137上述の最初のステップから、ベンチマークやプロファイリングのモジュールの
138138制御下でコードを再実行して、新しいコードが I<より短い時間> で、
139139B<同じ処理> を実行したことをチェックします。
140140作業を保存して、繰り返します…。
141141
142142=head1 GENERAL GUIDELINES
143143
144144(一般的なガイドライン)
145145
146146=begin original
147147
148148The critical thing when considering performance is to remember there is no such
149149thing as a C<Golden Bullet>, which is why there are no rules, only guidelines.
150150
151151=end original
152152
153153性能について考えるときに重要なことは、C<金の弾丸> のようなものは
154154ないということを忘れないことです; それがなぜここにルールがなく、
155155ガイドラインだけがある理由です。
156156
157157=begin original
158158
159159It is clear that inline code is going to be faster than subroutine or method
160160calls, because there is less overhead, but this approach has the disadvantage
161161of being less maintainable and comes at the cost of greater memory usage -
162162there is no such thing as a free lunch. If you are searching for an element in
163163a list, it can be more efficient to store the data in a hash structure, and
164164then simply look to see whether the key is defined, rather than to loop through
165165the entire array using grep() for instance. substr() may be (a lot) faster
166166than grep() but not as flexible, so you have another trade-off to access. Your
167167code may contain a line which takes 0.01 of a second to execute which if you
168168call it 1,000 times, quite likely in a program parsing even medium sized files
169169for instance, you already have a 10 second delay, in just one single code
170170location, and if you call that line 100,000 times, your entire program will
171171slow down to an unbearable crawl.
172172
173173=end original
174174
175175オーバーヘッドが少ないので、インラインコードはサブルーチンやメソッドの
176176呼び出しより早いのは明らかですが、この手法は保守性が悪くなってメモリ消費が
177177大きくなると言う欠点があります - フリーランチのようなものはありません。
178178一覧の要素を探すとき、例えば配列全体を grep() を使ってループを
179179するのではなく、データをハッシュ構造に保管して、キーがあるかどうかを調べる
180180方がより効率的です。
181181substr() は grep() より(とても)早くなりますが、それほど柔軟ではないので、
182182アクセスするのにもう一つのトレードオフがあります。
183183例えば中くらいのサイズのファイルをパースするような、1,000 回呼び出される
1841840.01 秒かかる行が単一の行ですでに 10 秒の遅延があるかもしれませんし、
185185その行が 100,000 回呼び出されるなら、プログラム全体が耐えられないぐらい
186186遅くなります。
187187
188188=begin original
189189
190190Using a subroutine as part of your sort is a powerful way to get exactly what
191191you want, but will usually be slower than the built-in I<alphabetic> C<cmp> and
192192I<numeric> C<E<lt>=E<gt>> sort operators. It is possible to make multiple
193193passes over your data, building indices to make the upcoming sort more
194194efficient, and to use what is known as the C<OM> (Orcish Maneuver) to cache the
195195sort keys in advance. The cache lookup, while a good idea, can itself be a
196196source of slowdown by enforcing a double pass over the data - once to setup the
197197cache, and once to sort the data. Using C<pack()> to extract the required sort
198198key into a consistent string can be an efficient way to build a single string
199199to compare, instead of using multiple sort keys, which makes it possible to use
200200the standard, written in C<c> and fast, perl C<sort()> function on the output,
201201and is the basis of the C<GRT> (Guttman Rossler Transform). Some string
202202combinations can slow the C<GRT> down, by just being too plain complex for its
203203own good.
204204
205205=end original
206206
207207ソートの一部としてサブルーチンを使うことは、したいことを正確にするための
208208強力な方法ですが、普通は組み込みの I<文字比較> の C<cmp> および
209209I<数値比較> の C<E<lt>=E<gt>> ソート演算子よりも遅いです。
210210データに対して複数パスを行って、ソートをより効率的にするためのインデックスを
211211構築し、予めソートキーをキャッシュするために C<OM> (Orcish Maneuver) として
212212知られてるものを使うことができます。
213213キャッシュの検索は、いい考えですが、それ自身データに対する 2 重パスを
214214強制することでスローダウンの元となり得ます - キャッシュの設定で一度、
215215データのソートでもう一度です。
216216必要なソートキーを永続的な文字列に展開するために C<pack()> を使うのは、
217217複数のソートキーを使わずに比較するための単一の文字列を構築する効率的な
218218方法になり得ます; これにより出力に標準で C<c> で書かれていて高速な
219219Perl の C<sort()> 関数を使えるようになり、C<GRT> (Guttman Rossler Transform)
220220の基礎となります。
221221一部の文字列比較は、単に複雑すぎるので C<GRT> を低下させます。
222222
223223=begin original
224224
225225For applications using database backends, the standard C<DBIx> namespace has
226226tries to help with keeping things nippy, not least because it tries to I<not>
227227query the database until the latest possible moment, but always read the docs
228228which come with your choice of libraries. Among the many issues facing
229229developers dealing with databases should remain aware of is to always use
230230C<SQL> placeholders and to consider pre-fetching data sets when this might
231231prove advantageous. Splitting up a large file by assigning multiple processes
232232to parsing a single file, using say C<POE>, C<threads> or C<fork> can also be a
233233useful way of optimizing your usage of the available C<CPU> resources, though
234234this technique is fraught with concurrency issues and demands high attention to
235235detail.
236236
237237=end original
238238
239239データベースバックエンドを使うアプリケーションで、標準の
240240C<DBIx> 名前空間は物事をぴりっとしたものにし続けるように助けようとします;
241241特に可能な限り遅くまでデータベースに問い合わせ I<しない> ようにしますが、
242242常に選択したライブラリに付属している文書を読んでください。
243243データベースを扱う開発者が直面する多くの問題で気にするべきことは、
244244常に C<SQL> プレースホルダを使うことと、利点がある分かるときにはデータ集合の
245245プリフェッチを考慮することです。
246246大きなファイルを、C<POE>, C<threads>, C<fork> と言ったものを使って
247247単一のファイルをパースする複数のプロセスに割り当てることで分割することも、
248248利用可能な C<CPU> リソースの仕様を最適化する有用な方法になり得ますが、
249249このテクニックは並列性の問題に直面し、詳細に関して高い注目を必要とします。
250250
251251=begin original
252252
253253Every case has a specific application and one or more exceptions, and there is
254254no replacement for running a few tests and finding out which method works best
255255for your particular environment, this is why writing optimal code is not an
256256exact science, and why we love using Perl so much - TMTOWTDI.
257257
258258=end original
259259
260260それぞれのケースには特定のアプリケーションと一つまたは複数の例外があり、
261261いくつかテストを実行して、特定の環境にとってどの手法が最良かを見つけることに
262262代わるものはありません; これは、最適なコードを書くことが正確な科学ではない
263263理由であり、我々が Perl を使うのをとても愛している理由です - TMTOWTDI。
264264
265265=head1 BENCHMARKS
266266
267267(ベンチマーク)
268268
269269=begin original
270270
271271Here are a few examples to demonstrate usage of Perl's benchmarking tools.
272272
273273=end original
274274
275275以下は、Perl のベンチマークツールの使い方を説明するいくつかの例です。
276276
277277=head2 Assigning and Dereferencing Variables.
278278
279279(変数への代入とデリファレンス)
280280
281281=begin original
282282
283283I'm sure most of us have seen code which looks like, (or worse than), this:
284284
285285=end original
286286
287287私たちのほとんどは、以下のような(あるいはもっとひどい)コードを見たことが
288288あるはずです:
289289
290290 if ( $obj->{_ref}->{_myscore} >= $obj->{_ref}->{_yourscore} ) {
291291 ...
292292
293293=begin original
294294
295295This sort of code can be a real eyesore to read, as well as being very
296296sensitive to typos, and it's much clearer to dereference the variable
297297explicitly. We're side-stepping the issue of working with object-oriented
298298programming techniques to encapsulate variable access via methods, only
299299accessible through an object. Here we're just discussing the technical
300300implementation of choice, and whether this has an effect on performance. We
301301can see whether this dereferencing operation, has any overhead by putting
302302comparative code in a file and running a C<Benchmark> test.
303303
304304=end original
305305
306306この種類のコードは読むと目が疲れ、タイプミスに弱く、変数を明示的に
307307デリファレンスすることで遥かに明確になります。
308308変数アクセスをメソッド経由でカプセル化して、オブジェクトを通してのみ
309309アクセス可能にすると言うオブジェクト指向プログラミングのテクニックを
310310使う問題を横に避けておきます。
311311ここでは単に選択する技術実装に関して、そしてこれが性能が向上するかどうかを
312312議論しています。
313313このデリファレンス操作がかなりのコードをファイルに置くことによる
314314オーバーヘッドがあるのかを C<Benchmark> テストで見てみます。
315315
316316=begin original
317317
318318# dereference
319319
320320=end original
321321
322322# デリファレンス
323323
324324 #!/usr/bin/perl
325325
326 use strict;
326 use v5.36;
327 use warnings;
328327
329328 use Benchmark;
330329
331330 my $ref = {
332331 'ref' => {
333332 _myscore => '100 + 1',
334333 _yourscore => '102 - 1',
335334 },
336335 };
337336
338337 timethese(1000000, {
339338 'direct' => sub {
340339 my $x = $ref->{ref}->{_myscore} . $ref->{ref}->{_yourscore} ;
341340 },
342341 'dereference' => sub {
343342 my $ref = $ref->{ref};
344343 my $myscore = $ref->{_myscore};
345344 my $yourscore = $ref->{_yourscore};
346345 my $x = $myscore . $yourscore;
347346 },
348347 });
349348
350349=begin original
351350
352351It's essential to run any timing measurements a sufficient number of times so
353352the numbers settle on a numerical average, otherwise each run will naturally
354353fluctuate due to variations in the environment, to reduce the effect of
355354contention for C<CPU> resources and network bandwidth for instance. Running
356355the above code for one million iterations, we can take a look at the report
357356output by the C<Benchmark> module, to see which approach is the most effective.
358357
359358=end original
360359
361360時間計測は、平均を安定させるために十分な回数行うことが重要です;
362361さもなければそれぞれの実行は、例えば C<CPU> リソースの競合の効果や
363362ネットワーク帯域のような環境の変化によって自然に変動します。
364363どの手法が最も効果的を見るために、上述のコードを 100 万回繰り返して、
365364C<Benchmark> モジュールによって出力された報告を見てみます。
366365
367366 $> perl dereference
368367
369368 Benchmark: timing 1000000 iterations of dereference, direct...
370369 dereference: 2 wallclock secs ( 1.59 usr + 0.00 sys = 1.59 CPU) @ 628930.82/s (n=1000000)
371370 direct: 1 wallclock secs ( 1.20 usr + 0.00 sys = 1.20 CPU) @ 833333.33/s (n=1000000)
372371
373372=begin original
374373
375374The difference is clear to see and the dereferencing approach is slower. While
376375it managed to execute an average of 628,930 times a second during our test, the
377376direct approach managed to run an additional 204,403 times, unfortunately.
378377Unfortunately, because there are many examples of code written using the
379378multiple layer direct variable access, and it's usually horrible. It is,
380379however, minusculy faster. The question remains whether the minute gain is
381380actually worth the eyestrain, or the loss of maintainability.
382381
383382=end original
384383
385384違いははっきりと見え、デリファレンスの手法はより遅いです。
386385これはテスト中 1 秒間に平均して 628,930 回実行しましたが、直接手法は
387386残念ながらさらに 204,403 回実行しています。
388387残念ながら、複数層の直接変数アクセスを使ったコード例がたくさんあるので、
389388これは普通は恐ろしいものです。
390389しかし、これはほんの少し速いです。
391390問題は、ほんの少しの向上が疲れ目と保守性の喪失の価値があるかです。
392391
393392=head2 Search and replace or tr
394393
395394(検索と置換または tr)
396395
397396=begin original
398397
399398If we have a string which needs to be modified, while a regex will almost
400399always be much more flexible, C<tr>, an oft underused tool, can still be a
401400useful. One scenario might be replace all vowels with another character. The
402401regex solution might look like this:
403402
404403=end original
405404
406405変更する必要がある文字列がある場合、正規表現はほとんど常により柔軟性が
407406ありますが、活用されていない C<tr> も依然有用です。
408407一つのシナリオとしては、全ての母音を他の文字に置換するというものです。
409408正規表現による解放は以下のようなものになるでしょう:
410409
411410 $str =~ s/[aeiou]/x/g
412411
413412=begin original
414413
415414The C<tr> alternative might look like this:
416415
417416=end original
418417
419418C<tr> による代替案は以下のようになります:
420419
421420 $str =~ tr/aeiou/xxxxx/
422421
423422=begin original
424423
425424We can put that into a test file which we can run to check which approach is
426425the fastest, using a global C<$STR> variable to assign to the C<my $str>
427426variable so as to avoid perl trying to optimize any of the work away by
428427noticing it's assigned only the once.
429428
430429=end original
431430
432431どの手法が一番早いかをチェックするために、実行するテストファイルにこれを
433432置きます; perl が一度しか代入されないことを気付くことで処理しないように
434433最適化しようとすることを避けるために、C<my $str> 変数へ代入するために
435434グローバルな C<$STR> 変数を使います。
436435
437436=begin original
438437
439438# regex-transliterate
440439
441440=end original
442441
443442# 正規表現-文字変換
444443
445444 #!/usr/bin/perl
446445
447 use strict;
446 use v5.36;
448 use warnings;
449447
450448 use Benchmark;
451449
452450 my $STR = "$$-this and that";
453451
454452 timethese( 1000000, {
455453 'sr' => sub { my $str = $STR; $str =~ s/[aeiou]/x/g; return $str; },
456454 'tr' => sub { my $str = $STR; $str =~ tr/aeiou/xxxxx/; return $str; },
457455 });
458456
459457=begin original
460458
461459Running the code gives us our results:
462460
463461=end original
464462
465463コードを実行することで結果が得られます:
466464
467465 $> perl regex-transliterate
468466
469467 Benchmark: timing 1000000 iterations of sr, tr...
470468 sr: 2 wallclock secs ( 1.19 usr + 0.00 sys = 1.19 CPU) @ 840336.13/s (n=1000000)
471469 tr: 0 wallclock secs ( 0.49 usr + 0.00 sys = 0.49 CPU) @ 2040816.33/s (n=1000000)
472470
473471=begin original
474472
475473The C<tr> version is a clear winner. One solution is flexible, the other is
476474fast - and it's appropriately the programmer's choice which to use.
477475
478476=end original
479477
480478C<tr> 版が明らかな勝者です。
481479ある解決法は柔軟性があり、他の解決法は高速です - そして適切に
482480どちらを使うかはプログラマの選択です。
483481
484482=begin original
485483
486484Check the C<Benchmark> docs for further useful techniques.
487485
488486=end original
489487
490488さらなる有用なテクニックについては C<Benchmark> の文書を参照してください。
491489
492490=head1 PROFILING TOOLS
493491
494492(プロファイリングツール)
495493
496494=begin original
497495
498496A slightly larger piece of code will provide something on which a profiler can
499497produce more extensive reporting statistics. This example uses the simplistic
500498C<wordmatch> program which parses a given input file and spews out a short
501499report on the contents.
502500
503501=end original
504502
505503やや大きめのコードではプロファイラが生成するより大規模な状況報告が
506504何かを提供するでしょう。
507505この例は、与えられた入力ファイルをパースして、内容の短いレポートを出力する
508506単純な C<wordmatch> プログラムを使います。
509507
510508=begin original
511509
512510# wordmatch
513511
514512=end original
515513
516514# 単語マッチング
517515
518516 #!/usr/bin/perl
519517
520 use strict;
518 use v5.36;
521 use warnings;
522519
523520 =head1 NAME
524521
525522 filewords - word analysis of input file
526523
527524 =head1 SYNOPSIS
528525
529526 filewords -f inputfilename [-d]
530527
531528 =head1 DESCRIPTION
532529
533530 This program parses the given filename, specified with C<-f>, and
534531 displays a simple analysis of the words found therein. Use the C<-d>
535532 switch to enable debugging messages.
536533
537534 =cut
538535
539536 use FileHandle;
540537 use Getopt::Long;
541538
542539 my $debug = 0;
543540 my $file = '';
544541
545542 my $result = GetOptions (
546543 'debug' => \$debug,
547544 'file=s' => \$file,
548545 );
549546 die("invalid args") unless $result;
550547
551548 unless ( -f $file ) {
552549 die("Usage: $0 -f filename [-d]");
553550 }
554551 my $FH = FileHandle->new("< $file")
555552 or die("unable to open file($file): $!");
556553
557554 my $i_LINES = 0;
558555 my $i_WORDS = 0;
559556 my %count = ();
560557
561558 my @lines = <$FH>;
562559 foreach my $line ( @lines ) {
563560 $i_LINES++;
564561 $line =~ s/\n//;
565562 my @words = split(/ +/, $line);
566563 my $i_words = scalar(@words);
567564 $i_WORDS = $i_WORDS + $i_words;
568565 debug("line: $i_LINES supplying $i_words words: @words");
569566 my $i_word = 0;
570567 foreach my $word ( @words ) {
571568 $i_word++;
572569 $count{$i_LINES}{spec} += matches($i_word, $word,
573570 '[^a-zA-Z0-9]');
574571 $count{$i_LINES}{only} += matches($i_word, $word,
575572 '^[^a-zA-Z0-9]+$');
576573 $count{$i_LINES}{cons} += matches($i_word, $word,
577574 '^[(?i:bcdfghjklmnpqrstvwxyz)]+$');
578575 $count{$i_LINES}{vows} += matches($i_word, $word,
579576 '^[(?i:aeiou)]+$');
580577 $count{$i_LINES}{caps} += matches($i_word, $word,
581578 '^[(A-Z)]+$');
582579 }
583580 }
584581
585582 print report( %count );
586583
587584 sub matches {
588585 my $i_wd = shift;
589586 my $word = shift;
590587 my $regex = shift;
591588 my $has = 0;
592589
593590 if ( $word =~ /($regex)/ ) {
594591 $has++ if $1;
595592 }
596593
597594 debug( "word: $i_wd "
598595 . ($has ? 'matches' : 'does not match')
599596 . " chars: /$regex/");
600597
601598 return $has;
602599 }
603600
604601 sub report {
605602 my %report = @_;
606603 my %rep;
607604
608605 foreach my $line ( keys %report ) {
609 foreach my $key ( keys %{ $report{$line} } ) {
606 foreach my $key ( keys $report{$line}->%* ) {
610607 $rep{$key} += $report{$line}{$key};
611608 }
612609 }
613610
614611 my $report = qq|
615612 $0 report for $file:
616613 lines in file: $i_LINES
617614 words in file: $i_WORDS
618615 words with special (non-word) characters: $i_spec
619616 words with only special (non-word) characters: $i_only
620617 words with only consonants: $i_cons
621618 words with only capital letters: $i_caps
622619 words with only vowels: $i_vows
623620 |;
624621
625622 return $report;
626623 }
627624
628625 sub debug {
629626 my $message = shift;
630627
631628 if ( $debug ) {
632629 print STDERR "DBG: $message\n";
633630 }
634631 }
635632
636633 exit 0;
637634
638635=head2 Devel::DProf
639636
640637=begin original
641638
642639This venerable module has been the de-facto standard for Perl code profiling
643640for more than a decade, but has been replaced by a number of other modules
644641which have brought us back to the 21st century. Although you're recommended to
645642evaluate your tool from the several mentioned here and from the CPAN list at
646643the base of this document, (and currently L<Devel::NYTProf> seems to be the
647644weapon of choice - see below), we'll take a quick look at the output from
648645L<Devel::DProf> first, to set a baseline for Perl profiling tools. Run the
649646above program under the control of C<Devel::DProf> by using the C<-d> switch on
650647the command-line.
651648
652649=end original
653650
654651この由緒あるモジュールは 10 年以上 Perl コードプロファイリングのデファクト
655652スタンダードでしたが、21 世紀になって色々なその他のモジュールに
656653置き換えられています。
657654いくつかここで言及されたり、この文書の基礎となる CPAN リストからツールを
658655評価することを勧められていますが、(そして現在のところ L<Devel::NYTProf> が
659656選択する武器のようですが - 後述します)、Perl プロファイリングツールの
660657基本となる L<Devel::DProf> からの出力をまず簡単に見てみます。
661658コマンドラインで C<-d> オプションを使うことで C<Devel::DProf> の制御下で
662659プログラムを実行します。
663660
664661 $> perl -d:DProf wordmatch -f perl5db.pl
665662
666663 <...multiple lines snipped...>
667664
668665 wordmatch report for perl5db.pl:
669666 lines in file: 9428
670667 words in file: 50243
671668 words with special (non-word) characters: 20480
672669 words with only special (non-word) characters: 7790
673670 words with only consonants: 4801
674671 words with only capital letters: 1316
675672 words with only vowels: 1701
676673
677674=begin original
678675
679676C<Devel::DProf> produces a special file, called F<tmon.out> by default, and
680677this file is read by the C<dprofpp> program, which is already installed as part
681678of the C<Devel::DProf> distribution. If you call C<dprofpp> with no options,
682679it will read the F<tmon.out> file in the current directory and produce a human
683680readable statistics report of the run of your program. Note that this may take
684681a little time.
685682
686683=end original
687684
688685C<Devel::DProf> は、デフォルトでは F<tmon.out> という名前の特殊なファイルを
689686出力し、このファイルは C<Devel::DProf> ディストリビューションの一部として
690687既にインストールされている C<dprofpp> プログラムによって読み込まれます。
691688オプションなしで C<dprofpp> を呼び出すと、カレントディレクトリの
692689F<tmon.out> ファイルを読み込んで、あなたのプログラムの実行に関する
693690人間が読める形での統計情報を出力します。
694691これには少し時間がかかるかもしれないことに注意してください。
695692
696693 $> dprofpp
697694
698695 Total Elapsed Time = 2.951677 Seconds
699696 User+System Time = 2.871677 Seconds
700697 Exclusive Times
701698 %Time ExclSec CumulS #Calls sec/call Csec/c Name
702699 102. 2.945 3.003 251215 0.0000 0.0000 main::matches
703700 2.40 0.069 0.069 260643 0.0000 0.0000 main::debug
704701 1.74 0.050 0.050 1 0.0500 0.0500 main::report
705702 1.04 0.030 0.049 4 0.0075 0.0123 main::BEGIN
706703 0.35 0.010 0.010 3 0.0033 0.0033 Exporter::as_heavy
707704 0.35 0.010 0.010 7 0.0014 0.0014 IO::File::BEGIN
708705 0.00 - -0.000 1 - - Getopt::Long::FindOption
709706 0.00 - -0.000 1 - - Symbol::BEGIN
710707 0.00 - -0.000 1 - - Fcntl::BEGIN
711708 0.00 - -0.000 1 - - Fcntl::bootstrap
712709 0.00 - -0.000 1 - - warnings::BEGIN
713710 0.00 - -0.000 1 - - IO::bootstrap
714711 0.00 - -0.000 1 - - Getopt::Long::ConfigDefaults
715712 0.00 - -0.000 1 - - Getopt::Long::Configure
716713 0.00 - -0.000 1 - - Symbol::gensym
717714
718715=begin original
719716
720717C<dprofpp> will produce some quite detailed reporting on the activity of the
721718C<wordmatch> program. The wallclock, user and system, times are at the top of
722719the analysis, and after this are the main columns defining which define the
723720report. Check the C<dprofpp> docs for details of the many options it supports.
724721
725722=end original
726723
727724C<dprofpp> は C<wordmatch> プログラムの活動のかなり詳細な報告を出力します。
728725壁時計時間、ユーザーとシステム時間が分析の先頭にあり、その後は報告を
729726定義する定義で主な列です。
730727対応している多くのオプションの詳細については C<dprofpp> の文書を
731728チェックしてください。
732729
733730=begin original
734731
735732See also C<L<Apache::DProf>> which hooks C<Devel::DProf> into C<mod_perl>.
736733
737734=end original
738735
739736C<Devel::DProf> を C<mod_perl> にフックする C<L<Apache::DProf>> も
740737参照してください。
741738
742739=head2 Devel::Profiler
743740
744741=begin original
745742
746743Let's take a look at the same program using a different profiler:
747744C<Devel::Profiler>, a drop-in Perl-only replacement for C<Devel::DProf>. The
748745usage is very slightly different in that instead of using the special C<-d:>
749746flag, you pull C<Devel::Profiler> in directly as a module using C<-M>.
750747
751748=end original
752749
753750同じプログラムの他のプロファイラによる結果も見てみましょう:
754751C<Devel::Profiler> は C<Devel::DProf> の Perl 専用のドロップインです。
755752使用法は特殊な C<-d:> フラグを使うのとはほんの少し違って、
756753C<Devel::Profiler> を C<-M> を使ってモジュールとして直接読み込みます。
757754
758755 $> perl -MDevel::Profiler wordmatch -f perl5db.pl
759756
760757 <...multiple lines snipped...>
761758
762759 wordmatch report for perl5db.pl:
763760 lines in file: 9428
764761 words in file: 50243
765762 words with special (non-word) characters: 20480
766763 words with only special (non-word) characters: 7790
767764 words with only consonants: 4801
768765 words with only capital letters: 1316
769766 words with only vowels: 1701
770767
771768=begin original
772769
773770C<Devel::Profiler> generates a tmon.out file which is compatible with the
774771C<dprofpp> program, thus saving the construction of a dedicated statistics
775772reader program. C<dprofpp> usage is therefore identical to the above example.
776773
777774=end original
778775
779776C<Devel::Profiler> は C<dprofpp> プログラムと互換性のある tmon.out ファイルを
780777生成するので、専用の統計読み込みプログラムの構築を省略できます。
781778従って C<dprofpp> の使用法は上述の例と同じです。
782779
783780 $> dprofpp
784781
785782 Total Elapsed Time = 20.984 Seconds
786783 User+System Time = 19.981 Seconds
787784 Exclusive Times
788785 %Time ExclSec CumulS #Calls sec/call Csec/c Name
789786 49.0 9.792 14.509 251215 0.0000 0.0001 main::matches
790787 24.4 4.887 4.887 260643 0.0000 0.0000 main::debug
791788 0.25 0.049 0.049 1 0.0490 0.0490 main::report
792789 0.00 0.000 0.000 1 0.0000 0.0000 Getopt::Long::GetOptions
793790 0.00 0.000 0.000 2 0.0000 0.0000 Getopt::Long::ParseOptionSpec
794791 0.00 0.000 0.000 1 0.0000 0.0000 Getopt::Long::FindOption
795792 0.00 0.000 0.000 1 0.0000 0.0000 IO::File::new
796793 0.00 0.000 0.000 1 0.0000 0.0000 IO::Handle::new
797794 0.00 0.000 0.000 1 0.0000 0.0000 Symbol::gensym
798795 0.00 0.000 0.000 1 0.0000 0.0000 IO::File::open
799796
800797=begin original
801798
802799Interestingly we get slightly different results, which is mostly because the
803800algorithm which generates the report is different, even though the output file
804801format was allegedly identical. The elapsed, user and system times are clearly
805802showing the time it took for C<Devel::Profiler> to execute its own run, but
806803the column listings feel more accurate somehow than the ones we had earlier
807804from C<Devel::DProf>. The 102% figure has disappeared, for example. This is
808805where we have to use the tools at our disposal, and recognise their pros and
809806cons, before using them. Interestingly, the numbers of calls for each
810807subroutine are identical in the two reports, it's the percentages which differ.
811As the author of C<Devel::Proviler> writes:
808As the author of C<Devel::Profiler> writes:
812809
813810=end original
814811
815812興味深いことに少し異なった結果が得られました; その理由のほとんどは、
816813出力ファイル形式は同一とされているにも関わらず、報告を生成するアルゴリズムが
817814異なることです。
818815経過時間とユーザー+システム時間は明らかに C<Devel::Profiler> が自身の実行で
819816かかった時間を表示してますが、列一覧は先に C<Devel::DProf> で得られたものより
820817いくらかより正確なものに感じられます。
821818例えば、102% の図は消えました。
822819これが、ツールを使ってみて、それらを使う前にそれらの利点と欠点を認識する
823820必要があるところです。
824821興味深いことに、それぞれのサブルーチンの呼び出し回数は二つの報告で
825822同じですが、百分率は異なっています。
826C<Devel::Proviler> の作者が書いているように:
823C<Devel::Profiler> の作者が書いているように:
827824
828825 ...running HTML::Template's test suite under Devel::DProf shows
829826 output() taking NO time but Devel::Profiler shows around 10% of the
830827 time is in output(). I don't know which to trust but my gut tells me
831828 something is wrong with Devel::DProf. HTML::Template::output() is a
832829 big routine that's called for every test. Either way, something needs
833830 fixing.
834831
835832=begin original
836833
837834YMMV.
838835
839836=end original
840837
841838あなたの意見は違うかもしれません。
842839
843840=begin original
844841
845842See also C<L<Devel::Apache::Profiler>> which hooks C<Devel::Profiler>
846843into C<mod_perl>.
847844
848845=end original
849846
850847C<mod_perl> に C<Devel::Profiler> フックを付ける
851848C<L<Devel::Apache::Profiler>> も参照してください。
852849
853850=head2 Devel::SmallProf
854851
855852=begin original
856853
857854The C<Devel::SmallProf> profiler examines the runtime of your Perl program and
858855produces a line-by-line listing to show how many times each line was called,
859856and how long each line took to execute. It is called by supplying the familiar
860857C<-d> flag to Perl at runtime.
861858
862859=end original
863860
864861C<Devel::SmallProf> プロファイラは Perl プログラムの実行時間を調べて、
865862それぞれの行が何回呼び出されたかをしめす行単位の一覧を出力します。
866863これは実行時に Perl に親しんだ C<-d> フラグを指定することで呼び出されます。
867864
868865 $> perl -d:SmallProf wordmatch -f perl5db.pl
869866
870867 <...multiple lines snipped...>
871868
872869 wordmatch report for perl5db.pl:
873870 lines in file: 9428
874871 words in file: 50243
875872 words with special (non-word) characters: 20480
876873 words with only special (non-word) characters: 7790
877874 words with only consonants: 4801
878875 words with only capital letters: 1316
879876 words with only vowels: 1701
880877
881878=begin original
882879
883C<Devel::SmallProf> writes it's output into a file called F<smallprof.out>, by
880C<Devel::SmallProf> writes its output into a file called F<smallprof.out>, by
884881default. The format of the file looks like this:
885882
886883=end original
887884
888885C<Devel::SmallProf> は出力を、デフォルトでは F<smallprof.out> と呼ばれる
889886ファイルに書き込みます。
890887ファイルの形式は以下のようなものです:
891888
892889 <num> <time> <ctime> <line>:<text>
893890
894891=begin original
895892
896893When the program has terminated, the output may be examined and sorted using
897894any standard text filtering utilities. Something like the following may be
898895sufficient:
899896
900897=end original
901898
902899プログラムが終了したとき、出力は任意の標準テキストフィルタリング
903900ユーティリティを使って検査とソートが行われます。
904901以下のようなもので十分でしょう:
905902
906903 $> cat smallprof.out | grep \d*: | sort -k3 | tac | head -n20
907904
908905 251215 1.65674 7.68000 75: if ( $word =~ /($regex)/ ) {
909906 251215 0.03264 4.40000 79: debug("word: $i_wd ".($has ? 'matches' :
910907 251215 0.02693 4.10000 81: return $has;
911908 260643 0.02841 4.07000 128: if ( $debug ) {
912909 260643 0.02601 4.04000 126: my $message = shift;
913910 251215 0.02641 3.91000 73: my $has = 0;
914911 251215 0.03311 3.71000 70: my $i_wd = shift;
915912 251215 0.02699 3.69000 72: my $regex = shift;
916913 251215 0.02766 3.68000 71: my $word = shift;
917914 50243 0.59726 1.00000 59: $count{$i_LINES}{cons} =
918915 50243 0.48175 0.92000 61: $count{$i_LINES}{spec} =
919916 50243 0.00644 0.89000 56: my $i_cons = matches($i_word, $word,
920917 50243 0.48837 0.88000 63: $count{$i_LINES}{caps} =
921918 50243 0.00516 0.88000 58: my $i_caps = matches($i_word, $word, '^[(A-
922919 50243 0.00631 0.81000 54: my $i_spec = matches($i_word, $word, '[^a-
923920 50243 0.00496 0.80000 57: my $i_vows = matches($i_word, $word,
924921 50243 0.00688 0.80000 53: $i_word++;
925922 50243 0.48469 0.79000 62: $count{$i_LINES}{only} =
926923 50243 0.48928 0.77000 60: $count{$i_LINES}{vows} =
927924 50243 0.00683 0.75000 55: my $i_only = matches($i_word, $word, '^[^a-
928925
929926=begin original
930927
931928You can immediately see a slightly different focus to the subroutine profiling
932929modules, and we start to see exactly which line of code is taking the most
933930time. That regex line is looking a bit suspicious, for example. Remember that
934931these tools are supposed to be used together, there is no single best way to
935932profile your code, you need to use the best tools for the job.
936933
937934=end original
938935
939936サブルーチンプロファイリングモジュールとは少し異なったフォーカスであることが
940937すぐに分かります; そして正確にコードのどの行が一番時間がかかるかを
941938見始めます。
942939例えば、正規表現行は少し疑わしく見えます。
943940これらのツールは互いに使われることを想定されていて、コードを
944941プロファイリングする単一の最良の方法というのはなく、仕事によって最良の
945942ツールを使う必要があると言うことを忘れないでください。
946943
947944=begin original
948945
949946See also C<L<Apache::SmallProf>> which hooks C<Devel::SmallProf> into
950947C<mod_perl>.
951948
952949=end original
953950
954951C<mod_perl> に C<L<Apache::SmallProf>> フックを付ける C<Apache::SmallProf> も
955952参照してください。
956953
957954=head2 Devel::FastProf
958955
959956=begin original
960957
961958C<Devel::FastProf> is another Perl line profiler. This was written with a view
962959to getting a faster line profiler, than is possible with for example
963960C<Devel::SmallProf>, because it's written in C<C>. To use C<Devel::FastProf>,
964961supply the C<-d> argument to Perl:
965962
966963=end original
967964
968965C<Devel::FastProf> はもう一つの Perl 行プロファイラです。
969966これは、例えば C<Devel::SmallProf> などよりも速い行プロファイラとして
970967C<C> で書かれました。
971968C<Devel::FastProf> を使うには、Perl に C<-d> オプションを指定します:
972969
973970 $> perl -d:FastProf wordmatch -f perl5db.pl
974971
975972 <...multiple lines snipped...>
976973
977974 wordmatch report for perl5db.pl:
978975 lines in file: 9428
979976 words in file: 50243
980977 words with special (non-word) characters: 20480
981978 words with only special (non-word) characters: 7790
982979 words with only consonants: 4801
983980 words with only capital letters: 1316
984981 words with only vowels: 1701
985982
986983=begin original
987984
988985C<Devel::FastProf> writes statistics to the file F<fastprof.out> in the current
989986directory. The output file, which can be specified, can be interpreted by using
990987the C<fprofpp> command-line program.
991988
992989=end original
993990
994991C<Devel::FastProf> は現在のディレクトリのファイル F<fastprof.out> に
995992統計情報を書き込みます。
996993指定可能な出力ファイルは C<fprofpp> コマンドラインプログラムを使って
997994解釈されます。
998995
999996 $> fprofpp | head -n20
1000997
1001998 # fprofpp output format is:
1002999 # filename:line time count: source
10031000 wordmatch:75 3.93338 251215: if ( $word =~ /($regex)/ ) {
10041001 wordmatch:79 1.77774 251215: debug("word: $i_wd ".($has ? 'matches' : 'does not match')." chars: /$regex/");
10051002 wordmatch:81 1.47604 251215: return $has;
10061003 wordmatch:126 1.43441 260643: my $message = shift;
10071004 wordmatch:128 1.42156 260643: if ( $debug ) {
10081005 wordmatch:70 1.36824 251215: my $i_wd = shift;
10091006 wordmatch:71 1.36739 251215: my $word = shift;
10101007 wordmatch:72 1.35939 251215: my $regex = shift;
10111008
10121009=begin original
10131010
10141011Straightaway we can see that the number of times each line has been called is
10151012identical to the C<Devel::SmallProf> output, and the sequence is only very
10161013slightly different based on the ordering of the amount of time each line took
10171014to execute, C<if ( $debug ) { > and C<my $message = shift;>, for example. The
10181015differences in the actual times recorded might be in the algorithm used
10191016internally, or it could be due to system resource limitations or contention.
10201017
10211018=end original
10221019
10231020直ちに、各行が呼び出された回数が C<Devel::SmallProf> の出力と同じで、並びは
10241021各行の実行時間順を基にして ほんの少しだけ異なる(例えば C<if ( $debug ) { > と
10251022C<my $message = shift;>) ことがわかります。
10261023実際に記録されている時間の違いは内部で使われているアルゴリズムかも
10271024しれませんし、システムリソースの制限や衝突によるかもしれません。
10281025
10291026=begin original
10301027
10311028See also the L<DBIx::Profile> which will profile database queries running
10321029under the C<DBIx::*> namespace.
10331030
10341031=end original
10351032
10361033C<DBIx::*> 名前空間で実行されるデータベース問い合わせをプロファイルする
10371034L<DBIx::Profile> も参照してください。
10381035
10391036=head2 Devel::NYTProf
10401037
10411038=begin original
10421039
10431040C<Devel::NYTProf> is the B<next generation> of Perl code profiler, fixing many
10441041shortcomings in other tools and implementing many cool features. First of all it
10451042can be used as either a I<line> profiler, a I<block> or a I<subroutine>
10461043profiler, all at once. It can also use sub-microsecond (100ns) resolution on
10471044systems which provide C<clock_gettime()>. It can be started and stopped even
10481045by the program being profiled. It's a one-line entry to profile C<mod_perl>
10491046applications. It's written in C<c> and is probably the fastest profiler
10501047available for Perl. The list of coolness just goes on. Enough of that, let's
10511048see how to it works - just use the familiar C<-d> switch to plug it in and run
10521049the code.
10531050
10541051=end original
10551052
10561053C<Devel::NYTProf> は B<新世代> Perl コードプロファイラで、他のツールの
10571054多くの欠点を修正し、多くのクールな機能を実装しています。
10581055まず、これは I<行> プロファイラと I<ブロック> または
10591056I<サブルーチン> プロファイラとして一度に使えます。
10601057また、C<clock_gettime()> を提供しているシステムではマイクロ秒未満 (100ns) の
10611058解像度を使えます。
10621059プログラムがプロファイルからでも開始終了できます。
10631060これは C<mod_perl> アプリケーションをプロファイルする一行エントリです。
10641061これは C<c> で書かれていて、おそらく Perl で利用可能な最速の
10651062プロファイラです。
10661063素晴らしさの一覧はまだ続きます。
10671064これで十分でしょうから、どのように動作するかを見てみましょう - 単に親しんだ
10681065C<-d> スイッチを使って、コードを実行します。
10691066
10701067 $> perl -d:NYTProf wordmatch -f perl5db.pl
10711068
10721069 wordmatch report for perl5db.pl:
10731070 lines in file: 9427
10741071 words in file: 50243
10751072 words with special (non-word) characters: 20480
10761073 words with only special (non-word) characters: 7790
10771074 words with only consonants: 4801
10781075 words with only capital letters: 1316
10791076 words with only vowels: 1701
10801077
10811078=begin original
10821079
10831080C<NYTProf> will generate a report database into the file F<nytprof.out> by
10841081default. Human readable reports can be generated from here by using the
10851082supplied C<nytprofhtml> (HTML output) and C<nytprofcsv> (CSV output) programs.
10861083We've used the Unix system C<html2text> utility to convert the
10871084F<nytprof/index.html> file for convenience here.
10881085
10891086=end original
10901087
10911088C<NYTProf> はデフォルトではファイル F<nytprof.out> にレポートデータベースを
10921089生成します。
10931090人間が読める報告は、提供される C<nytprofhtml> (HTML 出力) または
10941091C<nytprofcsv> (CSV 出力) プログラムを使うことでここから生成されます。
10951092F<nytprof/index.html> ファイルをここで便利なように変換するために Unix
10961093システムの C<html2text> ユーティリティを使っています。
10971094
10981095 $> html2text nytprof/index.html
10991096
11001097 Performance Profile Index
11011098 For wordmatch
11021099 Run on Fri Sep 26 13:46:39 2008
11031100 Reported on Fri Sep 26 13:47:23 2008
11041101
11051102 Top 15 Subroutines -- ordered by exclusive time
11061103 |Calls |P |F |Inclusive|Exclusive|Subroutine |
11071104 | | | |Time |Time | |
11081105 |251215|5 |1 |13.09263 |10.47692 |main:: |matches |
11091106 |260642|2 |1 |2.71199 |2.71199 |main:: |debug |
11101107 |1 |1 |1 |0.21404 |0.21404 |main:: |report |
11111108 |2 |2 |2 |0.00511 |0.00511 |XSLoader:: |load (xsub) |
11121109 |14 |14|7 |0.00304 |0.00298 |Exporter:: |import |
11131110 |3 |1 |1 |0.00265 |0.00254 |Exporter:: |as_heavy |
11141111 |10 |10|4 |0.00140 |0.00140 |vars:: |import |
11151112 |13 |13|1 |0.00129 |0.00109 |constant:: |import |
11161113 |1 |1 |1 |0.00360 |0.00096 |FileHandle:: |import |
11171114 |3 |3 |3 |0.00086 |0.00074 |warnings::register::|import |
11181115 |9 |3 |1 |0.00036 |0.00036 |strict:: |bits |
11191116 |13 |13|13|0.00032 |0.00029 |strict:: |import |
11201117 |2 |2 |2 |0.00020 |0.00020 |warnings:: |import |
11211118 |2 |1 |1 |0.00020 |0.00020 |Getopt::Long:: |ParseOptionSpec|
11221119 |7 |7 |6 |0.00043 |0.00020 |strict:: |unimport |
11231120
11241121 For more information see the full list of 189 subroutines.
11251122
11261123=begin original
11271124
11281125The first part of the report already shows the critical information regarding
11291126which subroutines are using the most time. The next gives some statistics
11301127about the source files profiled.
11311128
11321129=end original
11331130
11341131報告の最初の部分は既に、どのサブルーチンが一番時間がかかっているかという
11351132重要な情報を表示しています。
11361133以下はプロファイリングしたソースファイルに関するいくつかの統計情報です。
11371134
11381135 Source Code Files -- ordered by exclusive time then name
11391136 |Stmts |Exclusive|Avg. |Reports |Source File |
11401137 | |Time | | | |
11411138 |2699761|15.66654 |6e-06 |line . block . sub|wordmatch |
11421139 |35 |0.02187 |0.00062|line . block . sub|IO/Handle.pm |
11431140 |274 |0.01525 |0.00006|line . block . sub|Getopt/Long.pm |
11441141 |20 |0.00585 |0.00029|line . block . sub|Fcntl.pm |
11451142 |128 |0.00340 |0.00003|line . block . sub|Exporter/Heavy.pm |
11461143 |42 |0.00332 |0.00008|line . block . sub|IO/File.pm |
11471144 |261 |0.00308 |0.00001|line . block . sub|Exporter.pm |
11481145 |323 |0.00248 |8e-06 |line . block . sub|constant.pm |
11491146 |12 |0.00246 |0.00021|line . block . sub|File/Spec/Unix.pm |
11501147 |191 |0.00240 |0.00001|line . block . sub|vars.pm |
11511148 |77 |0.00201 |0.00003|line . block . sub|FileHandle.pm |
11521149 |12 |0.00198 |0.00016|line . block . sub|Carp.pm |
11531150 |14 |0.00175 |0.00013|line . block . sub|Symbol.pm |
11541151 |15 |0.00130 |0.00009|line . block . sub|IO.pm |
11551152 |22 |0.00120 |0.00005|line . block . sub|IO/Seekable.pm |
11561153 |198 |0.00085 |4e-06 |line . block . sub|warnings/register.pm|
11571154 |114 |0.00080 |7e-06 |line . block . sub|strict.pm |
11581155 |47 |0.00068 |0.00001|line . block . sub|warnings.pm |
11591156 |27 |0.00054 |0.00002|line . block . sub|overload.pm |
11601157 |9 |0.00047 |0.00005|line . block . sub|SelectSaver.pm |
11611158 |13 |0.00045 |0.00003|line . block . sub|File/Spec.pm |
11621159 |2701595|15.73869 | |Total |
11631160 |128647 |0.74946 | |Average |
11641161 | |0.00201 |0.00003|Median |
11651162 | |0.00121 |0.00003|Deviation |
11661163
11671164 Report produced by the NYTProf 2.03 Perl profiler, developed by Tim Bunce and
11681165 Adam Kaplan.
11691166
11701167=begin original
11711168
11721169At this point, if you're using the I<html> report, you can click through the
11731170various links to bore down into each subroutine and each line of code. Because
11741171we're using the text reporting here, and there's a whole directory full of
11751172reports built for each source file, we'll just display a part of the
11761173corresponding F<wordmatch-line.html> file, sufficient to give an idea of the
11771174sort of output you can expect from this cool tool.
11781175
11791176=end original
11801177
11811178この点で、I<html> レポートを使っているなら、サブルーチン単位と行単位の
11821179詳細への様々なリンクをクリックできます。
11831180ここではテキストレポートを使っていて、それぞれのソースファイルに対して
11841181ビルドされたレポートファイルがディレクトリにたくさんあるので、対応する
11851182F<wordmatch-line.html> ファイルの一部だけを表示します; この素晴らしいツールで
11861183どのような出力が得られるかの考えを与えるには十分です。
11871184
11881185 $> html2text nytprof/wordmatch-line.html
11891186
11901187 Performance Profile -- -block view-.-line view-.-sub view-
11911188 For wordmatch
11921189 Run on Fri Sep 26 13:46:39 2008
11931190 Reported on Fri Sep 26 13:47:22 2008
11941191
11951192 File wordmatch
11961193
11971194 Subroutines -- ordered by exclusive time
11981195 |Calls |P|F|Inclusive|Exclusive|Subroutine |
11991196 | | | |Time |Time | |
12001197 |251215|5|1|13.09263 |10.47692 |main::|matches|
12011198 |260642|2|1|2.71199 |2.71199 |main::|debug |
12021199 |1 |1|1|0.21404 |0.21404 |main::|report |
12031200 |0 |0|0|0 |0 |main::|BEGIN |
12041201
12051202 |Line|Stmts.|Exclusive|Avg. |Code |
12061203 | | |Time | | |
12071204 |1 | | | |#!/usr/bin/perl |
12081205 |2 | | | | |
12091206 | | | | |use strict; |
12101207 |3 |3 |0.00086 |0.00029|# spent 0.00003s making 1 calls to strict:: |
12111208 | | | | |import |
12121209 | | | | |use warnings; |
12131210 |4 |3 |0.01563 |0.00521|# spent 0.00012s making 1 calls to warnings:: |
12141211 | | | | |import |
12151212 |5 | | | | |
12161213 |6 | | | |=head1 NAME |
12171214 |7 | | | | |
12181215 |8 | | | |filewords - word analysis of input file |
12191216 <...snip...>
12201217 |62 |1 |0.00445 |0.00445|print report( %count ); |
12211218 | | | | |# spent 0.21404s making 1 calls to main::report|
12221219 |63 | | | | |
12231220 | | | | |# spent 23.56955s (10.47692+2.61571) within |
12241221 | | | | |main::matches which was called 251215 times, |
12251222 | | | | |avg 0.00005s/call: # 50243 times |
12261223 | | | | |(2.12134+0.51939s) at line 57 of wordmatch, avg|
12271224 | | | | |0.00005s/call # 50243 times (2.17735+0.54550s) |
12281225 |64 | | | |at line 56 of wordmatch, avg 0.00005s/call # |
12291226 | | | | |50243 times (2.10992+0.51797s) at line 58 of |
12301227 | | | | |wordmatch, avg 0.00005s/call # 50243 times |
12311228 | | | | |(2.12696+0.51598s) at line 55 of wordmatch, avg|
12321229 | | | | |0.00005s/call # 50243 times (1.94134+0.51687s) |
12331230 | | | | |at line 54 of wordmatch, avg 0.00005s/call |
12341231 | | | | |sub matches { |
12351232 <...snip...>
12361233 |102 | | | | |
12371234 | | | | |# spent 2.71199s within main::debug which was |
12381235 | | | | |called 260642 times, avg 0.00001s/call: # |
12391236 | | | | |251215 times (2.61571+0s) by main::matches at |
12401237 |103 | | | |line 74 of wordmatch, avg 0.00001s/call # 9427 |
12411238 | | | | |times (0.09628+0s) at line 50 of wordmatch, avg|
12421239 | | | | |0.00001s/call |
12431240 | | | | |sub debug { |
12441241 |104 |260642|0.58496 |2e-06 |my $message = shift; |
12451242 |105 | | | | |
12461243 |106 |260642|1.09917 |4e-06 |if ( $debug ) { |
12471244 |107 | | | |print STDERR "DBG: $message\n"; |
12481245 |108 | | | |} |
12491246 |109 | | | |} |
12501247 |110 | | | | |
12511248 |111 |1 |0.01501 |0.01501|exit 0; |
12521249 |112 | | | | |
12531250
12541251=begin original
12551252
12561253Oodles of very useful information in there - this seems to be the way forward.
12571254
12581255=end original
12591256
12601257大量のとても有用な情報がここにあります - これは前進する道のように思えます。
12611258
12621259=begin original
12631260
12641261See also C<L<Devel::NYTProf::Apache>> which hooks C<Devel::NYTProf> into
12651262C<mod_perl>.
12661263
12671264=end original
12681265
12691266C<mod_perl> に C<Devel::NYTProf> フックを付ける C<L<Devel::NYTProf::Apache>> も
12701267参照してください。
12711268
12721269=head1 SORTING
12731270
12741271(ソート)
12751272
12761273=begin original
12771274
12781275Perl modules are not the only tools a performance analyst has at their
12791276disposal, system tools like C<time> should not be overlooked as the next
12801277example shows, where we take a quick look at sorting. Many books, theses and
12811278articles, have been written about efficient sorting algorithms, and this is not
12821279the place to repeat such work, there's several good sorting modules which
12831280deserve taking a look at too: C<Sort::Maker>, C<Sort::Key> spring to mind.
12841281However, it's still possible to make some observations on certain Perl specific
12851282interpretations on issues relating to sorting data sets and give an example or
12861283two with regard to how sorting large data volumes can effect performance.
12871284Firstly, an often overlooked point when sorting large amounts of data, one can
12881285attempt to reduce the data set to be dealt with and in many cases C<grep()> can
12891286be quite useful as a simple filter:
12901287
12911288=end original
12921289
12931290Perl モジュールは性能分析者が持っている唯一の道具というわけではなく、
12941291ソートについて軽く見てみる次の例のように、C<time> のようなシステムツールも
12951292見落とすべきではありません。
12961293効率的なソートアルゴリズムについて書かれている多くの多くの本、論文、記事が
12971294あり、ここはそのようなことを繰り返す場所ではありません; 調べてみる価値のある
12981295いくつかのよいソートモジュールもあります: C<Sort::Maker>, C<Sort::Key> が
12991296思い浮かびます。
13001297しかし、まだデータ集合のソートに関連する問題の Perl 特有の解釈に関して
13011298いくつか観測できる可能性があるので、大量のデータがどのように性能に
13021299影響するかに関する例をいくつか示します。
13031300最初に、大量のデータをソートするときにしばしば見落とされる点は、扱うデータ
13041301集合を減らそうと出来ることと、多くの場合 C<grep()> が単純なフィルタとして
13051302かなり有用であるということです:
13061303
13071304 @data = sort grep { /$filter/ } @incoming
13081305
13091306=begin original
13101307
13111308A command such as this can vastly reduce the volume of material to actually
13121309sort through in the first place, and should not be too lightly disregarded
13131310purely on the basis of its simplicity. The C<KISS> principle is too often
13141311overlooked - the next example uses the simple system C<time> utility to
13151312demonstrate. Let's take a look at an actual example of sorting the contents of
13161313a large file, an apache logfile would do. This one has over a quarter of a
13171314million lines, is 50M in size, and a snippet of it looks like this:
13181315
13191316=end original
13201317
13211318このようなコマンドは最初に実際にソートする量をとても減らすことが出来、
13221319単純性の原則だけであまり簡単に無視するべきではありません。
13231320C<KISS> 原則はあまりにも見逃されています - 次の例はデモに単純なシステム
13241321C<time> ユーティリティを使います。
13251322大きなファイルの内容をソートするという実際の例を見てみましょう; apache の
13261323ログファイルを使ってみます。
13271324これは 25 万行 50M バイトを超えますが、その一部は以下のようなものです:
13281325
13291326=begin original
13301327
13311328# logfile
13321329
13331330=end original
13341331
13351332# ログファイル
13361333
13371334 188.209-65-87.adsl-dyn.isp.belgacom.be - - [08/Feb/2007:12:57:16 +0000] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
13381335 188.209-65-87.adsl-dyn.isp.belgacom.be - - [08/Feb/2007:12:57:16 +0000] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
13391336 151.56.71.198 - - [08/Feb/2007:12:57:41 +0000] "GET /suse-on-vaio.html HTTP/1.1" 200 2858 "http://www.linux-on-laptops.com/sony.html" "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1"
13401337 151.56.71.198 - - [08/Feb/2007:12:57:42 +0000] "GET /data/css HTTP/1.1" 404 206 "http://www.rfi.net/suse-on-vaio.html" "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1"
13411338 151.56.71.198 - - [08/Feb/2007:12:57:43 +0000] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1"
13421339 217.113.68.60 - - [08/Feb/2007:13:02:15 +0000] "GET / HTTP/1.1" 304 - "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
13431340 217.113.68.60 - - [08/Feb/2007:13:02:16 +0000] "GET /data/css HTTP/1.1" 404 206 "http://www.rfi.net/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
13441341 debora.to.isac.cnr.it - - [08/Feb/2007:13:03:58 +0000] "GET /suse-on-vaio.html HTTP/1.1" 200 2858 "http://www.linux-on-laptops.com/sony.html" "Mozilla/5.0 (compatible; Konqueror/3.4; Linux) KHTML/3.4.0 (like Gecko)"
13451342 debora.to.isac.cnr.it - - [08/Feb/2007:13:03:58 +0000] "GET /data/css HTTP/1.1" 404 206 "http://www.rfi.net/suse-on-vaio.html" "Mozilla/5.0 (compatible; Konqueror/3.4; Linux) KHTML/3.4.0 (like Gecko)"
13461343 debora.to.isac.cnr.it - - [08/Feb/2007:13:03:58 +0000] "GET /favicon.ico HTTP/1.1" 404 209 "-" "Mozilla/5.0 (compatible; Konqueror/3.4; Linux) KHTML/3.4.0 (like Gecko)"
13471344 195.24.196.99 - - [08/Feb/2007:13:26:48 +0000] "GET / HTTP/1.0" 200 3309 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.9) Gecko/20061206 Firefox/1.5.0.9"
13481345 195.24.196.99 - - [08/Feb/2007:13:26:58 +0000] "GET /data/css HTTP/1.0" 404 206 "http://www.rfi.net/" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.9) Gecko/20061206 Firefox/1.5.0.9"
13491346 195.24.196.99 - - [08/Feb/2007:13:26:59 +0000] "GET /favicon.ico HTTP/1.0" 404 209 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; fr; rv:1.8.0.9) Gecko/20061206 Firefox/1.5.0.9"
13501347 crawl1.cosmixcorp.com - - [08/Feb/2007:13:27:57 +0000] "GET /robots.txt HTTP/1.0" 200 179 "-" "voyager/1.0"
13511348 crawl1.cosmixcorp.com - - [08/Feb/2007:13:28:25 +0000] "GET /links.html HTTP/1.0" 200 3413 "-" "voyager/1.0"
13521349 fhm226.internetdsl.tpnet.pl - - [08/Feb/2007:13:37:32 +0000] "GET /suse-on-vaio.html HTTP/1.1" 200 2858 "http://www.linux-on-laptops.com/sony.html" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
13531350 fhm226.internetdsl.tpnet.pl - - [08/Feb/2007:13:37:34 +0000] "GET /data/css HTTP/1.1" 404 206 "http://www.rfi.net/suse-on-vaio.html" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)"
13541351 80.247.140.134 - - [08/Feb/2007:13:57:35 +0000] "GET / HTTP/1.1" 200 3309 "-" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
13551352 80.247.140.134 - - [08/Feb/2007:13:57:37 +0000] "GET /data/css HTTP/1.1" 404 206 "http://www.rfi.net" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)"
13561353 pop.compuscan.co.za - - [08/Feb/2007:14:10:43 +0000] "GET / HTTP/1.1" 200 3309 "-" "www.clamav.net"
13571354 livebot-207-46-98-57.search.live.com - - [08/Feb/2007:14:12:04 +0000] "GET /robots.txt HTTP/1.0" 200 179 "-" "msnbot/1.0 (+http://search.msn.com/msnbot.htm)"
13581355 livebot-207-46-98-57.search.live.com - - [08/Feb/2007:14:12:04 +0000] "GET /html/oracle.html HTTP/1.0" 404 214 "-" "msnbot/1.0 (+http://search.msn.com/msnbot.htm)"
13591356 dslb-088-064-005-154.pools.arcor-ip.net - - [08/Feb/2007:14:12:15 +0000] "GET / HTTP/1.1" 200 3309 "-" "www.clamav.net"
13601357 196.201.92.41 - - [08/Feb/2007:14:15:01 +0000] "GET / HTTP/1.1" 200 3309 "-" "MOT-L7/08.B7.DCR MIB/2.2.1 Profile/MIDP-2.0 Configuration/CLDC-1.1"
13611358
13621359=begin original
13631360
13641361The specific task here is to sort the 286,525 lines of this file by Response
13651362Code, Query, Browser, Referring Url, and lastly Date. One solution might be to
13661363use the following code, which iterates over the files given on the
13671364command-line.
13681365
13691366=end original
13701367
13711368ここでのタスクは Response Code, Query, Browser, Referring Url,
13721369lastly Date からなる 286,525 行のファイルをソートすることです。
13731370一つの解決法は、以下のコードのようにコマンドラインで指定されたファイルを
13741371反復する方法かもしれません。
13751372
13761373=begin original
13771374
13781375# sort-apache-log
13791376
13801377=end original
13811378
13821379# apache のログのソート
13831380
13841381 #!/usr/bin/perl -n
13851382
1386 use strict;
1383 use v5.36;
1387 use warnings;
13881384
13891385 my @data;
13901386
13911387 LINE:
13921388 while ( <> ) {
13931389 my $line = $_;
13941390 if (
13951391 $line =~ m/^(
13961392 ([\w\.\-]+) # client
13971393 \s*-\s*-\s*\[
13981394 ([^]]+) # date
13991395 \]\s*"\w+\s*
14001396 (\S+) # query
14011397 [^"]+"\s*
14021398 (\d+) # status
14031399 \s+\S+\s+"[^"]*"\s+"
14041400 ([^"]*) # browser
14051401 "
14061402 .*
14071403 )$/x
14081404 ) {
14091405 my @chunks = split(/ +/, $line);
14101406 my $ip = $1;
14111407 my $date = $2;
14121408 my $query = $3;
14131409 my $status = $4;
14141410 my $browser = $5;
14151411
14161412 push(@data, [$ip, $date, $query, $status, $browser, $line]);
14171413 }
14181414 }
14191415
14201416 my @sorted = sort {
14211417 $a->[3] cmp $b->[3]
14221418 ||
14231419 $a->[2] cmp $b->[2]
14241420 ||
14251421 $a->[0] cmp $b->[0]
14261422 ||
14271423 $a->[1] cmp $b->[1]
14281424 ||
14291425 $a->[4] cmp $b->[4]
14301426 } @data;
14311427
14321428 foreach my $data ( @sorted ) {
14331429 print $data->[5];
14341430 }
14351431
14361432 exit 0;
14371433
14381434=begin original
14391435
14401436When running this program, redirect C<STDOUT> so it is possible to check the
14411437output is correct from following test runs and use the system C<time> utility
14421438to check the overall runtime.
14431439
14441440=end original
14451441
14461442このプログラムを実行するとき、以後のテストで出力が正しいか
14471443チェックできるように C<STDOUT> をリダイレクトして、全体の実行時間を
14481444チェックするためにシステムの C<time> ユーティリティを使います。
14491445
14501446 $> time ./sort-apache-log logfile > out-sort
14511447
14521448 real 0m17.371s
14531449 user 0m15.757s
14541450 sys 0m0.592s
14551451
14561452=begin original
14571453
14581454The program took just over 17 wallclock seconds to run. Note the different
14591455values C<time> outputs, it's important to always use the same one, and to not
14601456confuse what each one means.
14611457
14621458=end original
14631459
14641460プログラムは実行にちょうど 17 壁時計秒ほどかかりました。
14651461C<time> 出力の異なった値に注意して、いつも同じものを使い、それぞれの値の
14661462意味を混乱しないことが重要です。
14671463
14681464=over 4
14691465
14701466=item Elapsed Real Time
14711467
14721468(実経過時間)
14731469
14741470=begin original
14751471
14761472The overall, or wallclock, time between when C<time> was called, and when it
14771473terminates. The elapsed time includes both user and system times, and time
14781474spent waiting for other users and processes on the system. Inevitably, this is
14791475the most approximate of the measurements given.
14801476
14811477=end original
14821478
14831479C<time> が呼び出されてからそれが終了するまでの間の全体的な、あるいは
14841480壁時計の、時間です。
14851481経過時間にはユーザー時間とシステム時間、およびシステム上の他のユーザーや
14861482プロセスを待つために費やされた時間を含みます。
14871483必然的に、これは与えられたものに最も近い時間です。
14881484
14891485=item User CPU Time
14901486
14911487(ユーザー CPU 時間)
14921488
14931489=begin original
14941490
14951491The user time is the amount of time the entire process spent on behalf of the
14961492user on this system executing this program.
14971493
14981494=end original
14991495
15001496ユーザー時間はこのシステムでこのプログラムを実行することで消費された
15011497全体のプロセス時間です。
15021498
15031499=item System CPU Time
15041500
15051501(システム CPU 時間)
15061502
15071503=begin original
15081504
15091505The system time is the amount of time the kernel itself spent executing
15101506routines, or system calls, on behalf of this process user.
15111507
15121508=end original
15131509
15141510システム時間はこのプロセスユーザーのためにカーネルが実行したルーチンや
15151511システムコールの時間です。
15161512
15171513=back
15181514
15191515=begin original
15201516
15211517Running this same process as a C<Schwarzian Transform> it is possible to
15221518eliminate the input and output arrays for storing all the data, and work on the
15231519input directly as it arrives too. Otherwise, the code looks fairly similar:
15241520
15251521=end original
15261522
15271523同じ処理を C<シュワルツ変換> (Schwarzian Transform) として実行すると、
15281524全てのデータを補完するための配列の入出力を除去することができ、
15291525入力を直接届いてすぐに処理します。
15301526さもなければ、コードはほぼ似て見えます:
15311527
15321528=begin original
15331529
15341530# sort-apache-log-schwarzian
15351531
15361532=end original
15371533
15381534# apache のログをシュワルツ変換ソート
15391535
15401536 #!/usr/bin/perl -n
15411537
1542 use strict;
1538 use v5.36;
1543 use warnings;
15441539
15451540 print
15461541
15471542 map $_->[0] =>
15481543
15491544 sort {
15501545 $a->[4] cmp $b->[4]
15511546 ||
15521547 $a->[3] cmp $b->[3]
15531548 ||
15541549 $a->[1] cmp $b->[1]
15551550 ||
15561551 $a->[2] cmp $b->[2]
15571552 ||
15581553 $a->[5] cmp $b->[5]
15591554 }
15601555 map [ $_, m/^(
15611556 ([\w\.\-]+) # client
15621557 \s*-\s*-\s*\[
15631558 ([^]]+) # date
15641559 \]\s*"\w+\s*
15651560 (\S+) # query
15661561 [^"]+"\s*
15671562 (\d+) # status
15681563 \s+\S+\s+"[^"]*"\s+"
15691564 ([^"]*) # browser
15701565 "
15711566 .*
15721567 )$/xo ]
15731568
15741569 => <>;
15751570
15761571 exit 0;
15771572
15781573=begin original
15791574
15801575Run the new code against the same logfile, as above, to check the new time.
15811576
15821577=end original
15831578
15841579新しい時間をチェックするために上述のように同じログファイルに対して
15851580新しいコードを実行します。
15861581
15871582 $> time ./sort-apache-log-schwarzian logfile > out-schwarz
15881583
15891584 real 0m9.664s
15901585 user 0m8.873s
15911586 sys 0m0.704s
15921587
15931588=begin original
15941589
15951590The time has been cut in half, which is a respectable speed improvement by any
15961591standard. Naturally, it is important to check the output is consistent with
15971592the first program run, this is where the Unix system C<cksum> utility comes in.
15981593
15991594=end original
16001595
16011596時間は半分になりました; これはあらゆる面で立派な速度改善です。
16021597当然ながら、出力が最初のプログラムの実行と一貫性があることをチェックするのは
16031598重要です; ここは Unix システム C<cksum> ユーティリティの出番です。
16041599
16051600 $> cksum out-sort out-schwarz
16061601 3044173777 52029194 out-sort
16071602 3044173777 52029194 out-schwarz
16081603
16091604=begin original
16101605
16111606BTW. Beware too of pressure from managers who see you speed a program up by 50%
16121607of the runtime once, only to get a request one month later to do the same again
16131608(true story) - you'll just have to point out you're only human, even if you are a
16141609Perl programmer, and you'll see what you can do...
16151610
16161611=end original
16171612
16181613ところで。
16191614あなたが一度実行時間を 50% 高速化したのを見た管理者が喜びすぎて、
16201615一ヶ月後にもう一度同じことを要求してくることに注意してください(実話) -
16211616例えあなたが Perl プログラマでもあなたがただの人間であることを
16221617指摘する必要があり、何ができるかを見てみましょう…
16231618
16241619=head1 LOGGING
16251620
16261621(ロギング)
16271622
16281623=begin original
16291624
16301625An essential part of any good development process is appropriate error handling
16311626with appropriately informative messages, however there exists a school of
16321627thought which suggests that log files should be I<chatty>, as if the chain of
16331628unbroken output somehow ensures the survival of the program. If speed is in
16341629any way an issue, this approach is wrong.
16351630
16361631=end original
16371632
16381633良い開発プロセスの本質的な部分は、適切に情報があるメッセージによる
16391634適切なエラー処理ですが、プログラムの生存を確実にするための壊れない
16401635出力のチェーンのように、ログファイルは I<おしゃべり> であるべきという
16411636考え方があります。
16421637速度が問題なら、この手法は間違っています。
16431638
16441639=begin original
16451640
16461641A common sight is code which looks something like this:
16471642
16481643=end original
16491644
16501645よく見かけるのは以下のような感じのコードです:
16511646
16521647 logger->debug( "A logging message via process-id: $$ INC: "
16531648 . Dumper(\%INC) )
16541649
16551650=begin original
16561651
16571652The problem is that this code will always be parsed and executed, even when the
16581653debug level set in the logging configuration file is zero. Once the debug()
16591654subroutine has been entered, and the internal C<$debug> variable confirmed to
16601655be zero, for example, the message which has been sent in will be discarded and
16611656the program will continue. In the example given though, the C<\%INC> hash will
16621657already have been dumped, and the message string constructed, all of which work
16631658could be bypassed by a debug variable at the statement level, like this:
16641659
16651660=end original
16661661
16671662問題は、例えログ設定ファイルのデバッグレベルがゼロでも、このコードは常に
16681663パースされて実行されることです。
16691664例えば、一度 debug() サブルーチンに入って、内部の C<$debug> 変数が
16701665ゼロであることを確認すると、送られたメッセージは捨てられてプログラムは
16711666続行します。
16721667しかし、上述の例では、C<\%INC> はすでにダンプされていて、メッセージ文字列は
16731668構築されていて、このような作業の全ては以下のような文レベルの
16741669デバッグ変数によって回避されるかもしれません:
16751670
16761671 logger->debug( "A logging message via process-id: $$ INC: "
16771672 . Dumper(\%INC) ) if $DEBUG;
16781673
16791674=begin original
16801675
16811676This effect can be demonstrated by setting up a test script with both forms,
16821677including a C<debug()> subroutine to emulate typical C<logger()> functionality.
16831678
16841679=end original
16851680
16861681この効果は、両方の形式で設定したテストスクリプトで図示します;
16871682これには典型的な C<logger()> 機能をエミュレートするための
16881683C<debug()> サブルーチンです。
16891684
16901685=begin original
16911686
16921687# ifdebug
16931688
16941689=end original
16951690
16961691# ifdebug
16971692
16981693 #!/usr/bin/perl
16991694
1700 use strict;
1695 use v5.36;
1701 use warnings;
17021696
17031697 use Benchmark;
17041698 use Data::Dumper;
17051699 my $DEBUG = 0;
17061700
17071701 sub debug {
17081702 my $msg = shift;
17091703
17101704 if ( $DEBUG ) {
17111705 print "DEBUG: $msg\n";
17121706 }
17131707 };
17141708
17151709 timethese(100000, {
17161710 'debug' => sub {
17171711 debug( "A $0 logging message via process-id: $$" . Dumper(\%INC) )
17181712 },
17191713 'ifdebug' => sub {
17201714 debug( "A $0 logging message via process-id: $$" . Dumper(\%INC) ) if $DEBUG
17211715 },
17221716 });
17231717
17241718=begin original
17251719
17261720Let's see what C<Benchmark> makes of this:
17271721
17281722=end original
17291723
17301724これによって C<Benchmark> がすることを見てみましょう:
17311725
17321726 $> perl ifdebug
17331727 Benchmark: timing 100000 iterations of constant, sub...
17341728 ifdebug: 0 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU) @ 10000000.00/s (n=100000)
17351729 (warning: too few iterations for a reliable count)
17361730 debug: 14 wallclock secs (13.18 usr + 0.04 sys = 13.22 CPU) @ 7564.30/s (n=100000)
17371731
17381732=begin original
17391733
17401734In the one case the code, which does exactly the same thing as far as
17411735outputting any debugging information is concerned, in other words nothing,
17421736takes 14 seconds, and in the other case the code takes one hundredth of a
17431737second. Looks fairly definitive. Use a C<$DEBUG> variable BEFORE you call the
17441738subroutine, rather than relying on the smart functionality inside it.
17451739
17461740=end original
17471741
17481742ある場合では、デバッグ情報を出力するのと全く同じ、言い換えると何もしない
17491743コードが 14 秒掛かっています; 他の場合ではコードは 0.01 秒掛かっています。
17501744かなり明確に見えます。
17511745内部のスマートな機能に依存するのではなく、サブルーチンを呼び出す前に
17521746C<$DEBUG> 変数を使ってください。
17531747
17541748=head2 Logging if DEBUG (constant)
17551749
17561750(DEBUG (定数) によるロギング)
17571751
17581752=begin original
17591753
17601754It's possible to take the previous idea a little further, by using a compile
17611755time C<DEBUG> constant.
17621756
17631757=end original
17641758
17651759コンパイル時 C<DEBUG> 定数を使うことで、前述のアイデアをさらに少し
17661760進めることも可能です。
17671761
17681762=begin original
17691763
17701764# ifdebug-constant
17711765
17721766=end original
17731767
17741768# ifdebug-定数
17751769
17761770 #!/usr/bin/perl
17771771
1778 use strict;
1772 use v5.36;
1779 use warnings;
17801773
17811774 use Benchmark;
17821775 use Data::Dumper;
17831776 use constant
17841777 DEBUG => 0
17851778 ;
17861779
17871780 sub debug {
17881781 if ( DEBUG ) {
17891782 my $msg = shift;
17901783 print "DEBUG: $msg\n";
17911784 }
17921785 };
17931786
17941787 timethese(100000, {
17951788 'debug' => sub {
17961789 debug( "A $0 logging message via process-id: $$" . Dumper(\%INC) )
17971790 },
17981791 'constant' => sub {
17991792 debug( "A $0 logging message via process-id: $$" . Dumper(\%INC) ) if DEBUG
18001793 },
18011794 });
18021795
18031796=begin original
18041797
18051798Running this program produces the following output:
18061799
18071800=end original
18081801
18091802このプログラムを実行すると以下の出力が得られます:
18101803
18111804 $> perl ifdebug-constant
18121805 Benchmark: timing 100000 iterations of constant, sub...
18131806 constant: 0 wallclock secs (-0.00 usr + 0.00 sys = -0.00 CPU) @ -7205759403792793600000.00/s (n=100000)
18141807 (warning: too few iterations for a reliable count)
18151808 sub: 14 wallclock secs (13.09 usr + 0.00 sys = 13.09 CPU) @ 7639.42/s (n=100000)
18161809
18171810=begin original
18181811
18191812The C<DEBUG> constant wipes the floor with even the C<$debug> variable,
18201813clocking in at minus zero seconds, and generates a "warning: too few iterations
18211814for a reliable count" message into the bargain. To see what is really going
18221815on, and why we had too few iterations when we thought we asked for 100000, we
18231816can use the very useful C<B::Deparse> to inspect the new code:
18241817
18251818=end original
18261819
18271820C<DEBUG> 定数は C<$debug> 変数に対してでも床掃除をして、マイナスゼロ秒として
18281821記録しています; さらに
18291822"warning: too few iterations for a reliable count" メッセージを生成します。
18301823何が本当に起きているか、そしてなぜ 100000 を聞いたときに反復が
18311824少なすぎるのかを見るために、新しいコードを調べるためにとても有用な
18321825C<B::Deparse> を使えます:
18331826
18341827 $> perl -MO=Deparse ifdebug-constant
18351828
18361829 use Benchmark;
18371830 use Data::Dumper;
18381831 use constant ('DEBUG', 0);
18391832 sub debug {
18401833 use warnings;
18411834 use strict 'refs';
18421835 0;
18431836 }
18441837 use warnings;
18451838 use strict 'refs';
18461839 timethese(100000, {'sub', sub {
18471840 debug "A $0 logging message via process-id: $$" . Dumper(\%INC);
18481841 }
18491842 , 'constant', sub {
18501843 0;
18511844 }
18521845 });
18531846 ifdebug-constant syntax OK
18541847
18551848=begin original
18561849
18571850The output shows the constant() subroutine we're testing being replaced with
18581851the value of the C<DEBUG> constant: zero. The line to be tested has been
18591852completely optimized away, and you can't get much more efficient than that.
18601853
18611854=end original
18621855
18631856出力は、テストしている constant() サブルーチンが C<DEBUG> 定数の値: ゼロに
18641857置き換えられていることを示しています。
18651858テストしたラインは完全に最適化されていて、これ以上すごく効率的にすることは
18661859できません。
18671860
18681861=head1 POSTSCRIPT
18691862
18701863(あとがき)
18711864
18721865=begin original
18731866
18741867This document has provided several way to go about identifying hot-spots, and
18751868checking whether any modifications have improved the runtime of the code.
18761869
18771870=end original
18781871
18791872この文書は、ホットスポットの識別と、どの修正がコードの実行時間を
18801873改善するかのチェックに関するいくつかの方法を提供しました。
18811874
18821875=begin original
18831876
18841877As a final thought, remember that it's not (at the time of writing) possible to
18851878produce a useful program which will run in zero or negative time and this basic
18861879principle can be written as: I<useful programs are slow> by their very
18871880definition. It is of course possible to write a nearly instantaneous program,
18881881but it's not going to do very much, here's a very efficient one:
18891882
18901883=end original
18911884
18921885最後の考慮点として、(これを書いている時点では) ゼロまたは負の時間で
18931886実行できる有用なプログラムを作成することは不可能であることを
18941887忘れないでください; そしてこの基本原則は次のように書けます:
18951888定義により、I<有用なプログラムは遅い>。
18961889もちろんほぼ瞬間的に動作するプログラムを書くことは可能ですが、とても
18971890多くのことをすることは出来ません; 以下はとても効率的なものです:
18981891
18991892 $> perl -e 0
19001893
19011894=begin original
19021895
19031896Optimizing that any further is a job for C<p5p>.
19041897
19051898=end original
19061899
19071900これ以上の最適化は C<p5p> の仕事です。
19081901
19091902=head1 SEE ALSO
19101903
19111904=begin original
19121905
19131906Further reading can be found using the modules and links below.
19141907
19151908=end original
19161909
19171910さらなる読み物は以下のモジュールとリンクを使って得られます。
19181911
19191912=head2 PERLDOCS
19201913
19211914(perldoc)
19221915
19231916=begin original
19241917
19251918For example: C<perldoc -f sort>.
19261919
19271920=end original
19281921
19291922例えば: C<perldoc -f sort>
19301923
19311924L<perlfaq4>.
19321925
19331926L<perlfork>, L<perlfunc>, L<perlretut>, L<perlthrtut>.
19341927
19351928L<threads>.
19361929
19371930=head2 MAN PAGES
19381931
19391932(man ページ)
19401933
19411934C<time>.
19421935
19431936=head2 MODULES
19441937
19451938(モジュール)
19461939
19471940=begin original
19481941
19491942It's not possible to individually showcase all the performance related code for
19501943Perl here, naturally, but here's a short list of modules from the CPAN which
19511944deserve further attention.
19521945
19531946=end original
19541947
19551948当然ながら、Perl で性能に関するコードを全て陳列することは不可能ですが、
19561949以下は CPAN の中からさらなる注目を受けるに値するモジュールの短いリストです。
19571950
19581951 Apache::DProf
19591952 Apache::SmallProf
19601953 Benchmark
19611954 DBIx::Profile
19621955 Devel::AutoProfiler
19631956 Devel::DProf
19641957 Devel::DProfLB
19651958 Devel::FastProf
19661959 Devel::GraphVizProf
19671960 Devel::NYTProf
19681961 Devel::NYTProf::Apache
19691962 Devel::Profiler
19701963 Devel::Profile
19711964 Devel::Profit
19721965 Devel::SmallProf
19731966 Devel::WxProf
19741967 POE::Devel::Profiler
19751968 Sort::Key
19761969 Sort::Maker
19771970
19781971=head2 URLS
19791972
19801973(URL)
19811974
19821975=begin original
19831976
19841977Very useful online reference material:
19851978
19861979=end original
19871980
19881981とても有用なオンラインリファレンス:
19891982
1990 http://www.ccl4.org/~nick/P/Fast_Enough/
1983 https://web.archive.org/web/20120515021937/http://www.ccl4.org/~nick/P/Fast_Enough/
19911984
1992 http://www-128.ibm.com/developerworks/library/l-optperl.html
1985 https://web.archive.org/web/20050706081718/http://www-106.ibm.com/developerworks/library/l-optperl.html
19931986
1994 http://perlbuzz.com/2007/11/bind-output-variables-in-dbi-for-speed-and-safety.html
1987 https://perlbuzz.com/2007/11/14/bind_output_variables_in_dbi_for_speed_and_safety/
19951988
19961989 http://en.wikipedia.org/wiki/Performance_analysis
19971990
19981991 http://apache.perl.org/docs/1.0/guide/performance.html
19991992
20001993 http://perlgolf.sourceforge.net/
20011994
20021995 http://www.sysarch.com/Perl/sort_paper.html
20031996
20041997=head1 AUTHOR
20051998
20061999Richard Foley <richard.foley@rfi.net> Copyright (c) 2008
20072000
20082001=cut
20092002
20102003=begin meta
20112004
20122005Translate: SHIRAKATA Kentaro <argrath@ub32.org>
20132006Status: completed
20142007
20152008=end meta