perlperf > 5.16.1 との差分

perlperf 5.16.1 と 5.20.1 の差分

11
22=encoding euc-jp
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 it's
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
326326 use strict;
327327 use warnings;
328328
329329 use Benchmark;
330330
331331 my $ref = {
332332 'ref' => {
333333 _myscore => '100 + 1',
334334 _yourscore => '102 - 1',
335335 },
336336 };
337337
338338 timethese(1000000, {
339339 'direct' => sub {
340340 my $x = $ref->{ref}->{_myscore} . $ref->{ref}->{_yourscore} ;
341341 },
342342 'dereference' => sub {
343343 my $ref = $ref->{ref};
344344 my $myscore = $ref->{_myscore};
345345 my $yourscore = $ref->{_yourscore};
346346 my $x = $myscore . $yourscore;
347347 },
348348 });
349349
350350=begin original
351351
352352It's essential to run any timing measurements a sufficient number of times so
353353the numbers settle on a numerical average, otherwise each run will naturally
354354fluctuate due to variations in the environment, to reduce the effect of
355355contention for C<CPU> resources and network bandwidth for instance. Running
356356the above code for one million iterations, we can take a look at the report
357357output by the C<Benchmark> module, to see which approach is the most effective.
358358
359359=end original
360360
361361時間計測は、平均を安定させるために十分な回数行うことが重要です;
362362さもなければそれぞれの実行は、例えば C<CPU> リソースの競合の効果や
363363ネットワーク帯域のような環境の変化によって自然に変動します。
364364どの手法が最も効果的を見るために、上述のコードを 100 万回繰り返して、
365365C<Benchmark> モジュールによって出力された報告を見てみます。
366366
367367 $> perl dereference
368368
369369 Benchmark: timing 1000000 iterations of dereference, direct...
370370 dereference: 2 wallclock secs ( 1.59 usr + 0.00 sys = 1.59 CPU) @ 628930.82/s (n=1000000)
371371 direct: 1 wallclock secs ( 1.20 usr + 0.00 sys = 1.20 CPU) @ 833333.33/s (n=1000000)
372372
373373=begin original
374374
375375The difference is clear to see and the dereferencing approach is slower. While
376376it managed to execute an average of 628,930 times a second during our test, the
377377direct approach managed to run an additional 204,403 times, unfortunately.
378378Unfortunately, because there are many examples of code written using the
379379multiple layer direct variable access, and it's usually horrible. It is,
380380however, minusculy faster. The question remains whether the minute gain is
381381actually worth the eyestrain, or the loss of maintainability.
382382
383383=end original
384384
385385違いははっきりと見え、デリファレンスの手法はより遅いです。
386386これはテスト中 1 秒間に平均して 628,930 回実行しましたが、直接手法は
387387残念ながらさらに 204,403 回実行しています。
388388残念ながら、複数層の直接変数アクセスを使ったコード例がたくさんあるので、
389389これは普通は恐ろしいものです。
390390しかし、これはほんの少し速いです。
391391問題は、ほんの少しの向上が疲れ目と保守性の喪失の価値があるかです。
392392
393393=head2 Search and replace or tr
394394
395395(検索と置換または tr)
396396
397397=begin original
398398
399399If we have a string which needs to be modified, while a regex will almost
400400always be much more flexible, C<tr>, an oft underused tool, can still be a
401401useful. One scenario might be replace all vowels with another character. The
402402regex solution might look like this:
403403
404404=end original
405405
406406変更する必要がある文字列がある場合、正規表現はほとんど常により柔軟性が
407407ありますが、活用されていない C<tr> も依然有用です。
408408一つのシナリオとしては、全ての母音を他の文字に置換するというものです。
409409正規表現による解放は以下のようなものになるでしょう:
410410
411411 $str =~ s/[aeiou]/x/g
412412
413413=begin original
414414
415415The C<tr> alternative might look like this:
416416
417417=end original
418418
419419C<tr> による代替案は以下のようになります:
420420
421421 $str =~ tr/aeiou/xxxxx/
422422
423423=begin original
424424
425425We can put that into a test file which we can run to check which approach is
426426the fastest, using a global C<$STR> variable to assign to the C<my $str>
427427variable so as to avoid perl trying to optimize any of the work away by
428428noticing it's assigned only the once.
429429
430430=end original
431431
432432どの手法が一番早いかをチェックするために、実行するテストファイルにこれを
433433置きます; perl が一度しか代入されないことを気付くことで処理しないように
434434最適化しようとすることを避けるために、C<my $str> 変数へ代入するために
435435グローバルな C<$STR> 変数を使います。
436436
437437=begin original
438438
439439# regex-transliterate
440440
441441=end original
442442
443443# 正規表現-文字変換
444444
445445 #!/usr/bin/perl
446446
447447 use strict;
448448 use warnings;
449449
450450 use Benchmark;
451451
452452 my $STR = "$$-this and that";
453453
454454 timethese( 1000000, {
455455 'sr' => sub { my $str = $STR; $str =~ s/[aeiou]/x/g; return $str; },
456456 'tr' => sub { my $str = $STR; $str =~ tr/aeiou/xxxxx/; return $str; },
457457 });
458458
459459=begin original
460460
461461Running the code gives us our results:
462462
463463=end original
464464
465465コードを実行することで結果が得られます:
466466
467467 $> perl regex-transliterate
468468
469469 Benchmark: timing 1000000 iterations of sr, tr...
470470 sr: 2 wallclock secs ( 1.19 usr + 0.00 sys = 1.19 CPU) @ 840336.13/s (n=1000000)
471471 tr: 0 wallclock secs ( 0.49 usr + 0.00 sys = 0.49 CPU) @ 2040816.33/s (n=1000000)
472472
473473=begin original
474474
475475The C<tr> version is a clear winner. One solution is flexible, the other is
476476fast - and it's appropriately the programmer's choice which to use.
477477
478478=end original
479479
480480C<tr> 版が明らかな勝者です。
481481ある解決法は柔軟性があり、他の解決法は高速です - そして適切に
482482どちらを使うかはプログラマの選択です。
483483
484484=begin original
485485
486486Check the C<Benchmark> docs for further useful techniques.
487487
488488=end original
489489
490490さらなる有用なテクニックについては C<Benchmark> の文書を参照してください。
491491
492492=head1 PROFILING TOOLS
493493
494494(プロファイリングツール)
495495
496496=begin original
497497
498498A slightly larger piece of code will provide something on which a profiler can
499499produce more extensive reporting statistics. This example uses the simplistic
500500C<wordmatch> program which parses a given input file and spews out a short
501501report on the contents.
502502
503503=end original
504504
505505やや大きめのコードではプロファイラが生成するより大規模な状況報告が
506506何かを提供するでしょう。
507507この例は、与えられた入力ファイルをパースして、内容の短いレポートを出力する
508508単純な C<wordmatch> プログラムを使います。
509509
510510=begin original
511511
512512# wordmatch
513513
514514=end original
515515
516516# 単語マッチング
517517
518518 #!/usr/bin/perl
519519
520520 use strict;
521521 use warnings;
522522
523523 =head1 NAME
524524
525525 filewords - word analysis of input file
526526
527527 =head1 SYNOPSIS
528528
529529 filewords -f inputfilename [-d]
530530
531531 =head1 DESCRIPTION
532532
533533 This program parses the given filename, specified with C<-f>, and displays a
534534 simple analysis of the words found therein. Use the C<-d> switch to enable
535535 debugging messages.
536536
537537 =cut
538538
539539 use FileHandle;
540540 use Getopt::Long;
541541
542542 my $debug = 0;
543543 my $file = '';
544544
545545 my $result = GetOptions (
546546 'debug' => \$debug,
547547 'file=s' => \$file,
548548 );
549549 die("invalid args") unless $result;
550550
551551 unless ( -f $file ) {
552552 die("Usage: $0 -f filename [-d]");
553553 }
554554 my $FH = FileHandle->new("< $file") or die("unable to open file($file): $!");
555555
556556 my $i_LINES = 0;
557557 my $i_WORDS = 0;
558558 my %count = ();
559559
560560 my @lines = <$FH>;
561561 foreach my $line ( @lines ) {
562562 $i_LINES++;
563563 $line =~ s/\n//;
564564 my @words = split(/ +/, $line);
565565 my $i_words = scalar(@words);
566566 $i_WORDS = $i_WORDS + $i_words;
567567 debug("line: $i_LINES supplying $i_words words: @words");
568568 my $i_word = 0;
569569 foreach my $word ( @words ) {
570570 $i_word++;
571571 $count{$i_LINES}{spec} += matches($i_word, $word, '[^a-zA-Z0-9]');
572572 $count{$i_LINES}{only} += matches($i_word, $word, '^[^a-zA-Z0-9]+$');
573573 $count{$i_LINES}{cons} += matches($i_word, $word, '^[(?i:bcdfghjklmnpqrstvwxyz)]+$');
574574 $count{$i_LINES}{vows} += matches($i_word, $word, '^[(?i:aeiou)]+$');
575575 $count{$i_LINES}{caps} += matches($i_word, $word, '^[(A-Z)]+$');
576576 }
577577 }
578578
579579 print report( %count );
580580
581581 sub matches {
582582 my $i_wd = shift;
583583 my $word = shift;
584584 my $regex = shift;
585585 my $has = 0;
586586
587587 if ( $word =~ /($regex)/ ) {
588588 $has++ if $1;
589589 }
590590
591591 debug("word: $i_wd ".($has ? 'matches' : 'does not match')." chars: /$regex/");
592592
593593 return $has;
594594 }
595595
596596 sub report {
597597 my %report = @_;
598598 my %rep;
599599
600600 foreach my $line ( keys %report ) {
601601 foreach my $key ( keys %{ $report{$line} } ) {
602602 $rep{$key} += $report{$line}{$key};
603603 }
604604 }
605605
606606 my $report = qq|
607607 $0 report for $file:
608608 lines in file: $i_LINES
609609 words in file: $i_WORDS
610610 words with special (non-word) characters: $i_spec
611611 words with only special (non-word) characters: $i_only
612612 words with only consonants: $i_cons
613613 words with only capital letters: $i_caps
614614 words with only vowels: $i_vows
615615 |;
616616
617617 return $report;
618618 }
619619
620620 sub debug {
621621 my $message = shift;
622622
623623 if ( $debug ) {
624624 print STDERR "DBG: $message\n";
625625 }
626626 }
627627
628628 exit 0;
629629
630630=head2 Devel::DProf
631631
632632=begin original
633633
634634This venerable module has been the de-facto standard for Perl code profiling
635635for more than a decade, but has been replaced by a number of other modules
636636which have brought us back to the 21st century. Although you're recommended to
637637evaluate your tool from the several mentioned here and from the CPAN list at
638638the base of this document, (and currently L<Devel::NYTProf> seems to be the
639639weapon of choice - see below), we'll take a quick look at the output from
640640L<Devel::DProf> first, to set a baseline for Perl profiling tools. Run the
641641above program under the control of C<Devel::DProf> by using the C<-d> switch on
642642the command-line.
643643
644644=end original
645645
646646この由緒あるモジュールは 10 年以上 Perl コードプロファイリングのデファクト
647647スタンダードでしたが、21 世紀になって色々なその他のモジュールに
648648置き換えられています。
649649いくつかここで言及されたり、この文書の基礎となる CPAN リストからツールを
650650評価することを勧められていますが、(そして現在のところ L<Devel::NYTProf> が
651651選択する武器のようですが - 後述します)、Perl プロファイリングツールの
652652基本となる L<Devel::DProf> からの出力をまず簡単に見てみます。
653653コマンドラインで C<-d> オプションを使うことで C<Devel::DProf> の制御下で
654654プログラムを実行します。
655655
656656 $> perl -d:DProf wordmatch -f perl5db.pl
657657
658658 <...multiple lines snipped...>
659659
660660 wordmatch report for perl5db.pl:
661661 lines in file: 9428
662662 words in file: 50243
663663 words with special (non-word) characters: 20480
664664 words with only special (non-word) characters: 7790
665665 words with only consonants: 4801
666666 words with only capital letters: 1316
667667 words with only vowels: 1701
668668
669669=begin original
670670
671671C<Devel::DProf> produces a special file, called F<tmon.out> by default, and
672672this file is read by the C<dprofpp> program, which is already installed as part
673673of the C<Devel::DProf> distribution. If you call C<dprofpp> with no options,
674674it will read the F<tmon.out> file in the current directory and produce a human
675675readable statistics report of the run of your program. Note that this may take
676676a little time.
677677
678678=end original
679679
680680C<Devel::DProf> は、デフォルトでは F<tmon.out> という名前の特殊なファイルを
681681出力し、このファイルは C<Devel::DProf> ディストリビューションの一部として
682682既にインストールされている C<dprofpp> プログラムによって読み込まれます。
683683オプションなしで C<dprofpp> を呼び出すと、カレントディレクトリの
684684F<tmon.out> ファイルを読み込んで、あなたのプログラムの実行に関する
685685人間が読める形での統計情報を出力します。
686686これには少し時間がかかるかもしれないことに注意してください。
687687
688688 $> dprofpp
689689
690690 Total Elapsed Time = 2.951677 Seconds
691691 User+System Time = 2.871677 Seconds
692692 Exclusive Times
693693 %Time ExclSec CumulS #Calls sec/call Csec/c Name
694694 102. 2.945 3.003 251215 0.0000 0.0000 main::matches
695695 2.40 0.069 0.069 260643 0.0000 0.0000 main::debug
696696 1.74 0.050 0.050 1 0.0500 0.0500 main::report
697697 1.04 0.030 0.049 4 0.0075 0.0123 main::BEGIN
698698 0.35 0.010 0.010 3 0.0033 0.0033 Exporter::as_heavy
699699 0.35 0.010 0.010 7 0.0014 0.0014 IO::File::BEGIN
700700 0.00 - -0.000 1 - - Getopt::Long::FindOption
701701 0.00 - -0.000 1 - - Symbol::BEGIN
702702 0.00 - -0.000 1 - - Fcntl::BEGIN
703703 0.00 - -0.000 1 - - Fcntl::bootstrap
704704 0.00 - -0.000 1 - - warnings::BEGIN
705705 0.00 - -0.000 1 - - IO::bootstrap
706706 0.00 - -0.000 1 - - Getopt::Long::ConfigDefaults
707707 0.00 - -0.000 1 - - Getopt::Long::Configure
708708 0.00 - -0.000 1 - - Symbol::gensym
709709
710710=begin original
711711
712712C<dprofpp> will produce some quite detailed reporting on the activity of the
713713C<wordmatch> program. The wallclock, user and system, times are at the top of
714714the analysis, and after this are the main columns defining which define the
715715report. Check the C<dprofpp> docs for details of the many options it supports.
716716
717717=end original
718718
719719C<dprofpp> は C<wordmatch> プログラムの活動のかなり詳細な報告を出力します。
720720壁時計時間、ユーザーとシステム時間が分析の先頭にあり、その後は報告を
721721定義する定義で主な列です。
722722対応している多くのオプションの詳細については C<dprofpp> の文書を
723723チェックしてください。
724724
725725=begin original
726726
727727See also C<Apache::DProf> which hooks C<Devel::DProf> into C<mod_perl>.
728728
729729=end original
730730
731731C<Devel::DProf> を C<mod_perl> にフックする C<Apache::DProf> も
732732参照してください。
733733
734734=head2 Devel::Profiler
735735
736736=begin original
737737
738738Let's take a look at the same program using a different profiler:
739739C<Devel::Profiler>, a drop-in Perl-only replacement for C<Devel::DProf>. The
740740usage is very slightly different in that instead of using the special C<-d:>
741741flag, you pull C<Devel::Profiler> in directly as a module using C<-M>.
742742
743743=end original
744744
745745同じプログラムの他のプロファイラによる結果も見てみましょう:
746746C<Devel::Profiler> は C<Devel::DProf> の Perl 専用のドロップインです。
747747使用法は特殊な C<-d:> フラグを使うのとはほんの少し違って、
748748C<Devel::Profiler> を C<-M> を使ってモジュールとして直接読み込みます。
749749
750750 $> perl -MDevel::Profiler wordmatch -f perl5db.pl
751751
752752 <...multiple lines snipped...>
753753
754754 wordmatch report for perl5db.pl:
755755 lines in file: 9428
756756 words in file: 50243
757757 words with special (non-word) characters: 20480
758758 words with only special (non-word) characters: 7790
759759 words with only consonants: 4801
760760 words with only capital letters: 1316
761761 words with only vowels: 1701
762762
763763=begin original
764764
765765C<Devel::Profiler> generates a tmon.out file which is compatible with the
766766C<dprofpp> program, thus saving the construction of a dedicated statistics
767767reader program. C<dprofpp> usage is therefore identical to the above example.
768768
769769=end original
770770
771771C<Devel::Profiler> は C<dprofpp> プログラムと互換性のある tmon.out ファイルを
772772生成するので、専用の統計読み込みプログラムの構築を省略できます。
773773従って C<dprofpp> の使用法は上述の例と同じです。
774774
775775 $> dprofpp
776776
777777 Total Elapsed Time = 20.984 Seconds
778778 User+System Time = 19.981 Seconds
779779 Exclusive Times
780780 %Time ExclSec CumulS #Calls sec/call Csec/c Name
781781 49.0 9.792 14.509 251215 0.0000 0.0001 main::matches
782782 24.4 4.887 4.887 260643 0.0000 0.0000 main::debug
783783 0.25 0.049 0.049 1 0.0490 0.0490 main::report
784784 0.00 0.000 0.000 1 0.0000 0.0000 Getopt::Long::GetOptions
785785 0.00 0.000 0.000 2 0.0000 0.0000 Getopt::Long::ParseOptionSpec
786786 0.00 0.000 0.000 1 0.0000 0.0000 Getopt::Long::FindOption
787787 0.00 0.000 0.000 1 0.0000 0.0000 IO::File::new
788788 0.00 0.000 0.000 1 0.0000 0.0000 IO::Handle::new
789789 0.00 0.000 0.000 1 0.0000 0.0000 Symbol::gensym
790790 0.00 0.000 0.000 1 0.0000 0.0000 IO::File::open
791791
792792=begin original
793793
794794Interestingly we get slightly different results, which is mostly because the
795795algorithm which generates the report is different, even though the output file
796796format was allegedly identical. The elapsed, user and system times are clearly
797797showing the time it took for C<Devel::Profiler> to execute its own run, but
798798the column listings feel more accurate somehow than the ones we had earlier
799799from C<Devel::DProf>. The 102% figure has disappeared, for example. This is
800800where we have to use the tools at our disposal, and recognise their pros and
801801cons, before using them. Interestingly, the numbers of calls for each
802802subroutine are identical in the two reports, it's the percentages which differ.
803803As the author of C<Devel::Proviler> writes:
804804
805805=end original
806806
807807興味深いことに少し異なった結果が得られました; その理由のほとんどは、
808808出力ファイル形式は同一とされているにも関わらず、報告を生成するアルゴリズムが
809809異なることです。
810810経過時間とユーザー+システム時間は明らかに C<Devel::Profiler> が自身の実行で
811811かかった時間を表示してますが、列一覧は先に C<Devel::DProf> で得られたものより
812812いくらかより正確なものに感じられます。
813813例えば、102% の図は消えました。
814814これが、ツールを使ってみて、それらを使う前にそれらの利点と欠点を認識する
815815必要があるところです。
816816興味深いことに、それぞれのサブルーチンの呼び出し回数は二つの報告で
817817同じですが、百分率は異なっています。
818818C<Devel::Proviler> の作者が書いているように:
819819
820820 ...running HTML::Template's test suite under Devel::DProf shows output()
821821 taking NO time but Devel::Profiler shows around 10% of the time is in output().
822822 I don't know which to trust but my gut tells me something is wrong with
823823 Devel::DProf. HTML::Template::output() is a big routine that's called for
824824 every test. Either way, something needs fixing.
825825
826826=begin original
827827
828828YMMV.
829829
830830=end original
831831
832832あなたの意見は違うかもしれません。
833833
834834=begin original
835835
836836See also C<Devel::Apache::Profiler> which hooks C<Devel::Profiler> into C<mod_perl>.
837837
838838=end original
839839
840840C<mod_perl> に C<Devel::Profiler> フックを付ける
841841C<Devel::Apache::Profiler> も参照してください。
842842
843843=head2 Devel::SmallProf
844844
845845=begin original
846846
847847The C<Devel::SmallProf> profiler examines the runtime of your Perl program and
848848produces a line-by-line listing to show how many times each line was called,
849849and how long each line took to execute. It is called by supplying the familiar
850850C<-d> flag to Perl at runtime.
851851
852852=end original
853853
854854C<Devel::SmallProf> プロファイラは Perl プログラムの実行時間を調べて、
855855それぞれの行が何回呼び出されたかをしめす行単位の一覧を出力します。
856856これは実行時に Perl に親しんだ C<-d> フラグを指定することで呼び出されます。
857857
858858 $> perl -d:SmallProf wordmatch -f perl5db.pl
859859
860860 <...multiple lines snipped...>
861861
862862 wordmatch report for perl5db.pl:
863863 lines in file: 9428
864864 words in file: 50243
865865 words with special (non-word) characters: 20480
866866 words with only special (non-word) characters: 7790
867867 words with only consonants: 4801
868868 words with only capital letters: 1316
869869 words with only vowels: 1701
870870
871871=begin original
872872
873873C<Devel::SmallProf> writes it's output into a file called F<smallprof.out>, by
874874default. The format of the file looks like this:
875875
876876=end original
877877
878878C<Devel::SmallProf> は出力を、デフォルトでは F<smallprof.out> と呼ばれる
879879ファイルに書き込みます。
880880ファイルの形式は以下のようなものです:
881881
882882 <num> <time> <ctime> <line>:<text>
883883
884884=begin original
885885
886886When the program has terminated, the output may be examined and sorted using
887887any standard text filtering utilities. Something like the following may be
888888sufficient:
889889
890890=end original
891891
892892プログラムが終了したとき、出力は任意の標準テキストフィルタリング
893893ユーティリティを使って検査とソートが行われます。
894894以下のようなもので十分でしょう:
895895
896896 $> cat smallprof.out | grep \d*: | sort -k3 | tac | head -n20
897897
898898 251215 1.65674 7.68000 75: if ( $word =~ /($regex)/ ) {
899899 251215 0.03264 4.40000 79: debug("word: $i_wd ".($has ? 'matches' :
900900 251215 0.02693 4.10000 81: return $has;
901901 260643 0.02841 4.07000 128: if ( $debug ) {
902902 260643 0.02601 4.04000 126: my $message = shift;
903903 251215 0.02641 3.91000 73: my $has = 0;
904904 251215 0.03311 3.71000 70: my $i_wd = shift;
905905 251215 0.02699 3.69000 72: my $regex = shift;
906906 251215 0.02766 3.68000 71: my $word = shift;
907907 50243 0.59726 1.00000 59: $count{$i_LINES}{cons} =
908908 50243 0.48175 0.92000 61: $count{$i_LINES}{spec} =
909909 50243 0.00644 0.89000 56: my $i_cons = matches($i_word, $word,
910910 50243 0.48837 0.88000 63: $count{$i_LINES}{caps} =
911911 50243 0.00516 0.88000 58: my $i_caps = matches($i_word, $word, '^[(A-
912912 50243 0.00631 0.81000 54: my $i_spec = matches($i_word, $word, '[^a-
913913 50243 0.00496 0.80000 57: my $i_vows = matches($i_word, $word,
914914 50243 0.00688 0.80000 53: $i_word++;
915915 50243 0.48469 0.79000 62: $count{$i_LINES}{only} =
916916 50243 0.48928 0.77000 60: $count{$i_LINES}{vows} =
917917 50243 0.00683 0.75000 55: my $i_only = matches($i_word, $word, '^[^a-
918918
919919=begin original
920920
921921You can immediately see a slightly different focus to the subroutine profiling
922922modules, and we start to see exactly which line of code is taking the most
923923time. That regex line is looking a bit suspicious, for example. Remember that
924924these tools are supposed to be used together, there is no single best way to
925925profile your code, you need to use the best tools for the job.
926926
927927=end original
928928
929929サブルーチンプロファイリングモジュールとは少し異なったフォーカスであることが
930930すぐに分かります; そして正確にコードのどの行が一番時間がかかるかを
931931見始めます。
932932例えば、正規表現行は少し疑わしく見えます。
933933これらのツールは互いに使われることを想定されていて、コードを
934934プロファイリングする単一の最良の方法というのはなく、仕事によって最良の
935935ツールを使う必要があると言うことを忘れないでください。
936936
937937=begin original
938938
939939See also C<Apache::SmallProf> which hooks C<Devel::SmallProf> into C<mod_perl>.
940940
941941=end original
942942
943943C<mod_perl> に C<Devel::SmallProf> フックを付ける C<Apache::SmallProf> も
944944参照してください。
945945
946946=head2 Devel::FastProf
947947
948948=begin original
949949
950950C<Devel::FastProf> is another Perl line profiler. This was written with a view
951951to getting a faster line profiler, than is possible with for example
952952C<Devel::SmallProf>, because it's written in C<C>. To use C<Devel::FastProf>,
953953supply the C<-d> argument to Perl:
954954
955955=end original
956956
957957C<Devel::FastProf> はもう一つの Perl 行プロファイラです。
958958これは、例えば C<Devel::SmallProf> などよりも速い行プロファイラとして
959959C<C> で書かれました。
960960C<Devel::FastProf> を使うには、Perl に C<-d> オプションを指定します:
961961
962962 $> perl -d:FastProf wordmatch -f perl5db.pl
963963
964964 <...multiple lines snipped...>
965965
966966 wordmatch report for perl5db.pl:
967967 lines in file: 9428
968968 words in file: 50243
969969 words with special (non-word) characters: 20480
970970 words with only special (non-word) characters: 7790
971971 words with only consonants: 4801
972972 words with only capital letters: 1316
973973 words with only vowels: 1701
974974
975975=begin original
976976
977977C<Devel::FastProf> writes statistics to the file F<fastprof.out> in the current
978978directory. The output file, which can be specified, can be interpreted by using
979979the C<fprofpp> command-line program.
980980
981981=end original
982982
983983C<Devel::FastProf> は現在のディレクトリのファイル F<fastprof.out> に
984984統計情報を書き込みます。
985985指定可能な出力ファイルは C<fprofpp> コマンドラインプログラムを使って
986986解釈されます。
987987
988988 $> fprofpp | head -n20
989989
990990 # fprofpp output format is:
991991 # filename:line time count: source
992992 wordmatch:75 3.93338 251215: if ( $word =~ /($regex)/ ) {
993993 wordmatch:79 1.77774 251215: debug("word: $i_wd ".($has ? 'matches' : 'does not match')." chars: /$regex/");
994994 wordmatch:81 1.47604 251215: return $has;
995995 wordmatch:126 1.43441 260643: my $message = shift;
996996 wordmatch:128 1.42156 260643: if ( $debug ) {
997997 wordmatch:70 1.36824 251215: my $i_wd = shift;
998998 wordmatch:71 1.36739 251215: my $word = shift;
999999 wordmatch:72 1.35939 251215: my $regex = shift;
10001000
10011001=begin original
10021002
10031003Straightaway we can see that the number of times each line has been called is
10041004identical to the C<Devel::SmallProf> output, and the sequence is only very
10051005slightly different based on the ordering of the amount of time each line took
10061006to execute, C<if ( $debug ) { > and C<my $message = shift;>, for example. The
10071007differences in the actual times recorded might be in the algorithm used
10081008internally, or it could be due to system resource limitations or contention.
10091009
10101010=end original
10111011
10121012直ちに、各行が呼び出された回数が C<Devel::SmallProf> の出力と同じで、並びは
10131013各行の実行時間順を基にして ほんの少しだけ異なる(例えば C<if ( $debug ) { > と
10141014C<my $message = shift;>) ことがわかります。
10151015実際に記録されている時間の違いは内部で使われているアルゴリズムかも
10161016しれませんし、システムリソースの制限や衝突によるかもしれません。
10171017
10181018=begin original
10191019
10201020See also the L<DBIx::Profile> which will profile database queries running
10211021under the C<DBIx::*> namespace.
10221022
10231023=end original
10241024
10251025C<DBIx::*> 名前空間で実行されるデータベース問い合わせをプロファイルする
10261026L<DBIx::Profile> も参照してください。
10271027
10281028=head2 Devel::NYTProf
10291029
10301030=begin original
10311031
10321032C<Devel::NYTProf> is the B<next generation> of Perl code profiler, fixing many
10331033shortcomings in other tools and implementing many cool features. First of all it
10341034can be used as either a I<line> profiler, a I<block> or a I<subroutine>
10351035profiler, all at once. It can also use sub-microsecond (100ns) resolution on
10361036systems which provide C<clock_gettime()>. It can be started and stopped even
10371037by the program being profiled. It's a one-line entry to profile C<mod_perl>
10381038applications. It's written in C<c> and is probably the fastest profiler
10391039available for Perl. The list of coolness just goes on. Enough of that, let's
10401040see how to it works - just use the familiar C<-d> switch to plug it in and run
10411041the code.
10421042
10431043=end original
10441044
10451045C<Devel::NYTProf> は B<新世代> Perl コードプロファイラで、他のツールの
10461046多くの欠点を修正し、多くのクールな機能を実装しています。
10471047まず、これは I<行> プロファイラと I<ブロック> または
10481048I<サブルーチン> プロファイラとして一度に使えます。
10491049また、C<clock_gettime()> を提供しているシステムではマイクロ秒未満 (100ns) の
10501050解像度を使えます。
10511051プログラムがプロファイルからでも開始終了できます。
10521052これは C<mod_perl> アプリケーションをプロファイルする一行エントリです。
10531053これは C<c> で書かれていて、おそらく Perl で利用可能な最速の
10541054プロファイラです。
10551055素晴らしさの一覧はまだ続きます。
10561056これで十分でしょうから、どのように動作するかを見てみましょう - 単に親しんだ
10571057C<-d> スイッチを使って、コードを実行します。
10581058
10591059 $> perl -d:NYTProf wordmatch -f perl5db.pl
10601060
10611061 wordmatch report for perl5db.pl:
10621062 lines in file: 9427
10631063 words in file: 50243
10641064 words with special (non-word) characters: 20480
10651065 words with only special (non-word) characters: 7790
10661066 words with only consonants: 4801
10671067 words with only capital letters: 1316
10681068 words with only vowels: 1701
10691069
10701070=begin original
10711071
10721072C<NYTProf> will generate a report database into the file F<nytprof.out> by
10731073default. Human readable reports can be generated from here by using the
10741074supplied C<nytprofhtml> (HTML output) and C<nytprofcsv> (CSV output) programs.
10751075We've used the Unix system C<html2text> utility to convert the
10761076F<nytprof/index.html> file for convenience here.
10771077
10781078=end original
10791079
10801080C<NYTProf> はデフォルトではファイル F<nytprof.out> にレポートデータベースを
10811081生成します。
10821082人間が読める報告は、提供される C<nytprofhtml> (HTML 出力) または
10831083C<nytprofcsv> (CSV 出力) プログラムを使うことでここから生成されます。
10841084F<nytprof/index.html> ファイルをここで便利なように変換するために Unix
10851085システムの C<html2text> ユーティリティを使っています。
10861086
10871087 $> html2text nytprof/index.html
10881088
10891089 Performance Profile Index
10901090 For wordmatch
10911091 Run on Fri Sep 26 13:46:39 2008
10921092 Reported on Fri Sep 26 13:47:23 2008
10931093
10941094 Top 15 Subroutines -- ordered by exclusive time
10951095 |Calls |P |F |Inclusive|Exclusive|Subroutine |
10961096 | | | |Time |Time | |
10971097 |251215|5 |1 |13.09263 |10.47692 |main:: |matches |
10981098 |260642|2 |1 |2.71199 |2.71199 |main:: |debug |
10991099 |1 |1 |1 |0.21404 |0.21404 |main:: |report |
11001100 |2 |2 |2 |0.00511 |0.00511 |XSLoader:: |load (xsub) |
11011101 |14 |14|7 |0.00304 |0.00298 |Exporter:: |import |
11021102 |3 |1 |1 |0.00265 |0.00254 |Exporter:: |as_heavy |
11031103 |10 |10|4 |0.00140 |0.00140 |vars:: |import |
11041104 |13 |13|1 |0.00129 |0.00109 |constant:: |import |
11051105 |1 |1 |1 |0.00360 |0.00096 |FileHandle:: |import |
11061106 |3 |3 |3 |0.00086 |0.00074 |warnings::register::|import |
11071107 |9 |3 |1 |0.00036 |0.00036 |strict:: |bits |
11081108 |13 |13|13|0.00032 |0.00029 |strict:: |import |
11091109 |2 |2 |2 |0.00020 |0.00020 |warnings:: |import |
11101110 |2 |1 |1 |0.00020 |0.00020 |Getopt::Long:: |ParseOptionSpec|
11111111 |7 |7 |6 |0.00043 |0.00020 |strict:: |unimport |
11121112
11131113 For more information see the full list of 189 subroutines.
11141114
11151115=begin original
11161116
11171117The first part of the report already shows the critical information regarding
11181118which subroutines are using the most time. The next gives some statistics
11191119about the source files profiled.
11201120
11211121=end original
11221122
11231123報告の最初の部分は既に、どのサブルーチンが一番時間がかかっているかという
11241124重要な情報を表示しています。
11251125以下はプロファイリングしたソースファイルに関するいくつかの統計情報です。
11261126
11271127 Source Code Files -- ordered by exclusive time then name
11281128 |Stmts |Exclusive|Avg. |Reports |Source File |
11291129 | |Time | | | |
11301130 |2699761|15.66654 |6e-06 |line . block . sub|wordmatch |
11311131 |35 |0.02187 |0.00062|line . block . sub|IO/Handle.pm |
11321132 |274 |0.01525 |0.00006|line . block . sub|Getopt/Long.pm |
11331133 |20 |0.00585 |0.00029|line . block . sub|Fcntl.pm |
11341134 |128 |0.00340 |0.00003|line . block . sub|Exporter/Heavy.pm |
11351135 |42 |0.00332 |0.00008|line . block . sub|IO/File.pm |
11361136 |261 |0.00308 |0.00001|line . block . sub|Exporter.pm |
11371137 |323 |0.00248 |8e-06 |line . block . sub|constant.pm |
11381138 |12 |0.00246 |0.00021|line . block . sub|File/Spec/Unix.pm |
11391139 |191 |0.00240 |0.00001|line . block . sub|vars.pm |
11401140 |77 |0.00201 |0.00003|line . block . sub|FileHandle.pm |
11411141 |12 |0.00198 |0.00016|line . block . sub|Carp.pm |
11421142 |14 |0.00175 |0.00013|line . block . sub|Symbol.pm |
11431143 |15 |0.00130 |0.00009|line . block . sub|IO.pm |
11441144 |22 |0.00120 |0.00005|line . block . sub|IO/Seekable.pm |
11451145 |198 |0.00085 |4e-06 |line . block . sub|warnings/register.pm|
11461146 |114 |0.00080 |7e-06 |line . block . sub|strict.pm |
11471147 |47 |0.00068 |0.00001|line . block . sub|warnings.pm |
11481148 |27 |0.00054 |0.00002|line . block . sub|overload.pm |
11491149 |9 |0.00047 |0.00005|line . block . sub|SelectSaver.pm |
11501150 |13 |0.00045 |0.00003|line . block . sub|File/Spec.pm |
11511151 |2701595|15.73869 | |Total |
11521152 |128647 |0.74946 | |Average |
11531153 | |0.00201 |0.00003|Median |
11541154 | |0.00121 |0.00003|Deviation |
11551155
11561156 Report produced by the NYTProf 2.03 Perl profiler, developed by Tim Bunce and
11571157 Adam Kaplan.
11581158
11591159=begin original
11601160
11611161At this point, if you're using the I<html> report, you can click through the
11621162various links to bore down into each subroutine and each line of code. Because
11631163we're using the text reporting here, and there's a whole directory full of
11641164reports built for each source file, we'll just display a part of the
11651165corresponding F<wordmatch-line.html> file, sufficient to give an idea of the
11661166sort of output you can expect from this cool tool.
11671167
11681168=end original
11691169
11701170この点で、I<html> レポートを使っているなら、サブルーチン単位と行単位の
11711171詳細への様々なリンクをクリックできます。
11721172ここではテキストレポートを使っていて、それぞれのソースファイルに対して
11731173ビルドされたレポートファイルがディレクトリにたくさんあるので、対応する
11741174F<wordmatch-line.html> ファイルの一部だけを表示します; この素晴らしいツールで
11751175どのような出力が得られるかの考えを与えるには十分です。
11761176
11771177 $> html2text nytprof/wordmatch-line.html
11781178
11791179 Performance Profile -- -block view-.-line view-.-sub view-
11801180 For wordmatch
11811181 Run on Fri Sep 26 13:46:39 2008
11821182 Reported on Fri Sep 26 13:47:22 2008
11831183
11841184 File wordmatch
11851185
11861186 Subroutines -- ordered by exclusive time
11871187 |Calls |P|F|Inclusive|Exclusive|Subroutine |
11881188 | | | |Time |Time | |
11891189 |251215|5|1|13.09263 |10.47692 |main::|matches|
11901190 |260642|2|1|2.71199 |2.71199 |main::|debug |
11911191 |1 |1|1|0.21404 |0.21404 |main::|report |
11921192 |0 |0|0|0 |0 |main::|BEGIN |
11931193
11941194 |Line|Stmts.|Exclusive|Avg. |Code |
11951195 | | |Time | | |
11961196 |1 | | | |#!/usr/bin/perl |
11971197 |2 | | | | |
11981198 | | | | |use strict; |
11991199 |3 |3 |0.00086 |0.00029|# spent 0.00003s making 1 calls to strict:: |
12001200 | | | | |import |
12011201 | | | | |use warnings; |
12021202 |4 |3 |0.01563 |0.00521|# spent 0.00012s making 1 calls to warnings:: |
12031203 | | | | |import |
12041204 |5 | | | | |
12051205 |6 | | | |=head1 NAME |
12061206 |7 | | | | |
12071207 |8 | | | |filewords - word analysis of input file |
12081208 <...snip...>
12091209 |62 |1 |0.00445 |0.00445|print report( %count ); |
12101210 | | | | |# spent 0.21404s making 1 calls to main::report|
12111211 |63 | | | | |
12121212 | | | | |# spent 23.56955s (10.47692+2.61571) within |
12131213 | | | | |main::matches which was called 251215 times, |
12141214 | | | | |avg 0.00005s/call: # 50243 times |
12151215 | | | | |(2.12134+0.51939s) at line 57 of wordmatch, avg|
12161216 | | | | |0.00005s/call # 50243 times (2.17735+0.54550s) |
12171217 |64 | | | |at line 56 of wordmatch, avg 0.00005s/call # |
12181218 | | | | |50243 times (2.10992+0.51797s) at line 58 of |
12191219 | | | | |wordmatch, avg 0.00005s/call # 50243 times |
12201220 | | | | |(2.12696+0.51598s) at line 55 of wordmatch, avg|
12211221 | | | | |0.00005s/call # 50243 times (1.94134+0.51687s) |
12221222 | | | | |at line 54 of wordmatch, avg 0.00005s/call |
12231223 | | | | |sub matches { |
12241224 <...snip...>
12251225 |102 | | | | |
12261226 | | | | |# spent 2.71199s within main::debug which was |
12271227 | | | | |called 260642 times, avg 0.00001s/call: # |
12281228 | | | | |251215 times (2.61571+0s) by main::matches at |
12291229 |103 | | | |line 74 of wordmatch, avg 0.00001s/call # 9427 |
12301230 | | | | |times (0.09628+0s) at line 50 of wordmatch, avg|
12311231 | | | | |0.00001s/call |
12321232 | | | | |sub debug { |
12331233 |104 |260642|0.58496 |2e-06 |my $message = shift; |
12341234 |105 | | | | |
12351235 |106 |260642|1.09917 |4e-06 |if ( $debug ) { |
12361236 |107 | | | |print STDERR "DBG: $message\n"; |
12371237 |108 | | | |} |
12381238 |109 | | | |} |
12391239 |110 | | | | |
12401240 |111 |1 |0.01501 |0.01501|exit 0; |
12411241 |112 | | | | |
12421242
12431243=begin original
12441244
12451245Oodles of very useful information in there - this seems to be the way forward.
12461246
12471247=end original
12481248
12491249大量のとても有用な情報がここにあります - これは前進する道のように思えます。
12501250
12511251=begin original
12521252
12531253See also C<Devel::NYTProf::Apache> which hooks C<Devel::NYTProf> into C<mod_perl>.
12541254
12551255=end original
12561256
12571257C<mod_perl> に C<Devel::NYTProf> フックを付ける C<Devel::NYTProf::Apache> も
12581258参照してください。
12591259
12601260=head1 SORTING
12611261
12621262(ソート)
12631263
12641264=begin original
12651265
12661266Perl modules are not the only tools a performance analyst has at their
12671267disposal, system tools like C<time> should not be overlooked as the next
12681268example shows, where we take a quick look at sorting. Many books, theses and
12691269articles, have been written about efficient sorting algorithms, and this is not
12701270the place to repeat such work, there's several good sorting modules which
12711271deserve taking a look at too: C<Sort::Maker>, C<Sort::Key> spring to mind.
12721272However, it's still possible to make some observations on certain Perl specific
12731273interpretations on issues relating to sorting data sets and give an example or
12741274two with regard to how sorting large data volumes can effect performance.
12751275Firstly, an often overlooked point when sorting large amounts of data, one can
12761276attempt to reduce the data set to be dealt with and in many cases C<grep()> can
12771277be quite useful as a simple filter:
12781278
12791279=end original
12801280
12811281Perl モジュールは性能分析者が持っている唯一の道具というわけではなく、
12821282ソートについて軽く見てみる次の例のように、C<time> のようなシステムツールも
12831283見落とすべきではありません。
12841284効率的なソートアルゴリズムについて書かれている多くの多くの本、論文、記事が
12851285あり、ここはそのようなことを繰り返す場所ではありません; 調べてみる価値のある
12861286いくつかのよいソートモジュールもあります: C<Sort::Maker>, C<Sort::Key> が
12871287思い浮かびます。
12881288しかし、まだデータ集合のソートに関連する問題の Perl 特有の解釈に関して
12891289いくつか観測できる可能性があるので、大量のデータがどのように性能に
12901290影響するかに関する例をいくつか示します。
12911291最初に、大量のデータをソートするときにしばしば見落とされる点は、扱うデータ
12921292集合を減らそうと出来ることと、多くの場合 C<grep()> が単純なフィルタとして
12931293かなり有用であるということです:
12941294
12951295 @data = sort grep { /$filter/ } @incoming
12961296
12971297=begin original
12981298
12991299A command such as this can vastly reduce the volume of material to actually
13001300sort through in the first place, and should not be too lightly disregarded
13011301purely on the basis of its simplicity. The C<KISS> principle is too often
13021302overlooked - the next example uses the simple system C<time> utility to
13031303demonstrate. Let's take a look at an actual example of sorting the contents of
13041304a large file, an apache logfile would do. This one has over a quarter of a
13051305million lines, is 50M in size, and a snippet of it looks like this:
13061306
13071307=end original
13081308
13091309このようなコマンドは最初に実際にソートする量をとても減らすことが出来、
13101310単純性の原則だけであまり簡単に無視するべきではありません。
13111311C<KISS> 原則はあまりにも見逃されています - 次の例はデモに単純なシステム
13121312C<time> ユーティリティを使います。
13131313大きなファイルの内容をソートするという実際の例を見てみましょう; apache の
13141314ログファイルを使ってみます。
13151315これは 25 万行 50M バイトを超えますが、その一部は以下のようなものです:
13161316
13171317=begin original
13181318
13191319# logfile
13201320
13211321=end original
13221322
13231323# ログファイル
13241324
13251325 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)"
13261326 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)"
13271327 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"
13281328 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"
13291329 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"
13301330 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)"
13311331 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)"
13321332 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)"
13331333 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)"
13341334 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)"
13351335 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"
13361336 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"
13371337 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"
13381338 crawl1.cosmixcorp.com - - [08/Feb/2007:13:27:57 +0000] "GET /robots.txt HTTP/1.0" 200 179 "-" "voyager/1.0"
13391339 crawl1.cosmixcorp.com - - [08/Feb/2007:13:28:25 +0000] "GET /links.html HTTP/1.0" 200 3413 "-" "voyager/1.0"
13401340 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)"
13411341 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)"
13421342 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)"
13431343 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)"
13441344 pop.compuscan.co.za - - [08/Feb/2007:14:10:43 +0000] "GET / HTTP/1.1" 200 3309 "-" "www.clamav.net"
13451345 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)"
13461346 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)"
13471347 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"
13481348 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"
13491349
13501350=begin original
13511351
13521352The specific task here is to sort the 286,525 lines of this file by Response
13531353Code, Query, Browser, Referring Url, and lastly Date. One solution might be to
13541354use the following code, which iterates over the files given on the
13551355command-line.
13561356
13571357=end original
13581358
13591359ここでのタスクは Response Code, Query, Browser, Referring Url,
13601360lastly Date からなる 286,525 行のファイルをソートすることです。
13611361一つの解決法は、以下のコードのようにコマンドラインで指定されたファイルを
13621362反復する方法かもしれません。
13631363
13641364=begin original
13651365
13661366# sort-apache-log
13671367
13681368=end original
13691369
13701370# apache のログのソート
13711371
13721372 #!/usr/bin/perl -n
13731373
13741374 use strict;
13751375 use warnings;
13761376
13771377 my @data;
13781378
13791379 LINE:
13801380 while ( <> ) {
13811381 my $line = $_;
13821382 if (
13831383 $line =~ m/^(
13841384 ([\w\.\-]+) # client
13851385 \s*-\s*-\s*\[
13861386 ([^]]+) # date
13871387 \]\s*"\w+\s*
13881388 (\S+) # query
13891389 [^"]+"\s*
13901390 (\d+) # status
13911391 \s+\S+\s+"[^"]*"\s+"
13921392 ([^"]*) # browser
13931393 "
13941394 .*
13951395 )$/x
13961396 ) {
13971397 my @chunks = split(/ +/, $line);
13981398 my $ip = $1;
13991399 my $date = $2;
14001400 my $query = $3;
14011401 my $status = $4;
14021402 my $browser = $5;
14031403
14041404 push(@data, [$ip, $date, $query, $status, $browser, $line]);
14051405 }
14061406 }
14071407
14081408 my @sorted = sort {
14091409 $a->[3] cmp $b->[3]
14101410 ||
14111411 $a->[2] cmp $b->[2]
14121412 ||
14131413 $a->[0] cmp $b->[0]
14141414 ||
14151415 $a->[1] cmp $b->[1]
14161416 ||
14171417 $a->[4] cmp $b->[4]
14181418 } @data;
14191419
14201420 foreach my $data ( @sorted ) {
14211421 print $data->[5];
14221422 }
14231423
14241424 exit 0;
14251425
14261426=begin original
14271427
14281428When running this program, redirect C<STDOUT> so it is possible to check the
14291429output is correct from following test runs and use the system C<time> utility
14301430to check the overall runtime.
14311431
14321432=end original
14331433
14341434このプログラムを実行するとき、以後のテストで出力が正しいか
14351435チェックできるように C<STDOUT> をリダイレクトして、全体の実行時間を
14361436チェックするためにシステムの C<time> ユーティリティを使います。
14371437
14381438 $> time ./sort-apache-log logfile > out-sort
14391439
14401440 real 0m17.371s
14411441 user 0m15.757s
14421442 sys 0m0.592s
14431443
14441444=begin original
14451445
14461446The program took just over 17 wallclock seconds to run. Note the different
14471447values C<time> outputs, it's important to always use the same one, and to not
14481448confuse what each one means.
14491449
14501450=end original
14511451
14521452プログラムは実行にちょうど 17 壁時計秒ほどかかりました。
14531453C<time> 出力の異なった値に注意して、いつも同じものを使い、それぞれの値の
14541454意味を混乱しないことが重要です。
14551455
14561456=over 4
14571457
14581458=item Elapsed Real Time
14591459
14601460(実経過時間)
14611461
14621462=begin original
14631463
14641464The overall, or wallclock, time between when C<time> was called, and when it
14651465terminates. The elapsed time includes both user and system times, and time
14661466spent waiting for other users and processes on the system. Inevitably, this is
14671467the most approximate of the measurements given.
14681468
14691469=end original
14701470
14711471C<time> が呼び出されてからそれが終了するまでの間の全体的な、あるいは
14721472壁時計の、時間です。
14731473経過時間にはユーザー時間とシステム時間、およびシステム上の他のユーザーや
14741474プロセスを待つために費やされた時間を含みます。
14751475必然的に、これは与えられたものに最も近い時間です。
14761476
14771477=item User CPU Time
14781478
14791479(ユーザー CPU 時間)
14801480
14811481=begin original
14821482
14831483The user time is the amount of time the entire process spent on behalf of the
14841484user on this system executing this program.
14851485
14861486=end original
14871487
14881488ユーザー時間はこのシステムでこのプログラムを実行することで消費された
14891489全体のプロセス時間です。
14901490
14911491=item System CPU Time
14921492
14931493(システム CPU 時間)
14941494
14951495=begin original
14961496
14971497The system time is the amount of time the kernel itself spent executing
14981498routines, or system calls, on behalf of this process user.
14991499
15001500=end original
15011501
15021502システム時間はこのプロセスユーザーのためにカーネルが実行したルーチンや
15031503システムコールの時間です。
15041504
15051505=back
15061506
15071507=begin original
15081508
15091509Running this same process as a C<Schwarzian Transform> it is possible to
15101510eliminate the input and output arrays for storing all the data, and work on the
15111511input directly as it arrives too. Otherwise, the code looks fairly similar:
15121512
15131513=end original
15141514
15151515同じ処理を C<シュワルツ変換> (Schwarzian Transform) として実行すると、
15161516全てのデータを補完するための配列の入出力を除去することができ、
15171517入力を直接届いてすぐに処理します。
15181518さもなければ、コードはほぼ似て見えます:
15191519
15201520=begin original
15211521
15221522# sort-apache-log-schwarzian
15231523
15241524=end original
15251525
15261526# apache のログをシュワルツ変換ソート
15271527
15281528 #!/usr/bin/perl -n
15291529
15301530 use strict;
15311531 use warnings;
15321532
15331533 print
15341534
15351535 map $_->[0] =>
15361536
15371537 sort {
15381538 $a->[4] cmp $b->[4]
15391539 ||
15401540 $a->[3] cmp $b->[3]
15411541 ||
15421542 $a->[1] cmp $b->[1]
15431543 ||
15441544 $a->[2] cmp $b->[2]
15451545 ||
15461546 $a->[5] cmp $b->[5]
15471547 }
15481548 map [ $_, m/^(
15491549 ([\w\.\-]+) # client
15501550 \s*-\s*-\s*\[
15511551 ([^]]+) # date
15521552 \]\s*"\w+\s*
15531553 (\S+) # query
15541554 [^"]+"\s*
15551555 (\d+) # status
15561556 \s+\S+\s+"[^"]*"\s+"
15571557 ([^"]*) # browser
15581558 "
15591559 .*
15601560 )$/xo ]
15611561
15621562 => <>;
15631563
15641564 exit 0;
15651565
15661566=begin original
15671567
15681568Run the new code against the same logfile, as above, to check the new time.
15691569
15701570=end original
15711571
15721572新しい時間をチェックするために上述のように同じログファイルに対して
15731573新しいコードを実行します。
15741574
15751575 $> time ./sort-apache-log-schwarzian logfile > out-schwarz
15761576
15771577 real 0m9.664s
15781578 user 0m8.873s
15791579 sys 0m0.704s
15801580
15811581=begin original
15821582
15831583The time has been cut in half, which is a respectable speed improvement by any
15841584standard. Naturally, it is important to check the output is consistent with
15851585the first program run, this is where the Unix system C<cksum> utility comes in.
15861586
15871587=end original
15881588
15891589時間は半分になりました; これはあらゆる面で立派な速度改善です。
15901590当然ながら、出力が最初のプログラムの実行と一貫性があることをチェックするのは
15911591重要です; ここは Unix システム C<cksum> ユーティリティの出番です。
15921592
15931593 $> cksum out-sort out-schwarz
15941594 3044173777 52029194 out-sort
15951595 3044173777 52029194 out-schwarz
15961596
15971597=begin original
15981598
15991599BTW. Beware too of pressure from managers who see you speed a program up by 50%
16001600of the runtime once, only to get a request one month later to do the same again
16011601(true story) - you'll just have to point out your only human, even if you are a
16021602Perl programmer, and you'll see what you can do...
16031603
16041604=end original
16051605
16061606ところで。
16071607あなたが一度実行時間を 50% 高速化したのを見た管理者が喜びすぎて、
16081608一ヶ月後にもう一度同じことを要求してくることに注意してください(実話) -
16091609例えあなたが Perl プログラマでもあなたがただの人間であることを
16101610指摘する必要があり、何ができるかを見てみましょう…
16111611
16121612=head1 LOGGING
16131613
16141614(ロギング)
16151615
16161616=begin original
16171617
16181618An essential part of any good development process is appropriate error handling
16191619with appropriately informative messages, however there exists a school of
16201620thought which suggests that log files should be I<chatty>, as if the chain of
16211621unbroken output somehow ensures the survival of the program. If speed is in
16221622any way an issue, this approach is wrong.
16231623
16241624=end original
16251625
16261626良い開発プロセスの本質的な部分は、適切に情報があるメッセージによる
16271627適切なエラー処理ですが、プログラムの生存を確実にするための壊れない
16281628出力のチェーンのように、ログファイルは I<おしゃべり> であるべきという
16291629考え方があります。
16301630速度が問題なら、この手法は間違っています。
16311631
16321632=begin original
16331633
16341634A common sight is code which looks something like this:
16351635
16361636=end original
16371637
16381638よく見かけるのは以下のような感じのコードです:
16391639
16401640 logger->debug( "A logging message via process-id: $$ INC: " . Dumper(\%INC) )
16411641
16421642=begin original
16431643
16441644The problem is that this code will always be parsed and executed, even when the
16451645debug level set in the logging configuration file is zero. Once the debug()
16461646subroutine has been entered, and the internal C<$debug> variable confirmed to
16471647be zero, for example, the message which has been sent in will be discarded and
16481648the program will continue. In the example given though, the \%INC hash will
16491649already have been dumped, and the message string constructed, all of which work
16501650could be bypassed by a debug variable at the statement level, like this:
16511651
16521652=end original
16531653
16541654問題は、例えログ設定ファイルのデバッグレベルがゼロでも、このコードは常に
16551655パースされて実行されることです。
16561656例えば、一度 debug() サブルーチンに入って、内部の C<$debug> 変数が
16571657ゼロであることを確認すると、送られたメッセージは捨てられてプログラムは
16581658続行します。
16591659しかし、上述の例では、\%INC はすでにダンプされていて、メッセージ文字列は
16601660構築されていて、このような作業の全ては以下のような文レベルの
16611661デバッグ変数によって回避されるかもしれません:
16621662
16631663 logger->debug( "A logging message via process-id: $$ INC: " . Dumper(\%INC) ) if $DEBUG;
16641664
16651665=begin original
16661666
16671667This effect can be demonstrated by setting up a test script with both forms,
16681668including a C<debug()> subroutine to emulate typical C<logger()> functionality.
16691669
16701670=end original
16711671
16721672この効果は、両方の形式で設定したテストスクリプトで図示します;
16731673これには典型的な C<logger()> 機能をエミュレートするための
16741674C<debug()> サブルーチンです。
16751675
16761676=begin original
16771677
16781678# ifdebug
16791679
16801680=end original
16811681
16821682# ifdebug
16831683
16841684 #!/usr/bin/perl
16851685
16861686 use strict;
16871687 use warnings;
16881688
16891689 use Benchmark;
16901690 use Data::Dumper;
16911691 my $DEBUG = 0;
16921692
16931693 sub debug {
16941694 my $msg = shift;
16951695
16961696 if ( $DEBUG ) {
16971697 print "DEBUG: $msg\n";
16981698 }
16991699 };
17001700
17011701 timethese(100000, {
17021702 'debug' => sub {
17031703 debug( "A $0 logging message via process-id: $$" . Dumper(\%INC) )
17041704 },
17051705 'ifdebug' => sub {
17061706 debug( "A $0 logging message via process-id: $$" . Dumper(\%INC) ) if $DEBUG
17071707 },
17081708 });
17091709
17101710=begin original
17111711
17121712Let's see what C<Benchmark> makes of this:
17131713
17141714=end original
17151715
17161716これによって C<Benchmark> がすることを見てみましょう:
17171717
17181718 $> perl ifdebug
17191719 Benchmark: timing 100000 iterations of constant, sub...
17201720 ifdebug: 0 wallclock secs ( 0.01 usr + 0.00 sys = 0.01 CPU) @ 10000000.00/s (n=100000)
17211721 (warning: too few iterations for a reliable count)
17221722 debug: 14 wallclock secs (13.18 usr + 0.04 sys = 13.22 CPU) @ 7564.30/s (n=100000)
17231723
17241724=begin original
17251725
17261726In the one case the code, which does exactly the same thing as far as
17271727outputting any debugging information is concerned, in other words nothing,
17281728takes 14 seconds, and in the other case the code takes one hundredth of a
17291729second. Looks fairly definitive. Use a C<$DEBUG> variable BEFORE you call the
17301730subroutine, rather than relying on the smart functionality inside it.
17311731
17321732=end original
17331733
17341734ある場合では、デバッグ情報を出力するのと全く同じ、言い換えると何もしない
17351735コードが 14 秒掛かっています; 他の場合ではコードは 0.01 秒掛かっています。
17361736かなり明確に見えます。
17371737内部のスマートな機能に依存するのではなく、サブルーチンを呼び出す前に
17381738C<$DEBUG> 変数を使ってください。
17391739
17401740=head2 Logging if DEBUG (constant)
17411741
17421742(DEBUG (定数) によるロギング)
17431743
17441744=begin original
17451745
17461746It's possible to take the previous idea a little further, by using a compile
17471747time C<DEBUG> constant.
17481748
17491749=end original
17501750
17511751コンパイル時 C<DEBUG> 定数を使うことで、前述のアイデアをさらに少し
17521752進めることも可能です。
17531753
17541754=begin original
17551755
17561756# ifdebug-constant
17571757
17581758=end original
17591759
17601760# ifdebug-定数
17611761
17621762 #!/usr/bin/perl
17631763
17641764 use strict;
17651765 use warnings;
17661766
17671767 use Benchmark;
17681768 use Data::Dumper;
17691769 use constant
17701770 DEBUG => 0
17711771 ;
17721772
17731773 sub debug {
17741774 if ( DEBUG ) {
17751775 my $msg = shift;
17761776 print "DEBUG: $msg\n";
17771777 }
17781778 };
17791779
17801780 timethese(100000, {
17811781 'debug' => sub {
17821782 debug( "A $0 logging message via process-id: $$" . Dumper(\%INC) )
17831783 },
17841784 'constant' => sub {
17851785 debug( "A $0 logging message via process-id: $$" . Dumper(\%INC) ) if DEBUG
17861786 },
17871787 });
17881788
17891789=begin original
17901790
17911791Running this program produces the following output:
17921792
17931793=end original
17941794
17951795このプログラムを実行すると以下の出力が得られます:
17961796
17971797 $> perl ifdebug-constant
17981798 Benchmark: timing 100000 iterations of constant, sub...
17991799 constant: 0 wallclock secs (-0.00 usr + 0.00 sys = -0.00 CPU) @ -7205759403792793600000.00/s (n=100000)
18001800 (warning: too few iterations for a reliable count)
18011801 sub: 14 wallclock secs (13.09 usr + 0.00 sys = 13.09 CPU) @ 7639.42/s (n=100000)
18021802
18031803=begin original
18041804
18051805The C<DEBUG> constant wipes the floor with even the C<$debug> variable,
18061806clocking in at minus zero seconds, and generates a "warning: too few iterations
18071807for a reliable count" message into the bargain. To see what is really going
18081808on, and why we had too few iterations when we thought we asked for 100000, we
18091809can use the very useful C<B::Deparse> to inspect the new code:
18101810
18111811=end original
18121812
18131813C<DEBUG> 定数は C<$debug> 変数に対してでも床掃除をして、マイナスゼロ秒として
18141814記録しています; さらに
18151815"warning: too few iterations for a reliable count" メッセージを生成します。
18161816何が本当に起きているか、そしてなぜ 100000 を聞いたときに反復が
18171817少なすぎるのかを見るために、新しいコードを調べるためにとても有用な
18181818C<B::Deparse> を使えます:
18191819
18201820 $> perl -MO=Deparse ifdebug-constant
18211821
18221822 use Benchmark;
18231823 use Data::Dumper;
18241824 use constant ('DEBUG', 0);
18251825 sub debug {
18261826 use warnings;
18271827 use strict 'refs';
18281828 0;
18291829 }
18301830 use warnings;
18311831 use strict 'refs';
18321832 timethese(100000, {'sub', sub {
18331833 debug "A $0 logging message via process-id: $$" . Dumper(\%INC);
18341834 }
18351835 , 'constant', sub {
18361836 0;
18371837 }
18381838 });
18391839 ifdebug-constant syntax OK
18401840
18411841=begin original
18421842
18431843The output shows the constant() subroutine we're testing being replaced with
18441844the value of the C<DEBUG> constant: zero. The line to be tested has been
18451845completely optimized away, and you can't get much more efficient than that.
18461846
18471847=end original
18481848
18491849出力は、テストしている constant() サブルーチンが C<DEBUG> 定数の値: ゼロに
18501850置き換えられていることを示しています。
18511851テストしたラインは完全に最適化されていて、これ以上すごく効率的にすることは
18521852できません。
18531853
18541854=head1 POSTSCRIPT
18551855
18561856(あとがき)
18571857
18581858=begin original
18591859
18601860This document has provided several way to go about identifying hot-spots, and
18611861checking whether any modifications have improved the runtime of the code.
18621862
18631863=end original
18641864
18651865この文書は、ホットスポットの識別と、どの修正がコードの実行時間を
18661866改善するかのチェックに関するいくつかの方法を提供しました。
18671867
18681868=begin original
18691869
18701870As a final thought, remember that it's not (at the time of writing) possible to
18711871produce a useful program which will run in zero or negative time and this basic
18721872principle can be written as: I<useful programs are slow> by their very
18731873definition. It is of course possible to write a nearly instantaneous program,
18741874but it's not going to do very much, here's a very efficient one:
18751875
18761876=end original
18771877
18781878最後の考慮点として、(これを書いている時点では) ゼロまたは負の時間で
18791879実行できる有用なプログラムを作成することは不可能であることを
18801880忘れないでください; そしてこの基本原則は次のように書けます:
18811881定義により、I<有用なプログラムは遅い>。
18821882もちろんほぼ瞬間的に動作するプログラムを書くことは可能ですが、とても
18831883多くのことをすることは出来ません; 以下はとても効率的なものです:
18841884
18851885 $> perl -e 0
18861886
18871887=begin original
18881888
18891889Optimizing that any further is a job for C<p5p>.
18901890
18911891=end original
18921892
18931893これ以上の最適化は C<p5p> の仕事です。
18941894
18951895=head1 SEE ALSO
18961896
18971897=begin original
18981898
18991899Further reading can be found using the modules and links below.
19001900
19011901=end original
19021902
19031903さらなる読み物は以下のモジュールとリンクを使って得られます。
19041904
19051905=head2 PERLDOCS
19061906
19071907(perldoc)
19081908
19091909=begin original
19101910
19111911For example: C<perldoc -f sort>.
19121912
19131913=end original
19141914
19151915例えば: C<perldoc -f sort>
19161916
19171917L<perlfaq4>.
19181918
19191919L<perlfork>, L<perlfunc>, L<perlretut>, L<perlthrtut>.
19201920
19211921L<threads>.
19221922
19231923=head2 MAN PAGES
19241924
19251925(man ページ)
19261926
19271927C<time>.
19281928
19291929=head2 MODULES
19301930
19311931(モジュール)
19321932
19331933=begin original
19341934
19351935It's not possible to individually showcase all the performance related code for
19361936Perl here, naturally, but here's a short list of modules from the CPAN which
19371937deserve further attention.
19381938
19391939=end original
19401940
19411941当然ながら、Perl で性能に関するコードを全て陳列することは不可能ですが、
19421942以下は CPAN の中からさらなる注目を受けるに値するモジュールの短いリストです。
19431943
19441944 Apache::DProf
19451945 Apache::SmallProf
19461946 Benchmark
19471947 DBIx::Profile
19481948 Devel::AutoProfiler
19491949 Devel::DProf
19501950 Devel::DProfLB
19511951 Devel::FastProf
19521952 Devel::GraphVizProf
19531953 Devel::NYTProf
19541954 Devel::NYTProf::Apache
19551955 Devel::Profiler
19561956 Devel::Profile
19571957 Devel::Profit
19581958 Devel::SmallProf
19591959 Devel::WxProf
19601960 POE::Devel::Profiler
19611961 Sort::Key
19621962 Sort::Maker
19631963
19641964=head2 URLS
19651965
19661966(URL)
19671967
19681968=begin original
19691969
19701970Very useful online reference material:
19711971
19721972=end original
19731973
19741974とても有用なオンラインリファレンス:
19751975
19761976 http://www.ccl4.org/~nick/P/Fast_Enough/
19771977
19781978 http://www-128.ibm.com/developerworks/library/l-optperl.html
19791979
19801980 http://perlbuzz.com/2007/11/bind-output-variables-in-dbi-for-speed-and-safety.html
19811981
19821982 http://en.wikipedia.org/wiki/Performance_analysis
19831983
19841984 http://apache.perl.org/docs/1.0/guide/performance.html
19851985
19861986 http://perlgolf.sourceforge.net/
19871987
19881988 http://www.sysarch.com/Perl/sort_paper.html
19891989
19901990=head1 AUTHOR
19911991
19921992Richard Foley <richard.foley@rfi.net> Copyright (c) 2008
19931993
19941994=cut
19951995
19961996=begin meta
19971997
19981998Translate: SHIRAKATA Kentaro <argrath@ub32.org>
19991999Status: completed
20002000
20012001=end meta