12 April 2008

XML::LibXML で属性を取り出すときのベンチマーク

XML::LibXML を使って、XML の属性を取り出すときに findvalue メソッドで XPath を使うのと XML::LibXML::Element のメソッド getAttribute を使うのとどちらが早いのかベンチマークしてみました。

Benchmark: timing 10000 iterations of accessor, xpath...
 accessor: 0 wallclock secs ( 0.05 usr + 0.00 sys = 0.05 CPU) @ 200000.00/s (n=10000)   (warning: too few iterations for a reliable count)
 xpath: 1 wallclock secs ( 0.55 usr + 0.00 sys = 0.55 CPU) @ 18181.82/s (n=10000)

XPath の方が遅いのか。。。XPathエンジンとか重たいのかな?

以下がコードです。

#!/usr/local/bin/perl
use strict;
use warnings;
use XML::LibXML;
use Perl6::Say;
use Benchmark;
my $xp = XML::LibXML->new;
my $doc = $xp->parse_string(<<"XML");
<?xml version="1.0"?>
<doc attr="please">
please ignore.this is a test.
</doc>
XML

my $xml = $doc->documentElement;

timethese (10000, {
    'accessor' => sub { $xml->getAttribute('attr') },
    'xpath' => sub { $xml->findvalue('@attr') },
});

追記
さらに、Devel::Profile を用いて、上記の timethese の中の accessor と xpath のそれぞれ片方だけを実行した結果の上位10位です。(上記のコードを baz.pl として保存して、perl -d:Profile baz.pl と実行)

'accessor'のみ実行(#'xpath'の行をコメントアウト)


time elapsed (wall): 0.7500
time running program: 0.5730 (76.40%)
time profiling (est.): 0.1770 (23.60%)
number of calls: 41183

%Time Sec. #calls sec/call F name
34.91 0.2000 20000 0.000010 :.../Perl/5.8.6/Benchmark.pm:651
18.27 0.1047 10000 0.000010 XML::LibXML::Element::getAttribute
10.43 0.0598 1 0.059758 :.../Perl/5.8.6/Benchmark.pm:675
10.41 0.0597 10000 0.000006 XML::LibXML::Element::_getAttribute
10.30 0.0590 1 0.059044 :.../Perl/5.8.6/Benchmark.pm:682
3.16 0.0181 1 0.018114 :baz.pl:6
1.23 0.0071 383 0.000018 Benchmark::new
1.17 0.0067 0 0.006728 *
1.15 0.0066 1 0.006588 :baz.pl:9
1.10 0.0063 1 0.006291 :baz.pl:8

'xpath'のみ実行(#'accessor'の行をコメントアウト)


time elapsed (wall): 2.2250
time running program: 1.7546 (78.86%)
time profiling (est.): 0.4705 (21.14%)
number of calls: 111103

%Time Sec. #calls sec/call F name
21.90 0.3842 10000 0.000038 XML::LibXML::Node::_find
17.64 0.3096 10000 0.000031 XML::LibXML::Node::findvalue
11.83 0.2076 10000 0.000021 XML::LibXML::NodeList::to_literal
11.63 0.2041 20000 0.000010 :.../Perl/5.8.6/Benchmark.pm:651
11.26 0.1976 10000 0.000020 XML::LibXML::Node::find
3.90 0.0684 10000 0.000007 XML::LibXML::Node::string_value
3.56 0.0625 1 0.062548 :.../Perl/5.8.6/Benchmark.pm:682
3.44 0.0604 1 0.060442 :.../Perl/5.8.6/Benchmark.pm:675
3.36 0.0590 10000 0.000006 XML::LibXML::Literal::new
3.23 0.0566 10000 0.000006 XML::LibXML::NodeList::new

08 April 2008

みやがせ

みやがせ

31 March 2008

TypePad エンジニアも募集しています。

シックス・アパートの求人のページで、住職の募集とありますが、住職じゃないけどシックス・アパートのプロダクトに興味のある開発者も募集しております。お経もいいけど TypePad もね。

シックス・アパート的にはコードが書ける住職がベストですね。

住職の方の主な業務内容は以下の通りだそうです。さすが外資系は違いますね。

主な業務内容

* 毎日の坐禅において社員にカツを入れる
* 週1回の全社ミーティングで法話を語る
* 年に2回のお盆イベントを主催する
* 定期的に読経を行う
* shakyou-a-thonを主催する

26 March 2008

Hash::Merge

Perl でハッシュをマージしたいなと思った。というか Catalyst で config メソッドはどうなっているのか見てみたら、Catalyst::Component の config メソッドで Catalyst::Utils::merge_hashes を呼び出している。merge_hashes($a, $b) としたときに、$a に $b をマージするためにいろいろとごにょごにょしているわけです。そのごにょごにょ(つまり Catalyst::Utils::merge_hashes)を単体で使いたいと思ったけど Catalyst 名前空間のモジュールは依存関係に含めるとちょっと厄介なイメージがあったので、単体で使えるモジュールが CPAN にないか探してみたらありました。

Hash::Merge

名前からしてズバリな感じです。

使い方は perldoc にあるように次の通り。

use Hash::Merge qw( merge );my %a = (    'foo'  => 1,    'bar'  => [ qw( a b e ) ],    'querty' => { 'bob' => 'alice' },);my %b = (    'foo'  => 2,    'bar'  => [ qw(c d) ],    'querty' => { 'ted' => 'margeret' },);

my %c = %{ merge( \%a, \%b ) };

とすると、デフォルトでは %a から %b に上書きする感じになって結果は次のようになります。

$VAR1 = 'bar';$VAR2 = [     'a',     'b',     'e',     'c',     'd'    ];$VAR3 = 'querty';$VAR4 = {     'bob' => 'alice',     'ted' => 'margeret'    };$VAR5 = 'foo';$VAR6 = 1;

ARRAYは結合してくれているし、SCALARは上書きしてくれているし、HASHはマージしてくれている。

で merge メソッドの第二引数を第一引数にかぶせたい場合もあるでしょう。そんなときには Hash::Merge::set_behavior メソッドを使います。
先ほどの上記のコードは以下のようになります。

use Hash::Merge qw( merge );my %a = (    'foo'  => 1,    'bar'  => [ qw( a b e ) ],    'querty' => { 'bob' => 'alice' },);my %b = (    'foo'  => 2,    'bar'  => [ qw(c d) ],    'querty' => { 'ted' => 'margeret' },);

Hash::Merge::set_behavior( 'RIGHT_PRECEDENT' );
my %c = %{ merge( \%a, \%b ) };

とすると結果は次の通りです。

$VAR1 = 'bar';$VAR2 = [     'a',     'b',     'e',     'c',     'd'    ];$VAR3 = 'querty';$VAR4 = {     'bob' => 'alice',     'ted' => 'margeret'    };$VAR5 = 'foo';$VAR6 = 2;

SCALAR である foo が %b の方を採用して 2 になっているのがわかりますね。

merge メソッドの引数の書き方を見れば分かるようにハッシュのリファレンスを渡していますし、merge メソッドの戻り値もハッシュのリファレンスなので次のように書く事もできます。

my $a = {    'foo'  => 1,};my $b = {    'foo'  => 2,};my $c = merge( $a, $b );

そうすれば結果は以下のようにになりますね。

$VAR1 = {     'bar' => [           'a',           'b',           'e',           'c',           'd'          ],     'querty' => {            'bob' => 'alice',            'ted' => 'margeret'           },     'foo' => 2    };

これはいい。Hash::Mergeを採用してみることに決めました。

25 March 2008

花見

桜が少しずつ花を咲かせていますが、我々のオフィスのみんなと花見に行く計画があります。楽しみです。

23 March 2008

多摩動物園

多摩動物園に行ってきました。広くて一日ではまわりきれないですね。ライオンバスはおすすめです。ライオンがえさを食べる姿を目の前で見ることができます。これはとても興味深いです。
それから今日はコアラの機嫌がよかったのかわるかったのかコアラが木から降りて床を歩き回っていました。こんな姿はなかなか見られないですね。
いやー楽しかったです。また行こうと思います。

Continue reading »

21 March 2008

テストです。

This is a test. please ignore this entry. thanks.

19 March 2008

xs:choice

今、XML Schema について少し学んでいるのですが、xs:choice について疑問があって調べました。

xs:choice というのは以下の例の場合、foo, bar, baz のいずれか一つを選択しなければなりません。

<xs:choice>  <xs:element name="foo" />  <xs:element name="bar" />  <xs:element name="baz" /></xs:choice>

xs:choice には 2 つの属性があります。

  • minOccurs (デフォルトは1)
  • maxOccurs (デフォルトは1)

なので、<xs:choice minOccurs="1" maxOccurs="1"> ということになるわけです。でも省略されているから、<xs:choice> は必ず一つを選択するということです。
で、<xs:choice minOccurs="0"> とした場合は 1 つ含まれるかもしれないということになるので、選択してもいいし選択しなくてもよくなります。(具体的にはmaxOccurs="1"なので、0か1ということです。)

<xs:choice minOccurs="0">  <xs:element name="foo" />  <xs:element name="bar" />  <xs:element name="baz" /></xs:choice>

foo, bar, baz のうちの1つあるかないかってことですね。

で、当初悩んでいたのが、次の例です。

<xs:choice minOccurs="0" maxOccurs="unbounded">  <xs:element name="foo" />  <xs:element name="bar" />  <xs:element name="baz" /></xs:choice>

unbounded は無制限の意味になります。ではこのときfoo, bar, baz はいくつ選ぶことができるか?
foo, bar, baz の 3 つでも OK ですし、それこそ foo, foo, bar, bar, bar, baz でも OK らしいです。もう choice の意味がないんじゃないか?と思う程。むしろ、xs:choice をやめて以下のようにしてもいいんじゃないか?と思ったり。(おそらく xs:choice にする意味がどこかにあるからこそ、xs:choice を使っているのだと思いますが。。。)

  <xs:element name="foo" minOccurs="0" maxOccurs="unbounded" />  <xs:element name="bar" minOccurs="0" maxOccurs="unbounded" />  <xs:element name="baz" minOccurs="0" maxOccurs="unbounded" />

ま、私は今のところ XML Schema を書くのではなく読む側なので、<xs:choice minOccurs="0" maxOccurs="unbounded"> の意味さえ分かればそれで OK なのですが、それにしても XML Schema は自由すぎて不自由な感じがしました。

ちなみに RelaxNG で書くと以下になります。

( foo | bar | baz )*

ところで、W3C の XML Schema の和訳ってなにげに少ないんですね。。。


参考

15 March 2008

テスト

soccerテストです。 please ignore this entry.baseball

春ですね。

今日はとても暖かい。こんな日はうたた寝をしてしまいそうです。

Access Ranking

Powered by Six Apart
Sponsored links