まだ重たいCMSをお使いですか?
毎秒1000リクエスト を捌く超高速CMS「adiary

2007/12/01(土)IIS + ActivePerl で ImageMagick のインストール

ActivePerl に ImageMagick をインストールする

activeperl_installer.png

  1. ImageMagick公式サイトからWindowsバイナリ-windows-dll.exe)をダウンロードしインストーラーを上の画面まで進める
  2. インストーラーの画面から、対応するActivePerlのVersionとビルドナンバーを確認したら(この場合 Ver5.8.8 build 822)インストールせずに一度インストーラーを閉じる。
  3. 今確認したバージョンの ActivePerl インストールする
  4. ImageMagickを上記画面で「Update executable search path」「install PerlMagick」の2つにチェックを入れてインストールする。

これで ImageMagick がインストールされているはずです。コマンドラインで次のように入力すると手動で確認できます(エラーがでなければ正常です)。

c:\>perl -e "use Image::Magick"

IIS で ImageMagick を使う場合

IISで ImageMagick を使う CGI などを起動する場合は、更にWindowsを再起動します

Image::Magick関連のDLLをロードさせるためにパス情報が設定されるのですが(環境変数PATH)、IISに新しいPATHを認識させるためには再起動しなければなりません。

2007/04/26(木)perl の Encode で find_encode は使えるのか?

perl tips - Encodeを速く使う方法によると、find_encoding を使うと、Encode による文字変換が早くなるらしいということで実験してみました。

実験条件

  • use utf8 しない(use utf8 はトラブルが多すぎてやってられないので)。
  • 変換前も変換後も utf8 フラグは立っていないこと。
  • 実験用データとして、42KBのテキストファイル(EUC-JP, 日本語半分ぐらい)を用意。

ソースはこんな感じです。引数に処理したい euc-jp のテキストファイル名を与えます。

use strict;
use Benchmark;
use Encode;
use Encode::Guess qw(euc-jp shiftjis iso-2022-jp);

my $euc = join('', <>);
my $utf = $euc;
Encode::from_to($utf, "euc-jp", "utf8");

my $euc_obj = find_encoding('euc-jp');
my $utf_obj = find_encoding('utf8');

my %test;
$test{fromto_u2e} = sub {
	my $x = $utf;
	Encode::from_to($x, "utf8", "euc-jp");
};
$test{fromto_e2u} = sub {
	my $x = $euc;
	Encode::from_to($x, "euc-jp", "utf8");
};
$test{find1_u2e} = sub {
	my $x = $euc_obj->encode( $utf_obj->decode($utf) );
};
$test{find1_e2u} = sub {
	my $x = $utf_obj->encode( $euc_obj->decode($euc) );
};
$test{find2_u2e} = sub {
	my $x = $utf;
	Encode::_utf8_on($x);
	$x = $euc_obj->encode( $x );
};
$test{find2_e2u} = sub {
	my $x = $euc_obj->decode($euc);
	Encode::_utf8_off($x);
};
$test{encode_u2e} = sub {
	my $x = $utf;
	Encode::_utf8_on($x);
	$x = encode('euc-jp', $x);
	print $x;
};
$test{decode_e2u} = sub {
	my $x = decode('euc-jp', $euc);
	Encode::_utf8_off($x);
};
timethese(1000,\%test);

結果は次のとおりになりました。

方式utf8 to euceuc to utf8
from_to100.26/s336.84/s
find_encoding103.92/s380.20/s
find_encoding + _utf_on/off357.21/s397.93/s
encode/decode304.76/s350.68/s

utf8からutf8(フラグ付き)への変換=utf8文字列の検証が入らないので速くなりましたが、ほかは大して変わりません。use utf8 しない環境では find_encodeを使うほどでもないなぁーという感じもします。

つまり、utf8を他の文字コードに変換する場合は、Encode::_utf8_on() + encode を使うと速い。短い文字列を多量に処理するのでなければ、ほかは大して変わらない。ということだと思います。

というわけで

早速adiaryに組み込んでみよう(笑)

2007/01/13(土)perl の import の働き

use と require と import の関係

perldoc perlmodによると、use というのは次と等価と書かれています。

use Module;
use Module LIST;

はそれぞれ、

BEGIN { require Module; import Module; }
BEGIN { require Module; import Module LIST; }

と等価になります。

BEGINとは?

BEGIN というのは、perl がそのソースファイルをロード中、発見次第最初に1回だけ実行する構文であるという意味です。少しフォローしておくと、モジュールのロードは、@INCにあるパスを順番に見てロードされますが、lib/ 以下に自作モジュールがあるとき、

push(@INC, './lib');
use Module;

はエラーとなります。先に use (BEGIN内構文)が実行されて、@INCにパスを追加する前にモジュールのロードが発生するからです。

use lib './lib';
use Module;

や、

push(@INC, './lib');
require Module; import  Module;

とする必要があります。END { }なんてのもありますが、脱線はこれぐらいにして本題に入りましょう。

import がない場合

モジュールをロードし perl の名前空間に展開するならば、基本的には require すれば足ります。

---test.pm---
package test;
sub new {
	return bless({}, shift);
}
---test.pl---
require test;
my $obj = new test();

ちなみに require では実行する度に処理されてしまうので無駄になりますから、

use test ();		BEGIN { require test; } と等価

とします。import しなくても、ロードしたライブラリを使えるわけです。ではインポートとは何なのか?

import の役割

import は外部ライブラリの関数をあたかも自分の関数のように扱う仕組みです。正確に言えば、外部ライブラリの関数を自分の名前空間内に展開する仕組みが import です。例を見てみましょう。

---test.pm---
use Exporter;		#←必須です
package test;
our @ISA    = qw(Exporter);	#←必須です
our @EXPORT = qw($X &sum);
our @EXPORT_OK = qw($Y);
our $X = 10;
our $Y = 20;
sub sum {
	return ($_[0]+$_[1]);	#渡された引数2つを加えて返す処理
}
print "in test.pm : X=", \$X, "\n";

呼び出し側はこんな感じです。

use test;	# BEGIN {require test; import test;} と等価
our ($X, $Y);
print "X=$X ", \$X, "\n";
print "Y=$Y\n";
print sum(5,3),"\n";

として実行してみます。

in test4.pm X=SCALAR(0x93bc130)

X=20 SCALAR(0x93bc130)

Y=

30

となります。test という名前空間内の変数 $X、関数 sum が、import した側で使えるようになっています。perl 的に正確に言えば、$test::x と &test::sum の示す実体が(内部的な実体のポインタが)それぞれ $MAIN::x、&MAIN::sum にコピーされたことになります。その証拠に、リファレンスをとって実体を調べると、ともに同じ実体である SCALAR(0x93bc130) を示しています。

import される関数は、モジュール側で @EXPORT に代入されているものになります

import の引数は何?

import は配列引数を取れることになっています。これは、モジュール側で @EXPORT および @EXPORT_OK に代入されているもののうち、どれをインポートするか指定する役割があります。

ですから、さきほどのソースで、

use test qw(&sum $Y);

と変更すると次のような結果になります。

in test4.pm X=SCALAR(0x953e1b8)

X= SCALAR(0x94fd660)

Y=10

30

$Yがインポートされている反面、$X が test.pm 内の実体とは違うものを示していることが分かります。

関連記事

2006/12/04(月)Perlと標準入出力ファイルハンドル

Perlで「use strict」で使用している場合、ファイルハンドルを動的に生成し変数に代入するには一工夫する必要がありました。

さらに、このファイルハンドルに標準入力などを代入する場合、

my $fh = 'STDOUT';

ではダメで、

my $fh = *STDOUT;

とします。少々気持ち悪い感じもしますが、STDOUTという定義済の名前に対する型グロブを与えることになります。Symbolなどのライブラリをみると分かりますが、動的ファイルハンドルの実体は、特定の名前に対する型グロブになっています。

2006/11/05(日)perlの長所と短所

所詮Perl?

ネットをみていると「所詮Perl」的な発言をみかけるのですが、いやいやマテマテマテマテ。かと思うと、はてなmixiもPerlだ! 的な肯定意見があったりして、それもまた視点としておかしいような。

Perlの長所

  • Rubyなどのスクリプト言語と比べ速く動作する(時に数倍以上)。
  • CやC++に比べはるかに開発が容易。
  • CやC++に比べどうしても遅くなるものの、重い計算をループ処理させなければ実用上そこまで大きく変わらない。
  • PHPに比べ、MVC的なソース(ソースとHTML部分を分離させるコード)を書くのに適当である。
  • 世の中のほとんどのサーバで動作する

という特徴があります。adiaryの基礎になっているスケルトンシステム(Satsuki-system)開発時、本当はRubyも検討したんですが、簡単なテストスクリプトをいくら走らせてもRubyの処理速度はPerlのそれに到底及びません。Perlは隅々まで最適化が行き届いていて、うまく書いてやれば相当早く動作します。

Perlの短所

  • 言語仕様が非常にきたない(アセンブラおなじくスクリプト言語として原始的)。
  • 標準ではCGIとして動作させるため、スクリプトとしての起動が遅い。処理が遅いのではない

ほとんどこの2点に尽きると思います。1つめは対Rubyで考えると非常に分かりやすい。互換性を保ってきた結果が現在のPerl 5+オブジェクト指向という複雑な状況なんですが、それでもこのゆるゆるのオブジェクト指向がまた逆手に取ってうまく使うと非常に効率的なシステムが作れます。

2つめはネットを検索すると沢山出てきますが、「PHPはPerlより速い」という意味での速いです。起動が速い。ネット上の共有レンタルサーバでなければmod_perlなどを使うことで解決できますし、うまく書けばCGIとして動かしてもそこまで重くなりません。*1

結局

Perlってのは使い倒せば大規模開発にも十二分にも耐えられる言語です。ただこの辺は適切に判断すべきで、仕様をきっちり決めることで綺麗なメンテ性を取るならRubyもありですし、Webアプリとして手軽に作りたいならPHP、処理速度と開発効率を同時に求めるならPerlということになると思います。*2

*1 : 起動=コンパイルが遅いということは、ライブラリが必要になるまで極力ロードしないことで改善できるということです

*2 : おまけに配布を考えなければCのルーチンを呼び出すことで処理速度は必要な部分でいくらでも速められますしね。

adiaryを開発する人間としては

「早くPerl6出ないかなぁー」ってのが本音です(笑) Satsuki-systemが全面書き直しになりそうで怖いのは怖いけども(苦笑)

OK キャンセル 確認 その他