本を買ってから「効率的なソース」について考えるようになった。とはいっても、数回の実行では目に見えて変わる事はないけど。
で、「サブディレクトリ内も一覧(その2)」を見てしまって「これはちょっと・・・」と思った(コスト表示した「その2」)。
で、ほぼ同じ物を新しく作ってみたら、時間が約半分になった(当社比)。結果的に「readdir」を一回で済むようにしたのが効いたのかもしれない。少なくとも、その発想が出ただけでも良しとしよう。
ただ、以前は使っていなかった「リファレンス」を使うようにしたので、ファイル数やディレクトリが多くなると、もっと短くなるかもしれない。
・・・と思ってやってみた。条件と結果は、以下のようになりました。
|
|
タイプ1 |
|
|
タイプ2 |
|
|
|
ts0014p |
ts0025 |
|
ts0014p |
ts0025 |
総フォルダ数 |
70 |
10.44 |
5.82 |
36 |
2.80 |
2.25 |
総ファイル数 |
4,631 |
|
|
424 |
|
|
総ファイルサイズ(バイト) |
12,843,625 |
|
|
1,746,391 |
|
|
HTMLファイル数 |
419 |
|
|
252 |
|
|
HTMLファイルサイズ(バイト) |
2,314,124 |
|
|
882,760 |
|
|
これだけで決めてしまうのはよくないけど、ファイル数が多いと「readdir」の回数が効いてくるようだ。でも、HTMLファイルの比率が高い場合は、それほど差がつかないのがちょっと残念。
ところで、「dumpvar.pl」と「dumpValueサブルーチン」は、(「リファレンス」を含む)配列、ハッシュを把握するのにとても役に立つパッケージで、「ActivePerl522」にはついている。これも前述の「実用 Perlプログラミング」に載っていたんだけど、実は非公開(非公式?)のパッケージらしい。
このサブルーチンを使うと、深い階層の配列やハッシュの値が、整形されて表示される。複雑な形式の変数を扱うときは、これで確認しながら作っていくと、デバッグもしやすいのでお奨めです。
使用する方法は、まず「dumpvar.pl」を「require」します。これは標準の「@INC」に入っていると思うので、探す必要はないと思います。そして、そのパッケージ内に存在する「dumpValue」サブルーチンに、表示したい配列、またはハッシュを「リファレンス」で渡します。すると、あら不思議。デバッグに有効な情報が手に入る。というわけです。是非試してみてください。
・・・ちょっと欠陥(ディレクトリ名が正しく取れない事があったみたいです)を見つけてしまったので、訂正しました。すると、悲しいかな、差が縮んでしまいました (T_T)
ただ、「ts0014p」にも新しい欠陥(ディレクトリの字下げが正しく行なわれていないみたいです)を見つけてしまったのですが・・・。
多少条件が変わりましたが、とりあえず、新しい結果を・・・。
|
タイプ1 |
タイプ2 |
ts0014p |
11.15 |
2.80 |
ts0025 |
9.88 |
2.31 |
「タイプ1」が、かなり遅くなってしまいました。ディレクトリ情報を収集するだけで「6秒」ほどかかってしまいます。訂正方法が良くなかったのかもしれません。ディレクトリとファイルの区別を、もっと簡潔にできないものでしょうか・・・。
・・・
今回、ローカル環境から完全に移行するために「jcode.pl」に変更しました。
ついでに、リンク先も付け加えたのですが・・・。ハッシュは順不同で呼び出されるので、見事にリンクの順番が変わってしまいました・・・。いくつか先に、配列を2つ使ってリンクを作成するスクリプトがあるはずなので、これは愛嬌ということに・・・ (^^;;;
ここから追記(2000/12/14)
ハッシュは、順不同で呼び出される、じゃなくて、取り出しやすいように順不同で格納される、が正解。呼び出した結果だけ見れば同じようなものだけど・・・。
ソースコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
|
#!/usr/bin/perl
#BEGIN{
# print "Content-type: text/plainnn";
# open(STDERR, ">&STDOUT");
# $|=1;
#}
$timeBegin = times;
# use Jcode;
require '../../../cgi-bin/jcode.pl';
$info_mailName = 'Nobu3';
$info_mailAddr = 'nobu3@x.age.ne.jp';
$info_uriName = 'Incomprehensible Perl Project';
$info_uriAddr = 'http://www.age.ne.jp/x/nobu3/perl/';
$info_uri = qq(<a href="$info_uriAddr">$info_uriName</a>.);
$info_mail = qq((C)1999 <a href="mailto:$info_mailAddr">$info_mailName</a>. All rights reserved.);
$info_copyright = "<address>n<font face=times>$info_uri<br>n$info_mail</font><br>n</address>n";
# @usr_stylesheet = ('/Nobu3/ipp.css','../test.css');# できあがりからのURIパス
@usr_stylesheet = ('../../ipp.css', '../test.css');
$usr_outcode = 'jis';
$usr_outCharset = 'iso-2022-jp';
$usr_title = 'テスト25';
$explain = $ENV{SCRIPT_NAME};
$explain =~ s|cgi/(ts[0-9]{4})(_[12u])?.cgi$|$1.htm|;
$explain_title = $usr_title . 'の解説';
%usr_links = ( 'Home' => '../../../index.htm'
, 'Perl' => '../../'
, 'TestCGI Index' => '../'
, $explain_title => $explain
);
$searchDir = '..';
$searchReg = '.(html?|[sp]ht(ml)?)$';
$indexReg = "index$searchReg";
{
$ra_dir = dirSearch($searchDir);
printHeader($usr_title);
printBodyHeader($usr_title);
print "<div class=test>n";
Jprint('<p>親ディレクトリ以下にあるファイルの一覧(HTMLファイルのみ)</p>'."n");
print "<ul>n";
# require "dumpvar.pl"; dumpValue($ra_dir);
printRefArray($ra_dir);
print "</ul>n</div>n";
printFooter();
exit(0);
}
sub searchTitle{
my($file)= @_;
my $title = 'タイトル無し';
open(IN, $file);
while(<IN>){
if(m|<title>(.*?)</title>|i){
$title = ($1 !~ /^s*$/) ? $1:'不正なタイトル';
last;
}
last if m|</head>|i;
}
close(IN);
return $title;
}
sub printRefArray{
my($ra_dir) = @_;
my $indexfile = (grep(/$indexReg/, @$ra_dir))[0] || '';
my $dir = shift(@$ra_dir);
my($dirname) = $dir =~ m|([^/]+)/$|;
my $title = 'HTMLインデックス無し';
$title = searchTitle($indexfile) if($indexfile);
Jprint(qq(<li><strong><a href="$dir">$dirname($title)</a></strong>n));
return if($#$ra_dir < 0);
print "<ul>n";
foreach $file(@$ra_dir){
next if($file eq $indexfile);
if(ref($file)){
printRefArray($file);
next;
}elsif(-r $file){
my $title = searchTitle($file);
my($filename) = $file =~ m|([^/]+)$|;
Jprint(qq(<li><a href="$file">$filename($title)</a>n));
}
}
print "</ul>n";
}
sub dirSearch{
my($dir) = @_;
my @dirs = ();
my @filenames = ("$dir/");
opendir(DIR, $dir);
my @files = sort grep(/^[^.]/, readdir(DIR));
closedir(DIR);
foreach(@files){
$_ = "$dir/$_";
if(-d $_){
push(@dirs, dirSearch($_));
}elsif(/$searchReg/){
push(@filenames, $_);
}
}
push(@filenames, @dirs);
return @filenames;
}
sub printHeader{
# 「<title>タグ」の文字列
my($title) = @_;
print "Content-type: text/html; charset=$usr_outCharsetnn";
print qq(<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN">n);
print "<html lang=ja>n<head>n";
print qq(<meta http-equiv="Content-type" content="text/html; charset=$usr_outCharset">n);
print qq(<meta http-equiv="Content-style-type" content="text/css">n);
Jprint("<title>$title</title>n");
print qq(<link rev="made" href="$info_mailAddr">n);
foreach(@usr_stylesheet){ print qq(<link rel="stylesheet" type="text/css" href="$_">n); }
print qq(<meta name="ROBOTS" content="NOINDEX">n);
print "</head>nn";
print "<body>nn";
}
sub printBodyHeader{
# 英字なら「printBodyHeader("<font face=times>Title String</font>");」がいい
my($title) = @_;
print "<div align=center>n";
Jprint(qq(<h1><a name="top">$title</a></h1>n<hr>n));
printLinks();
print "</div>n";
}
sub printFooter{
print "<div align=center>n";
print qq(<a href="#top">Top</a>n<hr>n);
printLinks();
print "</div>n";
print "n<div align=right>n";
$timeEnd = sprintf("%.3f", times - $timeBegin);
print "Cost : $timeEnd<br>n";
print $info_copyright;
print "n</body>n</html>nn";
}
sub printLinks{
my $cnt = 0;
foreach(keys %usr_links){
print "/ " if($cnt++);
Jprint(qq(<a href="$usr_links{$_}">$_</a>n));
}
print "<hr>n";
}
sub Jprint{
foreach(@_){
# print Jcode::convert($_, $usr_outcode);
print jcode::to($usr_outcode, $_);
}
}
|