JAMADAM.COM

RSS Subscribe to my RSS feed

Stripe Calendar

Sep, 2010
Aug 1213141516171819202122232425262728293031 Sep 123456

Entry: mod_perlにしてみた

mod_perlにしてみた

Initial post: 2008.08.02 | Last modified: 2008.08.02

このブログをmod_perl対応にしてみた。以前からspeedyCGI対応だったので、結構あっさりでした。これでレンタルサーバに以降できそうな気がしてきた。

ただ、まだ設定がまずいのか、あまりパフォーマンスはよくない。効果あったりなかったりとムラがある。そして、効果あるときでもspeedyに負けている。この辺は追々チューニングしていこう。

あと話は変わりますが、最近、CPAN Authorになりました。そんな世界に発信するほどのネタなんてなかったんですが、何事も経験と思って半ば強引に、improvedな車輪をいくつかアップしてみました(ごめんなさい)。おかげで、基礎的なモジュールの作り方から、様々なお作法までざっと習得することができました。

そして、今さらCPANすげーってことを知りました。どこの馬の骨とも分からない僕のような者が作った、見るからにパッとしないモジュールでも、半月で370件ものテストレポートが届き、30のプラットフォームでの動作確認がとれちゃったり。

自分で作ったもの以外は信用できない、とか、これも勉強のうち、とか言って、車輪の再発明をするのも、そろそろ卒業しようと思いました。

Entry: speedycgiすげかったんだ

speedycgiすげかったんだ

Initial post: 2008.02.19 | Last modified: 2008.02.19

キャッシュするとアクセスログが記録できなかったのを改善。キャッシュにアクセスログ系のテンプレート関数を書きこんじゃって、中間コード的な仕様にする。そしたら、以前に書いたエントリー中のサンプルコードとデリミタがバッティング。しばらく悩む。

そして解決。いずれにしても、キャッシュ機能自体、今のところ全く効果なし。てか、効果測定する方法がわからない。倍返しで速くなると何故か確信してたのに・・。しかも、クローラーに舐められた後はキャッシュファイルだけで1000ページも生成されてディスクの無駄。なんて考えると、余裕で速度10倍とかはじき出すspeedycgiってスゴすぎるな。そろそろ自宅サーバーもやめてレンタルサーバーにしようと思ったりもするけど、speedycgiがないことだけが憂鬱。

Entry: 画像サムネイル自動生成機能つけてみた

画像サムネイル自動生成機能つけてみた

Initial post: 2007.07.19 | Last modified: 2007.07.19

高速化第二弾。もはやサーバ側で何やっても大差ない気がしてきました。体感速度の重さはCSSが汚すぎるのと画像がデカ過ぎる辺りに問題が。最近のエントリーに添付する画像は全部、横800pxという馬鹿みたいにデカいのをブラウザに縮小させてたんですが、150pxのサムネイルを自動生成するようにしました。

mod_rewriteで気の利いた仕組みにしてみました。sample.jpgというのが元画像。sample.jpg?x=150とすると横150pxにして出力する。実はここまでは数日前から運用してたのですが、Perlの処理が重いのか、SpeedyCGIに任せて起動時間削減しても逆に重くなりました。という訳で、今日からキャッシュ機構を取り入れ、2度目以降のアクセス時にはPerlを一切使わない仕組みにしました。まだちゃんと動作してるか不安なので、詳細は後日。

- 2007.7.20追記 -
resize.cgi。実際は画像以外も扱うので、ちょっとだけ複雑。

#!/usr/bin/perl -w

### -----------------------------------------
### ディレクトリ構造
### -----------------------------------------
### 画像ルート
### ┣ resize.cgi
### ┣ image1.jpg
### ┣ image2.jpg
### ┣ image3.gif
### ┣ ...
### ┣ キャッシュディレクトリ
###    ┣ image1.x=100.jpg
###    ┣ image2.y=100.jpg
###    ┣ image3.x=100.gif
###    ┣ image3.x=100&y=200.gif
###    ┣ ...

### -----------------------------------------
### 初期設定
### -----------------------------------------
my $org_dir = '';
my $cache_dir = 'cache';
my $default_width = undef;
my $default_height = undef;
my $max_width = 800;
my $max_height = 800;
### -----------------------------------------

use strict;
use warnings;
use HTTP_util; # 自前
use Image::Magick;

our %QUERY = &HTTP_util::read_query($ENV{'QUERY_STRING'});

$QUERY{'f'} or die 'file not found';

my ($name, $ext) = ($QUERY{'f'} =~ /^(.+)\.([^.]+)$/);
my $new_query = ($ENV{'QUERY_STRING'} =~ /^f=.+?&(.+)/)[0];
my $cache_path = sprintf('%s/%s.%s.%s', $cache_dir, $name, $new_query, $ext);

&binary_out($cache_path) or &resize_image($cache_path);

### -----------------------------------------
### 汎用バイナリ出力
### -----------------------------------------
sub binary_out {
    
    if (open(IN, $_[0])) {
        
        print &HTTP_util::get_http_header(tpl_name => $QUERY{'f'});
        
        binmode(IN);
        binmode(STDOUT);
        
        read(IN, my $buf, -s $_[0]);
        print $buf;
        close(IN);
        
        return 1;
    }
    
    return 0;
}

### -----------------------------------------
### 画像リサイズ出力 & キャッシュ出力
### -----------------------------------------
sub resize_image {
    
    ### ソース
    my $org_path = $org_dir. './'. $QUERY{'f'};
    -e $org_path or die 'file not found';
    
    my $image = Image::Magick->new; $image->Read($org_path);
    my ($width, $height, $format) = $image->Get('width', 'height', 'magick');
    
    ### 引数取得
    my $target_width = ($QUERY{'x'} or $default_width or 0);
    my $target_height = ($QUERY{'y'} or $default_height or 0);
    
    ### アスペクト比保持
    $target_height  ||= ($height * $target_width) / $width;
    $target_width   ||= ($width * $target_height) / $height;
    
    ### 上限判定
    $target_width = $max_width if ($target_width > $max_width);
    $target_height = $max_height if ($target_height > $max_height);
    
    ### 四捨五入と0回避
    $target_width = (int($target_width + 0.5) or 1);
    $target_height = (int($target_height + 0.5) or 1);
    
    ### リサイズ
    $image->Resize(width => $target_width, height => $target_height);
    
    ### ヘッダ出力
    print &HTTP_util::get_http_header(tpl_name => $QUERY{'f'});
    
    ### -----------------------------------------
    ### ユーザー出力
    ### -----------------------------------------
    binmode(STDOUT);
    $image->Write($format. ':-');
    
    ### -----------------------------------------
    ### キャッシュ出力
    ### -----------------------------------------
    if (open(CACHE, "> $_[0]")) {
        
        binmode(CACHE);
        $image->Write(file => \*CACHE, filename => $cache_dir);
        close(CACHE);
    }
    
    undef $image;
    
    return 1;
}

画像ルートに.htaccess。通常はそのままファイルにアクセス。クエリー指定があるならキャッシュファイル名を生成して書き換え。ファイルの存在確認のうえ、なければresize.cgiに書き換え。一応動いてるっぽいけど、かなり自信なし。

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !cache/[^\/]+$
RewriteCond %{REQUEST_FILENAME} !resize.cgi$
RewriteCond %{QUERY_STRING} .
RewriteRule (\w+)\.(\w+)$ cache/$1.%{QUERY_STRING}.$2 [E=ORG:$1.$2,C]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.+) ?f=%{ENV:ORG}&%{QUERY_STRING}

Entry: SpeedyCGIで高速化してみた

SpeedyCGIで高速化してみた

Initial post: 2007.07.13 | Last modified: 2007.07.13

ブログがあまりに重いので、SpeedyCGIというものを導入してみました。apacheモジュールのほうです。最初、mod_perlにしようと思ったのですが、導入が大変なうえに、ネット上のベンチマークでSpeedyCGIのほうが上回っていたので、こちらにしました。名前はダサいけど優れモノです。リモートのFirefoxで計測して3倍速以上になりました。ただし、どこかに予期せぬバグが潜んでる可能性も。

いくつかある高速化の仕組みの中で、これが一番、導入が簡単と定評だったのですが、結構、ソースの変更が必要でした。ただ、SpeedyCGI専用の書き方というよりは、より汎用的な書き方になった感じなので悪くない。

インストール手順。設定はapache2.confで固定、使用の有無はhtaccessで個別に指定。非対応のCGIもあるので。

# apt-get install libapache2-mod-speedycgi

# cat apache2.conf
<IfModule mod_speedycgi2.c>
    SpeedyMaxruns 10
    SpeedyMaxBackends 10
    SpeedyTimeOut 3600
</IfModulev>

$ cat ~/www/blog/.htaccess
AddHandler speedycgi-script .cgi

CGIソースの変更。グローバル変数の初期化などは大方、そんなもんだろうと思って適当に片付けたのですが、下記の2点の発見に手こずりました。おかげで、フォームデコード処理レベルからぶった切って検証するはめに。

  • $^T(スクリプト起動時刻)は保持される  --> グローバル変数$main::boot_time = time()で代用
  • ・sysreadがなぜか機能しない  --> sysreadである必要ないのでreadに変更