Tim Bray wrote on his article Concur.next that:
No longer; Next year’s system will do more computing all right, but by giving you more CPUs, running at this year’s speed, to work with.
Perl’s multi-core support is good old-fashioned fork(2). It’s not sexy, but it works. So recently I began to use “prove -j9″. But some of our project’s tests are not works correctly under the “prove” command.
For example, our cron script has tests that create and remove a log file.
- foo.t open and create a log file.
- foo.t write something to the file.
- foo.t remove the file.
- bar.t open and create a new log file.
- bar.t write something to the file.
- bar.t remove the file.
And it’s not works at the same time.
- foo.t open and create a log file.
- bar.t open the log file.
- foo.t write something to the file.
- bar.t write something to the file, too.
- foo.t remove the file.
- bar.t can’t remove the file.
I can modify the code to fix it. However, I’m lazy and impatient. So I wrote a simple lock system named Test::Synchronized.
Test::Synchronized provides a giant lock to your tests. When you add “use Test::Synchronized;” on both foo.t and bar.t.
- foo.t create a lock directory.
- foo.t open and create a log file.
- bar.t can’t create the lock directory. So bar.t wait the end of foo.t.
- foo.t write something to the file.
- foo.t remove the file.
- foo.t remove the lock directory.
- bar.t create a new lock directory.
- bar.t open and create a new log file.
- …
It’s not sexy, but it works :)
I released 0.01 on Bitbucket and CPAN already. Enjoy!
0.02
Tokuhiro-san (aka tokuhirom) blogged about some bugs and problems of Test::Synchronized. So I fixed and released 0.02 now. Thanks a lot.
11月は早かった。さっきはじまったような気がする。ぼんやりしている間に25歳になっていて、しかし25歳らしいことをしているかといわれると、目もあてられない。
私はなにがしたいんだろうなあ。
行ったライブ: Easel presents「neco眠る vs あらかじめ決められた恋人たちへ」(渋谷 O-Nest)
すごく混んでいた。前半は neco 眠るで、後半があら恋。neco 眠るはぜんぜんノイズよりでなく、楽しくて良かったので思わず CD まで買ってしまった。新しいひとの CD 買うのは久しぶり。あら恋はあいかわらずかっこよかった。
Google Chrome / Chromium をネタにした飲み会。Twitter ユーザー中心っぽかったけど気にせずまざる。Chrome (PNG と pixel で一致をみるテストはだめだ / タイルなウィンドウマネージャつかってるから Glen ボタンみえない / w3m + WebKit / …) から関係ないこと (X は悪くない / Scala はコンパイルが遅い / …) まで、いろいろ話せて楽しかった。元同僚とも会ったので二次会はスタバ。
これについてはいろいろ書くことがあるので後で。
Perl の File::Find で簡単な、たとえば JavaScript のファイルを列挙する処理を書いたとする。
find(sub { print "$File::Find::name\n" if m/\.js$/; }, '.');
いつもこんな風にすませていたんだけど、これを Subversion レポジトリのワーキングコピー上で走らせると普通より遅い。ワーキングコピー上のすべてのフォルダには .svn という Subversion のメタデータを保存するフォルダがあり、そもそもたどるべき木が大きいので当たり前だ。
たとえば Google Closure Library の場合 svn checkout したものが150MB, svn export したものが69MBになる。
各地の .svn 以下の部分木を無視すればいいので、いつか枝刈りつきの File::Find を書くか探すかしようとしていたんだけど、preprocess オプションをつけるとそれができることがわかった。
find({
wanted => sub {
print "$File::Find::name\n" if m/\.js$/;
},
preprocess => sub {
grep { $_ ne '.svn' } @_;
},
'.'
);
ベンチマークをとったらちゃんと速くなっていた。数字 (4倍) はレポジトリに左右されると思う。
% svn info
Path: .
URL: http://closure-library.googlecode.com/svn/trunk
Repository Root: http://closure-library.googlecode.com/svn
Repository UUID: 0b95b8e8-c90f-11de-9d4f-f947ee5921c8
Revision: 8
Node Kind: directory
Schedule: normal
Last Changed Author: dtbentley
Last Changed Rev: 8
Last Changed Date: 2009-11-13 13:51:43 +0900 (金, 13 11 2009)
% perl ~/find.pl
...
Rate plain preprocess
plain 5.94/s -- -71%
preprocess 20.4/s 243% --
%
ベンチマークに使った find.pl はこんな感じです。
use strict;
use warnings;
use File::Find;
use Benchmark;
sub print_if_javascript {
print "$File::Find::name\n" if m/\.js$/;
}
Benchmark::cmpthese(-1, {
preprocess => sub {
find({
wanted => \&print_if_javascript,
preprocess => sub {
grep { $_ ne '.svn' } @_;
}
}, '.');
},
plain => sub {
find({
wanted => \&print_if_javascript,
}, '.');
}
});
速くなるのは当たり前だけど、予想より簡単だったのがうれしかった。