ports: 高速化の実験と検証2006年04月27日 13時27分53秒

では、効果の程を実験してみる。

# mount
/dev/ad0s3a on / (ufs, local, soft-updates)
devfs on /dev (devfs, local)
/dev/ad0s3d on /usr (ufs, local, noatime, soft-updates)
/dev/ad0s3e on /ports (ufs, local, noatime, soft-updates)
/ports/db/pkg on /var/db/pkg (nullfs, local, noatime)
/ports/X11R6 on /usr/X11R6 (nullfs, local, noatime)
/ports/local on /usr/local (nullfs, local, noatime)
/ports/compat on /usr/compat (nullfs, local, noatime)
linprocfs on /usr/compat/linux/proc (linprocfs, local)
/dev/md2 on /tmp (ufs, asynchronous, local)
/dev/da0s2.eli on /mnt/nfs (ufs, local, read-only)
# top
last pid:   760;  load averages:  0.24,  0.30,  0.14    up 0+00:02:51  00:13:52
42 processes:  2 running, 40 sleeping
CPU states:  0.6% user,  0.0% nice,  0.6% system,  0.0% interrupt, 98.8% idle
Mem: 30M Active, 21M Inact, 31M Wired, 18M Cache, 21M Buf, 378M Free
Swap: 1024M Total, 1024M Free
# dmesg
Timecounter "i8254" frequency 1193182 Hz quality 0
CPU: Mobile Intel(R) Celeron(R) CPU 2.40GHz (2394.01-MHz 686-class CPU)
  Origin = "GenuineIntel"  Id = 0xf29  Stepping = 9
...
real memory  = 519372800 (495 MB)
avail memory = 498860032 (475 MB)
...
ad0: 76319MB  at ata0-master UDMA100

TMPDIR や md-swap /tmp などのほとんどは、起動時に既に設定されているので、md-swap を割り当てるだけ。

# mdconfig -a -t swap -s 1g
md3
# newfs -U /dev/md3
/dev/md3: 1024.0MB (2097152 sectors) block size 16384, fragment size 2048
        using 6 cylinder groups of 183.77MB, 11761 blks, 23552 inodes.
        with soft updates
super-block backups (for fsck -b #) at:
 160, 376512, 752864, 1129216, 1505568, 1881920
# mount /dev/md3 /ports/tmp
# df /ports/tmp
Filesystem 1K-blocks Used  Avail Capacity  Mounted on
/dev/md3     1012974    4 931934     0%    /ports/tmp

WRKDIRPREFIX に md-swap を当てる。いくつかの ports を入れ直してみる。

# portupgrade -nf /var/db/pkg/linux_base-rh-7.3
...
# time portupgrade -f -w -W /var/db/pkg/linux_base-rh-7.3
...
85.130u 39.458s 3:43.97 55.6%   151+7596k 13683+1201io 84pf+0w
# time portupgrade -f /var/db/pkg/linux-sun-jdk-1.4.2.10
113.150u 15.625s 3:08.88 68.1%  68+9686k 8921+1820io 135pf+0w
# time portupgrade -f -w -W /var/db/pkg/zip-2.31
15.990u 5.878s 0:33.70 64.8%    1341+10919k 1296+49io 5pf+0w

make extract の段階の高速化はいつ行っているのか、気が付かない程効いている。処理時間を計測した後、今回の高速化の設定を解除し、標準的なシステムに近づける。

# umount /ports/tmp
# mdconfig -d -u 3
# mount -u /usr
# mount -u /ports
# unsetenv TMPDIR
# perl -p -i -e 's/WRKDIRPREFIX/#WRKDIRPREFIX/g' /etc/make.conf

また、同じ ports をインストールしなおして、時間を計測する。

# time portupgrade -f /var/db/pkg/linux_base-rh-7.3
[Updating the pkgdb  in /var/db/pkg ... - 383 packages found
(-0 +1) . done]
86.677u 42.957s 4:00.07 53.9%   156+7186k 12866+1114io 117pf+0w
# time portupgrade -f /var/db/pkg/linux-sun-jdk-1.4.2.10
[Updating the pkgdb  in /var/db/pkg ... - 383 packages found
(-0 +1) . done]
119.348u 17.181s 3:00.87 75.4%  76+9263k 1958+1814io 59pf+0w
# time portupgrade -f -w -W /var/db/pkg/zip-2.31
[Updating the pkgdb  in /var/db/pkg ... - 383 packages found
(-0 +1) . done]
16.443u 5.887s 0:41.10 54.3%    1337+10696k 1343+43io 5pf+0w

コマンドも含めると少々見づらいので抜粋する。

Optimized:

# time portupgrade -f -w -W /var/db/pkg/linux_base-rh-7.3
85.130u 39.458s 3:43.97 55.6%   151+7596k 13683+1201io 84pf+0w
# time portupgrade -f -w -W /var/db/pkg/linux-sun-jdk-1.4.2.10
113.150u 15.625s 3:08.88 68.1%  68+9686k 8921+1820io 135pf+0w
# time portupgrade -f -w -W /var/db/pkg/zip-2.31
15.990u 5.878s 0:33.70 64.8%    1341+10919k 1296+49io 5pf+0w

Non-Optimized:
# time portupgrade -f /var/db/pkg/linux_base-rh-7.3
86.677u 42.957s 4:00.07 53.9%   156+7186k 12866+1114io 117pf+0w
# time portupgrade -f /var/db/pkg/linux-sun-jdk-1.4.2.10
119.348u 17.181s 3:00.87 75.4%  76+9263k 1958+1814io 59pf+0w
# time portupgrade -f -w -W /var/db/pkg/zip-2.31
16.443u 5.887s 0:41.10 54.3%    1337+10696k 1343+43io 5pf+0w

この値を基に高速化率を計算する。

% dc
3 k
4 60 * 43 3 60 * + / p
1.076

3 60 * 8 3 60 * + / p
.957

41 33 / p
1.242

linux-base が 7% の高速化、linux-sun-java-1.4 は 5% 遅くなっている。zip は約 25% の高速化が出来た。

この値は、残念ながら期待を裏切るものだった。md device を物理ディスクの変わりに使うと物凄い高速化が体験できるからである。実際に seamonkey で試すと、


# cd /usr/ports/www/seamonkey
# time make extract
...
===>  Extracting for seamonkey-1.0
=> MD5 Checksum OK for seamonkey-1.0.source.tar.bz2.
=> SHA256 Checksum OK for seamonkey-1.0.source.tar.bz2.
===>   seamonkey-1.0 depends on file: /usr/local/bin/perl5.8.8 - found
43.934u 11.099s 2:25.17 37.9%   36+3615k 2302+577io 14pf+0w
dynabook-freebsd# mdconfig -a -t swap -s 1g
md3
dynabook-freebsd# newfs -U /dev/md3
/dev/md3: 1024.0MB (2097152 sectors) block size 16384, fragment size 2048
        using 6 cylinder groups of 183.77MB, 11761 blks, 23552 inodes.
        with soft updates
super-block backups (for fsck -b #) at:
 160, 376512, 752864, 1129216, 1505568, 1881920
dynabook-freebsd# mount /dev/md3 /ports/tmp
...
===>  Extracting for seamonkey-1.0
=> MD5 Checksum OK for seamonkey-1.0.source.tar.bz2.
=> SHA256 Checksum OK for seamonkey-1.0.source.tar.bz2.
===>   seamonkey-1.0 depends on file: /usr/local/bin/perl5.8.8 - found
45.625u 10.595s 1:01.48 91.4%   36+3633k 2296+618io 38pf+0w

二倍も速くなった。これは、bzip2 の展開に少々手間取るので、大した違いは出ていないが、rm -rf などをすると、雲泥の差が出る。また、gzip を使っているものも、最近の機械なら、CPU はほとんど使わずディスク待ちなので、更に速くなる。まあ、期待しすぎていたのが失敗らしい。

しかし、ここで終っては面白くない。実は portupgrade を走らせているときに、build 以外で時間が掛かるのは、pkg_create によるバックアップと、/var/db/pkg の更新であることに気が付いた。 /var/db/pkg の更新は、md device の上に置くことで高速化は可能であろう。しかし、今回は試さない。pkg_create が走っている間、tar が CPU を占拠しているのである。bzip2 で圧縮しているに違いない。pkg_create に視点を当てて、/usr/local/sbin/portupgrade を覗いてみると、


   1611   progress_message "Backing up the old version"
   1612
   1613   backup_pkgfile = nil
   1614
   1615   if str = backquote!(PkgDB::command(:pkg_create), '-vb', pkgname,
   1616                       File.join($tmpdir, pkgname + $portsdb.pkg_sufx))

が見つけられる。require に pkgtools があるので、locate pkgtools でそれらしきものを探すと、/usr/local/lib/ruby/site_ruby/1.8/pkgtools.rb が怪しい。これによると、pkgtools.conf を読み込むらしい。

う〜ん。どこで pkg_sufx が設定されるかわからない。とにかく、$portsdb.pkg_sufx を ".tgz" に変えると、gzip を使うようになる。


# time portupgrade -f -w -W /var/db/pkg/linux-sun-jdk-1.4.2.10
[Updating the pkgdb  in /var/db/pkg ... - 383 packages found
(-0 +1) . done]
38.135u 15.322s 1:56.89 45.7%   85+7211k 12906+1861io 189pf+0w
# time portupgrade -f -w -W /var/db/pkg/zip-2.31
[Updating the pkgdb  in /var/db/pkg ... - 383 packages found
(-0 +1) . done]
15.900u 5.926s 0:30.22 72.2%    1357+10907k 320+43io 4pf+0w

これで、更に少しは良くはなった。linux-sun-jdk-1.4 が二倍と、zip が三割増し。

もちろん何を更新するかで、大きく変わってくる。しかし、残念ながら、劇的に向上したという気がしない。追記になるが、portupgrade の構造上、並列処理は向かない。やはり、手っ取り早い高速化は速い機械を使うのが一番簡単でいいのか。もう少し丁寧に言い直すと、「局所的には大幅な高速化を実現できたが、その作業が占める全体的な時間の割合を見ると、微々たるものだった。」と言うことか。

Pentium 3 270MHz から AMD64 2800+ に移ったときの違いは凄かった。10 倍ぐらい速かったのでは。どうも、この時の衝撃が残っているのが落胆の一因でもあるのかも知れない。

さて、これを読んだ方々はこの結果を大きいと見るのであろうか。それとも、大したものではないと思うのだろうか。