CentOS 5.1 の perl をリビルドする

2008-12-26 追記

CentOS 5.2 の updates の perl-5.8.8-15.el5_2.1 で下記該当パッチ+αがあたった状態になっています。もう自分でパッチをあててリビルドする必要はありません(RHEL 5(.2) の perl-5.8.8-15.el5_2.1 で例のバグが治っていた - daily dayflower)。

どのプロダクトが影響をうけるのか

2008/01/07 時点での RedHatperl パッケージについて調べてみた結果。

ディストリビューション RPM バージョン overload バグ パフォーマンス悪化
素 5.8.8 - × -
素 >= 5.9.4 -
FC 6 5.8.8-12 ×
Fedora 7 5.8.8-27.fc7
RHEL 5.1 5.8.8-10.el5_0.2 ×
RHEL 5.2 (up) 5.8.8-15.el5_2.1

表のヘッダと◎○×がわかりにくいですけど気にしないでください*1。×はよくないって意味です。

で,overload のバグが顕在化することはあんまりないので patch#27512 をはずしてリビルドするのが定説なんですが(Perl 5.8.8 の仕様といえばそれまでですし),Fedora 7 / 8 あたりではきちんと治っているのがムカツク!つか標準パッケージで遅いのがもっとムカツク!

ので,CentOS 5 でも overload バグに対処しつつパフォーマンス劣化を防いでみます。

CentOS 5.1 用にリビルドする

方針としては,

  1. Fedora 7 用の SRPM から patch#28775 を取り出し
  2. CentOS 5.1 用の spec に追加する

です。今回は x86_64 環境用の記述なので適宜読みかえてください。


まず Fedora 7 用の SRPM をとってきます(後々 patch#28775 を抽出するため)。また,CentOS 5.1 用の SRPM をインストールします。

% cd

% wget http://ftp.iij.ad.jp/pub/linux/fedora/updates/7/SRPMS/perl-5.8.8-27.fc7.src.rpm

% rpm -ivh http://ftp.iij.ad.jp/pub/linux/centos/5.1/updates/SRPMS/perl-5.8.8-10.el5_0.2.src.rpm

CentOS 5.1 用の 10.el5_0.2 の RPM spec ファイルに下記のパッチを当てます。

--- SPECS/perl.spec.dist        2007-10-24 01:16:56.000000000 +0900
+++ SPECS/perl.spec     2008-01-07 18:33:31.000000000 +0900
@@ -162,6 +162,7 @@
 Patch27426:    perl-5.8.8-U27426.patch
 Patch27509:     perl-5.8.8-U27509.patch
 Patch27512:     perl-5.8.8-U27512.patch
+Patch28775:     perl-5.8.8-U28775.patch
 Patch27604:     perl-5.8.8-U27604.patch
 Patch27605:     perl-5.8.8-U27605.patch
 Patch27914:     perl-5.8.8-U27914.patch
@@ -373,6 +374,8 @@
 
 %patch27512 -p1
 
+%patch28775 -p1
+
 %patch27604 -p1
 
 %patch27605 -p1
@@ -595,6 +598,9 @@
 
 %changelog
 * Tue Oct 23 2007 Robin Norwood <rnorwood@redhat.com> - 4:5.8.8-10.el5.2
+- Resolves: rhbz#196836
+- Apply upstream patch #28775, which fixes an issue where reblessing
+  overloaded objects incurs significant performance penalty
 - Resolves: bug#323811
 - fix previous patch

patch#27512 があたりっぱなしになっているのが気になりますが,Fedora 7/8 の spec でもあたりっぱなしなので踏襲しました。これはやっぱ必要みたい。

さて,上記ファイルをたとえば perl-spec.patch などの名前で保存し,patch をあてます。

% cd ~/rpmbuild

% patch -p0 < ~/perl-spec.patch

次に,先ほど述べたように Fedora 7 用の SRPM から patch#28775 を抽出して SOURCES フォルダに置きます。

% cd ~/rpmbuild/SOURCES

% rpm2cpio ~/perl-5.8.8-27.fc7.src.rpm | cpio -i perl-5.8.8-U28775.patch
20436 blocks

あとは,perlRPM パッケージを作成します。

% cd ~/rpmbuild

% rpmbuild -bb SPECS/perl.spec

作成できたら(なるべく perl 系が常駐していない環境で)旧 perl のパッケージを削除し,ゴミを削除して新しいパッケージをインストールします。

% sudo rpm -e --nodeps perl

% sudo rm -r /usr/lib/perl5/5.8.8
% sudo rm -r /usr/lib64/perl5/5.8.8

# 下記 2 件はお好みで
% sudo rm -r /usr/lib/perl5/site_perl/5.8.8
% sudo rm -r /usr/lib64/perl5/site_perl/5.8.8

% sudo rpm -ivh ~/rpmbuild/RPMS/x86_64/perl-5.8.8-10.2.x86_64.rpm

うまくいったか

Yappo さんのベンチマークをとってみます。

% perl yappo.t

Benchmark: timing 1000000 iterations of not overload, overload...
not overload:  1 wallclock secs ( 1.68 usr +  0.00 sys =  1.68 CPU) @ 595238.10/s (n=1000000)
    overload:  2 wallclock secs ( 1.69 usr +  0.00 sys =  1.69 CPU) @ 591715.98/s (n=1000000)

無事パフォーマンスペナルティがなくなりました。とぅっとぅるー(^ω^)

overload のバグについても,

% cat > overload.pl

#!/usr/bin/perl
use strict;
use warnings;

package Stringify;
use overload q{""} => sub { 'Hi!' };

package main;

my $a = { };
my $b = $a;

bless $a, 'Stringify';

print $b, "\n";
^D

% perl overload.pl
Hi!

きちんと対応できてます。

*1:Perl 5.9.4 以降は抜本的解決がなされているので◎にしました。つまりパッチあて状態とは等価ではないということです