まだ重たい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 内の実体とは違うものを示していることが分かります。

関連記事