Subscribed unsubscribe Subscribe Subscribe

mysql プロンプト起動時に自動で SET NAMES utf8; を発行する

mysql
$ mysql -uuser --init-command='set names utf8;'

メソッドが定義されたファイル名と行番号を取得するコマンドを作った

perl
$ source_location.pl File::Spec canonpath
FILENAME: /Users/Cside/.../File/Spec/Unix.pm
LINE:    71

親クラスまでたどった大元の定義位置を返すので、クラス階層が複雑なときにデバッグに役立つ。 cpanm UNIVERSAL::source_location_for するとコマンドが使える。

UNIVERSAL::source_location_for は 結構前から CPAN に上げていた が、自分ではもっぱらラッパーコマンドから使うことがほとんどだったので、今回のバージョンでそのコマンドも同梱したという経緯。

-I オプションで任意のパスを通すようにするか迷ったが、 zsh なら perl =source_location_for -Iextlib で同じことができるので、まあいいかと思って今回は見送った。需要あれば p-r おなしゃす。 -> https://github.com/Cside/UNIVERSAL-source_location_for

「 bless は重い」は本当か

perl

よく「 Perl の bless() は重いので new() しまくるとパフォーマンス悪化につながる。シングルトン化せよ」みたいなのを聞く(ような気がする。気のせいかも)。

なので、

  1. ループ中で都度 new する方法
  2. インスタンスを使いまわす方法

で速度を測ってみた。

use Time::HiRes

# 7027.247 ms
{
    my $start = [ Time::HiRes::gettimeofday ];
    for (1..100_000) {
        Foo->new(map { $_ => $_ } 1..100);
    }
    print Time::HiRes::tv_interval($start) * 1000, "\n";
}
# 7297.862 ms
{
    my $start = [ Time::HiRes::gettimeofday ];
    for (1..100_000) {
        Foo->instance(map { $_ => $_ } 1..100);
    }
    print Time::HiRes::tv_interval($start) * 1000, "\n";
}

package Foo;

sub new {
    my ($class, %args) = @_;
    bless \%args, $class;
}

sub instance {
    my ($class, %args) = @_;
    state $instance ||= Foo->new;
    for my $key (keys %args) {
        $instance->{$key} = $args{$key};
    }
}

ほとんど一緒。

bless が重いという噂は聞き間違いで、 OO な実装が関数呼び出しな実装より遅くなるよ、という話だったのかもしれない。

See Also