カテゴリー「Ruby」の30件の投稿

2011年2月11日 (金)

igo-ruby 0.1.3

RubyRuby 1.9.2の確認環境が整ったので、形態素解析エンジンigo-rubyの動作を確認してみたところ、見事動作せず。

Ruby 1.9系のお作法を適用したら動くようになったので、version 0.1.3としてリリースしました。

というアレで今回のリリースノートは

  • Ruby 1.9系でも動作するように修正
だけです。

続きを読む "igo-ruby 0.1.3"

| | コメント (1) | トラックバック (0)

2011年2月 9日 (水)

複数バージョンのRubyをRVMで管理する

RubyそろそろRails3にも触れておきたいし、Rails3ならいっそのことRubyも1.9系に上げておきたい。
でも、メインで使ってるのはまだRails2.3系で、Rubyも1.8.7。言語もフレームワークも同時にバージョンを上げるのはリスキー…というほどRailsもRubyも使ってはいないんだけど、緩やかに移行した方がトラブルが少ないのも事実。

となると、Rails3とRails2の開発環境を準備して、必要に応じて切り替えるのが常套手段に思える。
Rails3はRuby1.9.2(と1.8.7)で動作保証されているらしいので、

  • (現環境として)Ruby 1.8.7 + Rails2
  • (新環境として)Ruby 1.9.2 + Rails3
の2つの環境を切り替えるという方針が良さそう。

続きを読む "複数バージョンのRubyをRVMで管理する"

| | コメント (0) | トラックバック (0)

2011年1月 8日 (土)

igo-rubyの性能

Rubyこの辺で作った形態素解析エンジンigo-ruby

あまりにも大きいドキュメントを解析するのは時間がかかるだろうと予想できるけど、どのくらいの粒度のドキュメントを解析すると実用的なのか、計測してみました。

一応、この辺で問題なく動いているんですけど、こういうのをそれなりに測定して、数字を知っておくと、それなりに有効だったりするわけです。

続きを読む "igo-rubyの性能"

| | コメント (0) | トラックバック (0)

2010年12月17日 (金)

RubyGemsの命名規約

Rubyigo-rubyの名前を決めるときにigo-rubyとigo_rubyとigorubyで悩んだ。

gemsの命名規約はたぶん厳密には決まってないんだけど、How to Name Gems強く推奨しているのは

  1. 通常requireするgemはアンダースコア(_)を使う。
  2. 他のgemを拡張する場合はハイフン(-)を使う。install net-http-persistentならrequireは"net/http/persistent"となる。
  3. アッパーケース(UpperCamel)は使わない。
という規則。

上記に従えばigo-rubyではなくigo_rubyとなるんだけど、igo-rubyはIgoのRuby版という位置づけだし、すでにigo-pythonもある。

あと、"ruby"に限れば、アンダースコア(*_ruby)よりもハイフン(-ruby)の方が多い気がする。
ということで、公開されているgemsの一覧を取得して、カウントしてみた。

まずは"_ruby"で終わるgems。

$ gem list -r | grep -e ".*_ruby "
cheddargetter_client_ruby (0.2.1)
collecta_ruby (0.1.3)
dcu-purple_ruby (0.7.0)
endless_ruby (0.0.1)
purple_ruby (0.6.7)
rrt_ruby (0.3.1 mswin32)
ruboss_on_ruby (1.0.1)
shattered_ruby (0.5.1)
strophe_ruby (0.0.5 ruby x86_64-linux)
talib_ruby (1.0.1)
tem_ruby (0.16.0)
which_ruby (0.0.3)
win_user32_ruby (0.1.0)
xbm_ruby (1.0.1)
15個。
一方、"-ruby"で終わるgemsは
$ gem list -r | grep -e ".*-ruby "
aalib-ruby (0.7.1)
adesklets-ruby (0.2.0)
amazon-fps-ruby (1.0.0)
atmos-ruby (1.4.0.7)
bb-ruby (0.9.5)
bcrypt-ruby (2.1.2)
benofsky-yajl-ruby (0.7.7)
btparse-ruby (0.2)
bzip2-ruby (0.2.7)
constant-contact-ruby (0.2.4)
couchdb-ruby (0.8.0)
coupa-libxml-ruby (1.1.4)
cql-ruby (0.8.2)
dailymile-ruby (0.1.3)
darcs-ruby (0.0.1)
dcas-ruby (0.4.0)
dnsimple-ruby (0.8.3)
dokan-ruby (0.0.1 mswin32)
douban-ruby (0.0.7)
dsf-ruby (0.0.0)
edge-parsley-ruby (0.4.5)
espeak-ruby (0.3.0)
evented-gearman-ruby (1.0.0)
evil-ruby (0.1.0)
fetchapi-ruby (1.1.1)
ffmpeg-ruby (0.1.3)
filipegiusti-yajl-ruby (0.6.4)
fitnesse-ruby (0.1.0)
fityk-ruby (1.0.0)
frenchrevcal-ruby (1.0.0)
ft2-ruby (0.1.3)
gearman-ruby (3.0.3)
google-spreadsheet-ruby (0.1.2)
gowalla-ruby (0.0.5)
greenpepper-ruby (0.0.1)
grendel-ruby (0.1.5)
gvoice-ruby (0.3.3)
harvest-ruby (0.1.1)
hbase-ruby (1.2.0)
id3lib-ruby (0.6.0 ruby x86-mswin32-60)
igo-ruby (0.1.2)
ipxact-ruby (0.13.0)
jberkel-mysql-ruby (2.8.1)
jblas-ruby (1.1.1)
kaltura-ruby (0.1.1)
koi-vm-ruby (0.0.4)
lda-ruby (0.3.1)
le1t0-parsley-ruby (0.4.5.001)
libqalculate-ruby (0.0.1)
libxml-ruby (1.1.4 ruby x86-mswin32-60)
libxosd-ruby (0.4)
libxosd2-ruby (0.4)
libxsl-ruby (0.3.6)
libxslt-ruby (0.9.7)
matlab-ruby (2.0.3)
mediainfo-ruby (0.2.0)
ming-ruby (1.0 mswin32)
ml-ruby (0.0.1)
monetra-ruby (0.0.6)
mplayer-ruby (0.1.0)
myspace-ruby (0.7.1)
newick-ruby (1.0.3)
nozbe-ruby (0.2.0)
nugramserver-ruby (0.1.0)
nvtristrip-ruby (0.5.0)
octave-ruby (1.0.9)
opentick-ruby (0.1.1)
opentox-ruby (0.0.2)
org-ruby (0.5.3)
osc-ruby (0.7.0)
pandoc-ruby (0.4.1)
pangel-sg-ruby (0.1.1)
parsley-ruby (0.4.5)
penctl-ruby (0.1.3)
phpass-ruby (0.1.2)
pomo-ruby (0.0.3)
portal-ruby (0.0.2)
ppe-4store-ruby (0.0.3)
prince-ruby (0.3.0)
puremvc-ruby (1.0.0)
radamanthus-superfeedr-ruby (0.4.3)
remember-the-ruby (1.3.0)
remoteling-ruby (0.0.5)
rounders-gdata-ruby (1.1.2)
s3-ruby (0.1.0)
saas_pulse-ruby (0.1.2)
sam-mysql-ruby (2.8.1)
serdisplib-ruby (0.5.2 x86-linux)
sg-ruby (0.1.0)
shodan-ruby (0.1.1)
sishen-hbase-ruby (1.0)
solr-ruby (0.0.8)
sprout-google-spreadsheet-ruby (0.0.1)
sqlite-ruby (2.2.3 ruby mswin32)
sqlite3-ruby (1.3.2 ruby x86-mingw32 x86-mswin32-60, 1.2.5 x86-mswin32, 1.2.3 mswin32)
sugestio-ruby (0.1.0)
superfeedr-ruby (0.4.3)
thumbnailer-ruby (0.1.2)
tickspot-ruby (0.1.0)
tropo-webapi-ruby (0.1.9)
tuio-ruby (0.2.5)
twaudio-ruby (0.1)
tworgy-ruby (0.4.2)
typesafe-ruby (0.0.2)
userapi-ruby (0.0.1)
velir_kaltura-ruby (0.4.9)
viddler-ruby (0.1.0)
vim-ruby (2007.05.07)
vtk-ruby (5.0.4.0 x86-mswin32-60)
web-socket-ruby (0.1.0)
win-gdi32-ruby (0.1.3)
win-user32-ruby (0.1.7)
wolframarnold-google-spreadsheet-ruby (0.1.4)
wordnik-ruby (0.3.2)
xmlsec-ruby (0.0.6)
yajl-ruby (0.7.8)
116個。
圧倒的に"-ruby"が多い。
やっぱり○○のRuby版という意味のgemsは"-ruby"をつけてるんじゃないかと思う。(そういう意味づけじゃないgemsも多々あるかとは思いますが。)

これらを勘案して、今回はigo-rubyとした。

| | コメント (0) | トラックバック (1)

2010年12月16日 (木)

igo-rubyを作った経緯

Ruby昨日当blogでも公開したigo-ruby
その開発(というか移植作業)に至る経緯や、強み、弱みなんかをさらしてみる。

経緯

TwitterでIgoのPython版を知ったのが12月1日。
その元になっているIgoを調べてみると、解析結果がほぼMeCab互換のJava(とCommon Lisp)で実装された形態素解析器であることが分かった。

MeCabについては以前も取り上げているけど、例えばRubyなんかから気軽と使おうとすると特にWindows環境ではバインディングがインストールできなかったりしてちょっとメンドい。
(それでもMeCabをWindowsからラクに使いたいぜ、という方はこちらをどうぞ。)

Windows環境じゃなくても、例えばネット上の、自前じゃない環境(レンタルサーバとかVPSとか)で動かそうとすると、まぁやっぱりメンドくさいと思う。

その点、IgoはJavaオンリーで動作するので、JavaVMが動くところならどこでも動く(はず)。ヒジョーにポータビリティが高い。

イイとこに目をつけてんなぁ、と。

再度、igo-pythonに目を向けると、(あくまでも主観だけど)igo-python自体はIgoの解析用辞書をできるだけそのまま使用するように移植したようで、最小限の実装で「まずはpythonで動作する」ことを優先しているように見える。
(解析用辞書の生成機能も今後実装する予定があるようです。)

やはり、イイとこに目をつけてんなぁ、と。

この調子ならソッコーでRuby実装も出るはず!!とは思ったんだけど、igo-pythonのソースを眺めているうちに「俺でもなんとかなるかも?」と思ったのが運の尽き
翌日くらいからJava版とPython版のソースを横目に、実際に動かしながら(おかげで自宅のPCにEclipseとPython入れちゃったヨ)Rubyへの移植を進め、12月11日に初版をリリースした。

…実はアルゴリズムをろくに理解しておらず…データ構造もよく分かってなくて結構苦戦してたり…。

強み

上にも書いたけど、Igoの強みはJavaオンリーで動くところ。辞書さえあればigo-pythonはPythonのみで、igo-rubyはRubyのみで動作する。
お気に入りの(あるいは使い慣れた)言語以外の仕組みを導入しなくてイイというのは強い。強すぎる。

日常的にプログラミングを行う職業プログラマでさえ…あるいはそれ故かもしれないけど、環境を準備するという行為はけっこう壁が高い。そういう本質的ではない部分で手を煩わせたくないんである。情報過多の時代にあって、自分の守備範囲外の情報には触れたくないんである。
(これはこれで問題ではあるんだけど、ここでは触れません。)

よろしい。

igo-rubyは(辞書さえ準備すれば)あなたの環境で即座に動作する。

弱み

これはigo-rubyだけの弱みだけど、Igoの辞書ファイルに依存している、という点。辞書ファイルのフォーマットが変わってしまえば、igo-pythonは動作しない。

少なくとも、現在のIgoの最新版であるIgo 0.4.2で生成した辞書ファイルでは動作しているように見えるので、将来的に(辞書ファイルのフォーマット変更によって)igo-rubyが動作しなくなった場合は、ひとまずこの0.4.2で辞書ファイルを生成することにより対応できると思う。

| | コメント (0) | トラックバック (0)

2010年12月15日 (水)

形態素解析器IgoのRuby版を作った

Ruby解析結果がほぼMeCab互換のJavaおよびCommon Lispで実装された形態素解析器IgoのRuby版を作りました。

正確にはIgoのエンジン部分をRubyに移植しましたですけれども。

ソース

ソースはGitHubに公開
また、RubyGems.orgにgemを公開してあるので、インターネットに接続している環境ならRubyGemsでインストールできます。

インストール

コマンドラインで下記を入力。
$ gem install igo-ruby
igo-rubyは、別途Igoと同じ解析用辞書ファイルが必要です。(igo-pythonと同じ方式。ただし、igo-pythonの方は辞書ファイルの生成機能も実装予定とのことです。)

解析用辞書ファイルの生成方法については、Igoのページを参照してください。

使い方

Igo::Taggerクラスのコンストラクタに辞書ファイルが入ったディレクトリを指定して、parseメソッドを呼び出します。

require 'rubygems'
require 'igo-ruby'
tagger = Igo::Tagger.new('../../ipadic') # 解析用辞書のディレクトリを指定
t = tagger.parse('吾輩は猫である。名前はまだ無い。')
t.each{|m|
puts "#{m.surface} #{m.feature} #{m.start}"
}
実行結果は以下のようになります。
吾輩 名詞,代名詞,一般,*,*,*,吾輩,ワガハイ,ワガハイ 0
は 助詞,係助詞,*,*,*,*,は,ハ,ワ 2
猫 名詞,一般,*,*,*,*,猫,ネコ,ネコ 3
で 助動詞,*,*,*,特殊・ダ,連用形,だ,デ,デ 4
ある 助動詞,*,*,*,五段・ラ行アル,基本形,ある,アル,アル 5
。 記号,句点,*,*,*,*,。,。,。 7
名前 名詞,一般,*,*,*,*,名前,ナマエ,ナマエ 8
は 助詞,係助詞,*,*,*,*,は,ハ,ワ 10
まだ 副詞,助詞類接続,*,*,*,*,まだ,マダ,マダ 11
無い 形容詞,自立,*,*,形容詞・アウオ段,基本形,無い,ナイ,ナイ 13
。 記号,句点,*,*,*,*,。,。,。 15
分かち書きもできます。
t = tagger.wakati('どこで生れたかとんと見当がつかぬ。')
puts t.join(' ')

# 実行結果
どこ で 生れ た か とんと 見当 が つか ぬ 。
詳細はREADMEを参照のこと。

サンプルウェブアプリ

igo-rubyをライブラリとして利用したRailsのウェブアプリ(サンプル)も作りました。こちらで公開しております。

動作確認環境

下記環境で確認済みです。

  • Windows(XP)
  • Linux(CentOS)
  • Mac OS X(10.6系)

謝辞

igo-rubyは本家Igoと、そのPython実装であるigo-pythonのソースをできるだけそのまま移植したものです。
先人達の知恵に超感謝いたします。

| | コメント (4) | トラックバック (0)

2010年11月 6日 (土)

MacPortsでCouchDBをインストール

MacPortsRuby on Railsが動作するPaaS環境HerokuNoSQLなアドオンとしてCouchDBが利用できるようになったらしい。

ということでCouchDBをMac OS Xにインストール。

$ sudo port list couchdb
couchdb @1.0.1 databases/couchdb
現時点でのMacPortsリポジトリに上がってるバージョンは1.0.1。

さっそくインストール。

$ sudo port install couchdb
---> Computing dependencies for couchdb
---> Dependencies to be installed: autoconf help2man p5-locale-gettext perl5 perl5.8 m4 automake curl curl-ca-bundle libidn openssl zlib pkgconfig icu libtool spidermonkey nspr readline
---> Fetching perl5.8
---> Attempting to fetch perl-5.8.9.tar.bz2 from http://www.cpan.org/src/
---> Verifying checksum(s) for perl5.8
---> Extracting perl5.8
---> Applying patches to perl5.8
---> Configuring perl5.8
---> Building perl5.8
---> Staging perl5.8 into destroot
---> Installing perl5.8 @5.8.9_3
---> Activating perl5.8 @5.8.9_3
---> Cleaning perl5.8
---> Fetching perl5
---> Verifying checksum(s) for perl5
---> Extracting perl5
---> Configuring perl5
---> Building perl5
---> Staging perl5 into destroot
---> Installing perl5 @5.8.9_0
---> Activating perl5 @5.8.9_0
---> Cleaning perl5
---> Fetching p5-locale-gettext
---> Attempting to fetch gettext-1.05.tar.gz from ftp://ftp.cpan.org/pub/CPAN/modules/by-module/Locale
---> Verifying checksum(s) for p5-locale-gettext
---> Extracting p5-locale-gettext
---> Applying patches to p5-locale-gettext
---> Configuring p5-locale-gettext
---> Building p5-locale-gettext
---> Staging p5-locale-gettext into destroot
---> Installing p5-locale-gettext @1.05_3
---> Activating p5-locale-gettext @1.05_3
---> Cleaning p5-locale-gettext
---> Fetching help2man
---> Attempting to fetch help2man-1.38.2.tar.gz from ftp://ftp.dti.ad.jp/pub/GNU/help2man
---> Verifying checksum(s) for help2man
---> Extracting help2man
---> Configuring help2man
---> Building help2man
---> Staging help2man into destroot
---> Installing help2man @1.38.2_0
---> Activating help2man @1.38.2_0
---> Cleaning help2man
---> Fetching m4
---> Attempting to fetch m4-1.4.15.tar.bz2 from ftp://ftp.dti.ad.jp/pub/GNU/m4
---> Verifying checksum(s) for m4
---> Extracting m4
---> Configuring m4
---> Building m4
---> Staging m4 into destroot
---> Installing m4 @1.4.15_0
---> Activating m4 @1.4.15_0
---> Cleaning m4
---> Fetching autoconf
---> Attempting to fetch autoconf-2.68.tar.bz2 from ftp://ftp.dti.ad.jp/pub/GNU/autoconf
---> Verifying checksum(s) for autoconf
---> Extracting autoconf
---> Configuring autoconf
---> Building autoconf
---> Staging autoconf into destroot
---> Installing autoconf @2.68_0
---> Activating autoconf @2.68_0
---> Cleaning autoconf
---> Fetching automake
---> Attempting to fetch automake-1.11.1.tar.bz2 from ftp://ftp.dti.ad.jp/pub/GNU/automake
---> Verifying checksum(s) for automake
---> Extracting automake
---> Configuring automake
---> Building automake
---> Staging automake into destroot
---> Installing automake @1.11.1_0
---> Activating automake @1.11.1_0
---> Cleaning automake
---> Fetching curl-ca-bundle
---> Attempting to fetch curl-7.21.2.tar.bz2 from http://distfiles.macports.org/curl
---> Attempting to fetch certdata-1.65.txt from http://distfiles.macports.org/curl
---> Verifying checksum(s) for curl-ca-bundle
---> Extracting curl-ca-bundle
---> Applying patches to curl-ca-bundle
---> Configuring curl-ca-bundle
---> Building curl-ca-bundle
---> Staging curl-ca-bundle into destroot
---> Installing curl-ca-bundle @7.21.2_0
---> Activating curl-ca-bundle @7.21.2_0
---> Cleaning curl-ca-bundle
---> Fetching libidn
---> Attempting to fetch libidn-1.19.tar.gz from ftp://ftp.dti.ad.jp/pub/GNU/libidn
---> Verifying checksum(s) for libidn
---> Extracting libidn
---> Configuring libidn
---> Building libidn
---> Staging libidn into destroot
---> Installing libidn @1.19_0
---> Activating libidn @1.19_0
---> Cleaning libidn
---> Fetching zlib
---> Attempting to fetch zlib-1.2.5.tar.bz2 from http://distfiles.macports.org/zlib
---> Verifying checksum(s) for zlib
---> Extracting zlib
---> Applying patches to zlib
---> Configuring zlib
---> Building zlib
---> Staging zlib into destroot
---> Installing zlib @1.2.5_0
---> Activating zlib @1.2.5_0
---> Cleaning zlib
---> Fetching openssl
---> Attempting to fetch openssl-1.0.0a.tar.gz from http://distfiles.macports.org/openssl
---> Verifying checksum(s) for openssl
---> Extracting openssl
---> Applying patches to openssl
---> Configuring openssl
---> Building openssl
---> Staging openssl into destroot
---> Installing openssl @1.0.0a_1
---> Activating openssl @1.0.0a_1
---> Cleaning openssl
---> Fetching pkgconfig
---> Attempting to fetch pkg-config-0.25.tar.gz from http://distfiles.macports.org/pkgconfig
---> Verifying checksum(s) for pkgconfig
---> Extracting pkgconfig
---> Applying patches to pkgconfig
---> Configuring pkgconfig
---> Building pkgconfig
---> Staging pkgconfig into destroot
---> Installing pkgconfig @0.25_1
---> Activating pkgconfig @0.25_1
---> Cleaning pkgconfig
---> Fetching curl
---> Verifying checksum(s) for curl
---> Extracting curl
---> Configuring curl
---> Building curl
---> Staging curl into destroot
---> Installing curl @7.21.2_1+ssl
---> Activating curl @7.21.2_1+ssl
---> Cleaning curl
---> Fetching icu
---> Attempting to fetch icu4c-4_3_4-src.tgz from http://distfiles.macports.org/icu
---> Verifying checksum(s) for icu
---> Extracting icu
---> Applying patches to icu
---> Configuring icu
---> Building icu
---> Staging icu into destroot
---> Installing icu @4.3.4_0
---> Activating icu @4.3.4_0
---> Cleaning icu
---> Fetching libtool
---> Attempting to fetch libtool-2.4.tar.gz from ftp://ftp.dti.ad.jp/pub/GNU/libtool
---> Verifying checksum(s) for libtool
---> Extracting libtool
---> Configuring libtool
---> Building libtool
---> Staging libtool into destroot
---> Installing libtool @2.4_0
---> Activating libtool @2.4_0
---> Cleaning libtool
---> Fetching nspr
---> Attempting to fetch nspr-4.8.6.tar.gz from http://ftp.mozilla.org/pub/mozilla.org/nspr/releases/v4.8.6/src/
---> Verifying checksum(s) for nspr
---> Extracting nspr
---> Configuring nspr
---> Building nspr
---> Staging nspr into destroot
---> Installing nspr @4.8.6_0
---> Activating nspr @4.8.6_0
---> Cleaning nspr
---> Fetching readline
---> Attempting to fetch readline61-001 from ftp://ftp.dti.ad.jp/pub/GNU/readline/readline-6.1-patches/
---> Attempting to fetch readline61-002 from ftp://ftp.dti.ad.jp/pub/GNU/readline/readline-6.1-patches/
---> Attempting to fetch readline-6.1.tar.gz from ftp://ftp.dti.ad.jp/pub/GNU/readline
---> Attempting to fetch readline-6.1.tar.gz from http://mirror.facebook.net/gnu/gnu/readline
---> Verifying checksum(s) for readline
---> Extracting readline
---> Applying patches to readline
---> Configuring readline
---> Building readline
---> Staging readline into destroot
---> Installing readline @6.1.002_0
---> Activating readline @6.1.002_0
---> Cleaning readline
---> Fetching spidermonkey
---> Attempting to fetch js-1.7.0.tar.gz from http://ftp.mozilla.org/pub/mozilla.org/js/
---> Verifying checksum(s) for spidermonkey
---> Extracting spidermonkey
---> Applying patches to spidermonkey
---> Configuring spidermonkey
---> Building spidermonkey
---> Staging spidermonkey into destroot
---> Installing spidermonkey @1.7.0_4
---> Activating spidermonkey @1.7.0_4
---> Cleaning spidermonkey
---> Fetching couchdb
---> Attempting to fetch apache-couchdb-1.0.1.tar.gz from ftp://ftp.infoscience.co.jp/pub/net/apache/dist/couchdb/1.0.1/
---> Attempting to fetch apache-couchdb-1.0.1.tar.gz from http://mirror.facebook.net/apache/couchdb/1.0.1/
---> Verifying checksum(s) for couchdb
---> Extracting couchdb
---> Configuring couchdb
---> Building couchdb
---> Staging couchdb into destroot
---> Installing couchdb @1.0.1_0
---> Activating couchdb @1.0.1_0
########################################################################
# Run the following command to install the CouchDB launchd
# startup item in order to start and re-start service automatically:
#
# sudo launchctl load -w /Library/LaunchDaemons/org.apache.couchdb.plist
########################################################################
---> Cleaning couchdb
依存パッケージが大量にインストールされた。Perlも入ってんなぁ。

CouchDBをサービス(daemon)化するにはlaunchctlを使用する。

$ sudo launchctl load -w /opt/local/Library/LaunchDaemons/org.apache.couchdb.plist
ブラウザでhttp://localhost:5984/_utils/にアクセスするとFutonという管理ツールが起動する。

Futon

| | コメント (4) | トラックバック (0)

2010年6月19日 (土)

代理戦争

休日出勤。
とにかく残業規制のリミットを超えないように、とのお達しなのでサービスサービス。


今年に入って覚えた最初のカタカナ言葉はブブゼラかもしんない。Googleトレンドでも急激に伸びてます

Rubyオランダ戦、日本は惜しかったですな。
興味深かったツイートはこれでしょうか。日本vsオランダはRuby vs Pythonの代理戦争である、と。なるほど。

次の対戦相手であるデンマークはRuby on Railsを生み出した国ですな。Ruby vs Railsという構図はあまりない気がしますが、Rubyの国とRuby on Railsの国、どっちが強いでしょうか。

ちなみにRailsの作者DHHことDavid Heinemeier Hanssonはけっこうイケメンだったりします。もちろん、Rubyの作者であるMatzことまつもとゆきひろ氏も負けてませんヨ。

| | コメント (0) | トラックバック (0)

2010年5月19日 (水)

(続)Ernie : Ruby/Erlang Hybrid BERT-RPC Server

ErlangRubyBERT-RPC ServerのRuby/Erlang実装であるErnieについて、面白そうなところなど。
インストール方法等はこちらをどうぞ。

ちなみに、BertもErnieもセサミストリートに登場するキャラクターだそうです。

Bert + Ernie

こういう遊び心、好きですヨ。


さて、Ernieを動作させるためにはconfigファイルが必要なので、下記のように作成し、config.cfgというファイル名で保存することにします。

[{module, ext},
{type, external},
{command, "ruby rpc-handler.rb"},
{count, 3}].
外部モジュールとして"ruby rpc-handler.rb"を実行し、そのプロセス数は3つ、という意味です。
従って、RPCとして動作させる(Ruby)コードはrpc-handler.rbというファイル名で保存すればイイわけですね。

サーバでコードが実行できる

RPCなので当たり前ですけど、リモートのコードをローカルから呼び出せます。 上記config.cfgファイルをリモート(サーバ側)に配置し、次にrpc-handler.rbというファイル名で下記をリモート側に保存します。
#rpc-handler.rb
require 'rubygems'
require 'ernie'
module Ext def hello(name) return "Hi, #{name}. I'm #{`hostname`.chomp}." end end
Ernie.expose(:ext, Ext)
コマンドプロンプトで以下を実行し、Ernieを起動します。
$ ernie -d -p 9999 -c config.cfg
最後にローカル(クライアント側)で下記スクリプト(client.rb)を実行します。
#client.rb
require 'rubygems'
require 'bertrpc'
service = BERTRPC::Service.new('リモートサーバ名', 9999) puts service.call.ext.hello('bar')
リモートサーバ名はDNSで解決できる名前かサーバのIPアドレスを適宜入力します。 サーバ名がfooの場合、実行結果は以下のようになります。
$ ruby client.rb 
Hi, bar. I'm foo.
このfooという名前は、リモート側で
`hostname`
を実行した結果ですので、確実にリモートでの実行結果をローカルで呼び出していることが分かります。

数値、stringや配列、ハッシュマップ、正規表現等が流せる

BERT and BERT-RPC 1.0 SpecificationによるとBERTとして流せるデータ型は下記の通り。
  • integer
  • float
  • atom
  • tuple
  • bytelist
  • list
  • binary
  • nil
  • boolean
  • time
  • regex
上の例ではhelloメソッドの戻り値がstringとしてBERTでローカルに流れていることになります。

それではlistに該当すると思われる配列をBERTで流してみます。
rpc-handler.rbに下記メソッドを追加し、Ernieを再起動します。

def list()
return [1, 2,'three',[4,5,'six'],7]
end
client.rbのRPC呼び出し部分は下記のように変更します。
p service.call.ext.list()
実行結果は下記の通り、期待通りに配列が取得できています。
$ ruby client.rb
[1, 2, "three", [4, 5, "six"], 7]
ハッシュも流せます。
def hashlist()
return {:a=>'a', :b=>1, :list=>list}
end
の結果は
{:a=>"a", :list=>[1, 2, "three", [4, 5, "six"], 7], :b=>1}
ハッシュなので順番は保持されませんが、正しい動作です。

次はtimeを流してみます。
rpc-handler.rbに下記メソッドを追加し、Ernieを再起動します。

def what_time?
Time.now
end
ローカルの
p service.call.ext.what_time?
の結果は期待通り
Sun May 16 02:21:13 +0900 2010
のようになります。

最後に、regex(正規表現)を流してみます。プロトコル上に正規表現を流すシーンがあまり思い浮かばないので、このような使い方で合っているのか分かりませんが、例えばrpc-handler.rbに下記メソッドを追加し、

def regex
return /foo(.*)baz/
end
client.rbを下記のようにします。
"foobarbaz" =~ service.call.ext.regex
puts $1
実行結果は
bar
であり、確かに/foo(.*)baz/でマッチした部分が取り出せています。

あるいは、rpc-handler.rbを

def regex(rgx)
"foobarbaz" =~ rgx
return $1
end
とし、ローカル側を
puts service.call.ext.regex(/foo(.*)baz/)
として、ローカルの正規表現をリモートに流し、その結果をstringで取得しても
bar
となります。

使い道は分かりませんが、とにかくBERTで正規表現が流せることが分かります。

無停止でハンドラを適用できる

ここまでに、rpc-handler.rbを適用するために、Ernieを何度か再起動していますが、実は無停止でハンドラを適用することができます。 gitのErnieのページのREADMEによると
reload-handlers Gracefully reload all of the external handlers
とあり、graceful reloadが使えることが分かります。

使い方は、コマンドプロンプトで下記のようにernieコマンドを実行するだけです。

$ ernie reload-handlers -p 9999
この場合、ポート9999でErnieが動作していなければ、エラーになります。

Erlangのフォールトトレランス

config.cfgファイルに{count, 3}と記載しておけば、外部モジュール(rpc-handler.rb)のプロセスが3つ立ち上がることは上で説明しました。

確かめてみます。

$ps x | grep ernie
29795 pts/0 Sl+ 0:00 /usr/local/lib/erlang/erts-5.7.4/bin/beam.smp (略) boot
30738 ? Ss 0:00 ernie handler unknown (ruby) - rpc-handle.rb - [1] waiting
30740 ? Ss 0:00 ernie handler unknown (ruby) - rpc-handle.rb - [1] waiting
30765 ? Ss 0:00 ernie handler unknown (ruby) - rpc-handle.rb - [1] waiting
プロセスID=30738, 30740, 30765でrpc-handler.rbのプロセスがそれぞれ3つ立ち上がっていることが分かります。

ここで、30738をkillし、再びプロセスを見てみます。

$ kill -KILL 30738
$ ps x | grep ernie
29795 pts/0 Sl+ 0:00 /usr/local/lib/erlang/erts-5.7.4/bin/beam.smp (略) boot
30740 ? Ss 0:00 ernie handler unknown (ruby) - rpc-handle.rb - [1] waiting
30765 ? Ss 0:00 ernie handler unknown (ruby) - rpc-handle.rb - [1] waiting
31356 ? Ss 0:00 ernie handler unknown (ruby) - rpc-handle.rb - [0] waiting
なんと、30738はkillされましたが、代わりにプロセスID=31356が自動的に起動し、3つのプロセス数を保っています。

これはErnieがErlangで実装されていることが大きく寄与しているものと思われます。
Erlangには言語仕様としてのフォールトトレランス(耐障害性)機能があり、Erlangプロセスが落ちても自動的に復旧させることができます。

開発者が「プロセスが落ちたとき」の振る舞いに(それほど)頭を悩ませなくて済むのは大きな利点だと思います。

最後に

長々とErnieの特徴を見てきましたが、BERTというマイナーなプロトコルを扱うこと、RPCという(たぶん)トレンドではないアーキテクチャを扱っていることなどから、WEB系の開発ではErnieを使用することはあまりないかもしれません。 しかし、クラウドが隆盛をきわめている昨今においては、分散処理が重要なキーワードになる可能性があり、軽量RPC(という言い方が正しいか分かりませんが)は分散処理においても威力を発揮しそうです。

耐障害性を持ち、複雑な手順を必要とせずにリモートのコードが実行できるErnie/BERT-RPCや、その他の軽量RPCは、意外に今後注目されるかもしれません。

| | コメント (1) | トラックバック (0)

2010年4月26日 (月)

自炊クラウド

最近、自炊を再開しました。夕食だけですが。

で、調味料がすべて賞味期限切れ

一体、どんだけ自炊してなかったんだ、と。
もしかしたら、上海行ってたころくらいから自炊をしていなかったかもしれません。


レパートリーが増えているわけもないので、月間ページビューが4億4000万PVという噂のクックパッドのお世話に、そのうちなるかもしれません。

clipクックパッドのデータ処理、たった5万円

ちなみにこのクックパッド。
レシピサイトというよりはRuby on Railsつながりで知っていたのですが、最近ではデータ解析等を分散処理で効率化していて、それもAmazon EC2上でHadoop(+Ruby)を動かすというクラウドな構成。

clipRubyとHadoopで分散処理 Hadoop Streamingの仕組み


ま、そんなことは、毎日の献立に頭を悩ます主婦(主夫)なみなさまには全然カンケーないですな。

| | コメント (0) | トラックバック (0)