Firefoxを最適化したらかなり速くなった
ここしばらくFirefoxを自前でビルドして使っていたのだが、思った程軽快に動いてくれないので、
ac_add_options --enable-optimize="-O2 -pipe -march=i386 -mcpu=i686" ac_add_options --disable-tests ac_add_options --disable-debug ac_add_options --enable-strip ac_add_options --enable-strip-libs ac_add_options --enable-reorder ac_add_options --enable-default-toolkit=gtk2 ac_add_options --enable-xft ac_add_options --enable-freetype2 ac_add_options --disable-installer
と最適化オプションを有効にしたら、見違えるように速くなった。
Firefoxのローカライズ
ビルド時に言語リソースを追加する方法が分かった。
(これまではインストール後に拡張機能としてXPIパッケージをインストールしていた)
.mozconfigに以下の内容を追加して、
ac_add_options --enable-ui-locale=ja-JP mk_add_options MOZ_CO_LOCALES="ja-JP" mk_add_options LOCALES_CVSROOT=:pserver:anonymous@cvs-mirror.mozilla.org:/l10n
チェックアウトする。
gmake -f client.mk checkout
これであとは普通にビルドすればいい。
gmake -f client.mk build
言語リソースだけをダウンロードできないかと思って結構探したんだけど見つからなかった。CVSから入手するしかないのかな?
リンク
- Localizing Firefox
Perlで並行処理
Perl 5.6だとスレッドが使えなかったので、forkして子プロセスを作るという伝統的なスタイルで実装した。単にforkしただけだと、子プロセスに値を渡すことはできても戻り値を受け取ることができないから、その部分にプロセス間通信(Unix-Domain TCP)を使ってみた。
### pararell.pl use strict; use POSIX ":sys_wait_h"; use Socket; use IO::Handle; use Data::Dumper; my $sock_path = '/tmp/catsock.$$'; BEGIN { $ENV{PATH} = '/usr/bin:/bin' } sub wait_all { my $kid; do { $kid = waitpid(-1, &WNOHANG); } until $kid == -1; } sub send_to_parent { my $obj = shift @_; my $sock; socket($sock, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; connect($sock, sockaddr_un($sock_path)) || die "connect: $!"; $sock->autoflush(1); my $d = new Data::Dumper([$obj]); $d->Terse(1); $d->Indent(0); my $data = $d->Dump; print $sock $$, "\n", length($data), "\n", $data; close($sock); } sub recv_from_child { my $sock = shift @_; $sock->autoflush(1); my $pid = <$sock> + 0; my $len = <$sock> + 0; my $res; read($sock, $res, $len); close $sock; my $obj = eval $res; return ($pid, $obj); } sub parallel { my ($max_process, $worker, $callback, @args) = @_; my $uaddr = sockaddr_un($sock_path); my $proto = getprotobyname('tcp'); socket(SERVER, PF_UNIX, SOCK_STREAM, 0) || die "socket: $!"; unlink($sock_path); SERVER->autoflush(1); bind(SERVER, $uaddr) || die "bind: $!"; listen(SERVER, SOMAXCONN) || die "listen: $!"; my %children; while (1) { while (@args && (keys %children < $max_process)) { my $arg = shift @args; my $pid = fork; die "Can't fork: $!" unless defined $pid; if ($pid) { # parent $children{$pid} = $arg; } else { # child my $ret = $worker->($arg); &send_to_parent($ret); exit; } } last unless keys %children; my $sock; accept($sock, SERVER); my ($pid, $res) = &recv_from_child($sock); my $waitedpid; do { $waitedpid = waitpid($pid, &WNOHANG); } while $waitedpid == 0; die "$waitedpid is NOT my child!" unless $children{$waitedpid}; $callback->($children{$pid}, $res); delete $children{$pid}; } &wait_all; }
こうやって使う。
#!/usr/bin/perl -Tw use strict; require 'parallel.pl'; sub worker { my $msg = shift @_; # do something sleep(1); srand; sleep(rand 5); return [length($msg), uc($msg)]; } sub main { sub callback { my ($arg, $ret) = @_; my ($len, $msg) = @{$ret}; printf "%s -> [$d, %s]\n", $arg, $len, $msg; } my @msg = qw(red green blue yellow white); ¶llel(3, \&worker, \&callback, @msg); } &main;
接続して来たプロセスのPIDをサーバ側で得る方法が分からなかったので、苦肉の策としてクライアントから自己申告するようなプロトコルにしている。実際には子プロセスでなくてもソケットに書き込めるプロセスからはいくらでも接続可能なので、これはセキュリティ上の問題になるかも知れない。
参考URL