プロが教える店舗&オフィスのセキュリティ対策術

Perlで他サイトの情報を取得し一覧表示させる処理の高速化

Perl初心者です。よろしくお願いします。

同サーバ内にあるテキストデータをPerlで読みこみ、HTMLで一覧表示させるプログラムを見よう見真似で作成しました。リストのレコード数は10~30ほど。タイトルとボタンA~Eが配置されており、ボタンAはファイルA、ボタンBはファイルB…とリンクしています。

ファイルは同サーバ内にあり、ファイルの有無を調べてリンクするか、しないかを設定していましたが、この度、訳があってこのファイルが他サーバへ移動、さらにシステムから吐き出される仕組みになって、同じPDFファイルでも「xxxx.pdf」が「http://hoge.com/hoge.aspx?code=1234」のようにファイルの場所を特定することができなくなりました。

仕方なくファイルの有無を指定するHTMLを書き出すようにしてもらったのですが、それをget(url)で取得する方法に切り替えたとたん、一覧表示にするのに5~6秒かかるようになってしましました。

さらにこれが原因でアクセス過多でサーバに負荷がかかり、ページを表示できない要因にもなってしましました。

情報の取得方法や、負荷をかけない方法などご教授いただければ幸いです。

以下CGI抜粋
#!/usr/local/bin/perl

use LWP::Simple;
use Time::Local;
use LWP::UserAgent;

$file = @ARGV[0];
$data = $file;
$file .= ".txt";

print "Content-type: text/html\n\n";

print <<HTML;
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.0 Transitional//EN'>
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=x-sjis">
<META HTTP-EQUIV="Content-Script-Type" CONTENT="text/javascript" />

</HEAD>

<BODY style="margin : 0px; >
<TABLE BORDER="0" CELLSPACING="0" CELLPADDING="0">

HTML
open(IN, $file);

while(<IN>){
@in = split(/\t/);

$pdf = "https://www.hoge.com/filecheck/entFileCheck.aspx …[10]
$gPdf = get($pdf);


#ボタン配置の処理とか・・・

close(IN);

print "</BODY>\n";
print "</HTML>\n";

exit;

A 回答 (4件)

>>ちなみにループが終ってから次のループが始まるまでの時間という観点ではどうなりますか?


>これは、どんな理由があって計測するのか私のスキルでは理解できませんが、やってみました。
ちょっと考えすぎました。$gPdf がwhileループの最後に達したとき、オブジェクトが捨てられて遅くなるのかなと考えました。

get したあとの処理が遅いんですかね?

この回答への補足

ありがとうございます。

get()の前後で計測すると「0.01~0.05」。「0.5~0.6」ではありませんでした。しかし全体では10~12秒かかっています。get()の処理をはずすと「0秒」。get()に時間がとられているのは間違いないようです。

補足日時:2010/06/16 14:45
    • good
    • 0

> 同様にプログラムのはじめと終わりにタイマーセット。

「0.5~0.6」と出ます。
ループの先頭と最後という意味でしょうか。

> プログラム全体の方をtime()に変えると10~12秒。実感に近いです。
これはプログラムの先頭と最後という意味ですよね。

ちなみにループが終ってから次のループが始まるまでの時間という観点ではどうなりますか?

while () {
2)
....
1)
}

ループのおわり 1)から 次のループがはじまる 2)まで
    • good
    • 0
この回答へのお礼

お世話になります。

>ループの先頭と最後という意味でしょうか。
いえ、1レコード毎にget()の前後で計測した値です。その平均値が0.5~0.6。

>これはプログラムの先頭と最後という意味ですよね。
はい。

>ちなみにループが終ってから次のループが始まるまでの時間という観点ではどうなりますか?
これは、どんな理由があって計測するのか私のスキルでは理解できませんが、やってみました。

while(<IN>){
$tt2 = (times())[0];
$tt3 = $tt2 - $tt1;

処理

$tt1 = (times())[0];
}
close(IN);

1レコード目以外は「0」と出ました。

お礼日時:2010/06/15 11:21

https://www.hoge.com/filecheck/entFileCheck.aspx …[10]
をループで取得するのが問題でしょうか。
get の前後で時間を計ることをお勧めします。
---
use Time::HiRes qw(gettimeofday);
use POSIX 'strftime';

my ( $sec, $usec ) = gettimeofday;
my $str = strftime( '%Y-%m-%d %H:%M:%S', localtime($sec) );
printf "%s.%03d\n", $str, $usec / 1000;
---

getを複数実行することがボトルネックなら、
複数のページ情報を一度に取得できるように交渉するしかないでしょうね。

例) 1から10,11のベージを取得する
https://www.hoge.com/filecheck/entFileCheck.aspx …
とか
    • good
    • 0
この回答へのお礼

ありがとうございます。

きっとそこに時間が取れれてるんだろうと、勝手な憶測で計測までしませんでしたが…

組み方が悪いのか?サーバで禁止してるのか?use Time::HiRes qw(gettimeofday); を設置するとエラー発生?なので、

$t1 = (times())[0];
#$gurl = get($url);
#$gurl2 = get($url2);
$t2 = (times())[0];
$t3 = $t2 - $t1;

で計測してみると、それぞれのレコードで「0.01~0.2」と出ます。しかし実感は全体の処理から表示まで5~6秒かかっています。同様にプログラムのはじめと終わりにタイマーセット。「0.5~0.6」と出ます。おかしいですよね。
プログラム全体の方をtime()に変えると10~12秒。実感に近いです。

1レコードのデータ取得時間が本当に「0.01~0.1」秒なら他に原因があることになりますが「$gurl = get($url); 」「$gurl2 = get($url2); 」を削除して実行しますと、あっという間に表示(0秒)されますので、やはりここに時間がかかってるのは間違いありません。

おっしゃるようにループで回すより、全レコード分吐き出してもらうのは時間、負荷ともに軽減できそうですね。これは相談してみますが、他に方法はないか。いまだに模索中。

よろしくおねがいします。

お礼日時:2010/06/14 21:31

https://www.hoge.com/filecheck/entFileCheck.aspx …[10]
を a タグを使ってリンクとして出せば?
    • good
    • 0
この回答へのお礼

説明不足でした。

リンク先ファイル、例えばAファイルならアドレスはhttp://www.hoge.com/link_a.aspx?=@in[10]
※@in[10]はループで各レコードからコード番号を拾っています。

このファイルが存在するときだけ、リンクするように、なければリンクなしで表示させています。

ファイルが同サーバーなら「-e」とかでその有無を調べられますが、できないのでファイルの有無をHTMLで書き出してもらっています。そのアドレスが例えばhttp://www.hoge.com/fcheck.aspx?=@in[10]で、ファイルAがあれば「fileA」、ファイルBがあれば「fileB」…と表示されます。
なので該当アドレスから表示データを取得して、検索。マッチすればボタンA~Eはリンク、無ければリンクなしとなります。
$url;
$gurl = get($url);
if ($gurl =~ /fileA/){#ファイルAにリンクする}
としているのですが、どうもこの処理がリスト表示を遅くさせているのではと考えています。

お礼日時:2010/06/13 23:11

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!