[Perl] スレッドを使って多重リクエスト

Posted by
ぴろり
Posted at
2010/11/28 16:27
Trackbacks
関連記事 (0)
Post Comment
コメントできます
Category
開発メモ カテゴリ

 実験的に Comet サーバ の Perl 実装を書いてみたのだけれど、負荷テストをするためには同時に多数のクライアントから接続要求を行う必要があります。そこで今回、Perl の threads モジュールを使って、多重リクエストを行うスクリプトを書いてみました。VMware Player を利用した仮想マシン上で、50 スレッドくらいまで多重化することができました。

このエントリーをはてなブックマークに追加  

ワーカースレッドを次々に生成する版

 後から考えると、どうしてこんな複雑なことしているんだろう? って思ったんですが… メインループ内で Thread::Queue を使ってワーカースレッドの数を監視し、ワーカースレッドの処理が終わってスレッドが破棄されると、次々にワーカースレッドを生成します。特に問題なさそうに見えて、スレッドの生成と破棄を繰り返す間にどんどんヒープメモリを食い潰すようです。3000 クライアントID ぐらいあたりからスワップを始めます(´・ω・`)ショボーン

#!/usr/bin/perl
$|++;

use strict;
use threads; # http://perldoc.jp/docs/modules/threads-1.67/threads.pod
use Thread::Queue;
use LWP::UserAgent;
use HTTP::Request;
use Time::HiRes;

use constant {
    THREADS_NUM     => 30, # スレッドの生成数
};

### ワーカースレッド監視用のキュー
my $queue = Thread::Queue->new;

### ワーカースレッドを生成するメインループ
my $client_id = 0;
while (1) {
    while ($queue->pending < THREADS_NUM) {
        printf STDERR "* Create Client(ID:%d)
", $client_id;
        $queue->enqueue ($client_id++);
        threads->new (&do_request, $client_id, 30 < rand 100)->detach;
    }
}

### ワーカースレッド
sub do_request {
    my ($client_id, $action) = @_;

    my $ua = LWP::UserAgent->new
        or die 'Failed to initialize LWP::UserAgent';

    if ($action) {
        printf "tClient(ID:%d) is a listener
", $client_id;
        $ua->request (HTTP::Request->new (GET => 'http://vm:9000/'));
    }
    else {
        printf "tClient(ID:%d) is a speaker
", $client_id;

        sleep rand 30;
        $ua->request (HTTP::Request->new (POST => 'http://vm:9000/'));
        printf "tClient (ID:%d) speaks
", $client_id;
    }

    $queue->dequeue;
}

ワーカースレッドがずっと頑張る版

 普通に考えた(;´Д`) 最初に必要な数だけワーカースレッドを生成しておいて、ワーカースレッド内で無限ループしてしまえばいいんじゃない? という版。Thread::Queue とか不要で、今のところ長時間走らせても大丈夫そうに見えている…

#!/usr/bin/perl
$|++;

use strict;
use threads; # http://perldoc.jp/docs/modules/threads-1.67/threads.pod
use LWP::UserAgent;
use HTTP::Request;
use Time::HiRes;

use constant {
    THREADS_NUM     => 50, # スレッドの生成数
};

### ワーカースレッドの生成
my @threads;
push @threads, threads->new (&do_request, $_) for (1..THREADS_NUM);
$_->join for @threads;

### ワーカースレッド
sub do_request {
    my ($client_id) = @_;

    my $ua = LWP::UserAgent->new
        or die 'Failed to initialize LWP::UserAgent';

    while (1) {
        if (30 < rand 100) {
            printf "Client(ID:%d) is a listener
", $client_id;
            $ua->request (HTTP::Request->new (GET => 'http://vm:9000/'));
        }
        else {
            sleep rand 30;
            $ua->request (HTTP::Request->new (POST => 'http://vm:9000/'));
            printf "Client(ID:%d) speaks
", $client_id;
        }
        threads->yield;
    }
}
このエントリーをはてなブックマークに追加  



関連記事/トラックバック

関連記事/トラックバックはまだありません

この記事にトラックバックを送るには?

コメントを投稿する

 
 (必須, 匿名可, 公開, トリップが使えます)
 (必須, 匿名可, 非公開, Gravatar に対応しています)
 (必須)
スパム コメント防止のため「投稿確認」欄に ランダムな数字 CAPTCHAについて を入力してから送信してください。お手数ですがご協力のほど宜しくお願いいたします。