Just another Ruby porter,

〜2004年5月中旬〜


<Prev(,) | Next(.)> | Recent(/)>> | RDF

2004-05-11 (Tue)

[Ruby] Rubyの拡張ライブラリの仕組み

Rubyの拡張ライブラリの仕組みは簡単だ。 require 'foo'を実行すると

  1. foo.soを$LOAD_PATHから探してロード(dlopen)する
  2. Init_fooというシンボルを元にアドレスを取得(dlsym)しInit_foo()を実行

ということが行なわれる。

だから一番簡単な何もしない拡張ライブラリは

Init_foo(){}

だけいい。

% echo 'Init_foo(){}' > foo.c
% ruby -rmkmf -e 'create_makefile("foo")' 
creating Makefile
% make
gcc -fPIC -Os  -fPIC  -I. -I/usr/local/lib/ruby/1.9/i386-linux \
  -I/usr/local/lib/ruby/1.9/i386-linux -I.   -c foo.c
gcc -shared  -L'/usr/local/lib' -o foo.so foo.o  \
  -lruby  -ldl -lcrypt -lm   -lc
% ruby -r./foo -e 'p $"'
["./foo.so"]

何にも依存してないんだから、もっと簡単に

% gcc -shared foo.c -o foo.so
% ruby -r./foo -e 'p $"'
["./foo.so"]

で十分。

もうちょっと実用的なものとしては

% cat >binmode.c
#include <fcntl.h>
#include <stdlib.h>
Init_binmode(){_fmode = O_BINARY;}
% gcc -mno-cygwin -s -shared binmode.c -o binmode.so

なんてのが考えられる(msvcrt用)。

% /c/mingw32/bin/ruby -e 'open("foo.txt","w"){|f|f.puts}'
% od -c foo.txt
0000000  \r  \n
0000002
% /c/mingw32/bin/ruby -r./binmode -e 'open("foo.txt","w"){|f|f.puts}'
% od -c foo.txt
0000000  \n
0000001

このようにrubyの変数や関数を参照しない場合は非常に簡単。 でも、普通はクラスを作ったりするのでこんなに簡単には済まない。 特にWindowsのDLLのような場合は。 [ruby-talk:99770]がcrashするのはそのあたりに原因がある。

とここまで書いてて眠くなった。つづく(かも)。


2004-05-12 (Wed)

[Ruby] Schwartzian Transform

Ruby 1.6.8にはsort_byはないけど、 shimにも含まれているように、sort_byは

def sort_by
  ary = map { |i| [yield(i), i] }
  ary.sort! { |a, b| a[0] <=> b[0] }
  ary.map! { |i| i[1] }
end

と書けます。これはPerlのSchwartzian Transformです。 これでなぜ速くなるかというと、 時間がかかるget_post_time()を各ファイルに対して1度しか呼ばなくなるからです。

cacheという意味では

tcache = {}
@storys.sort! {|f1,f2|
  (tcache[f1] ||= get_post_time(f1)) <=> (tcache[f1] ||= get_post_time(f2))
}

のようにするのがお手軽です。 たしかEffective Perlでシャチ泳ぎという名前で紹介されていた手法です。 こっちのほうがわかりやすいですね。

それと あのpatchに含まれている、lily.cgiのRUBY_VERSIONと、 plugin/trackback.rbの//nの部分に関してはRuby 1.6でも有効なので、 できれば取り込んでください。


2004-05-13 (Thu)

[Ruby] ruby-talk 100000

とうとう100000を越えた。 90000からは4ヶ月。

[Soft] gcovの互換性

先月GCCを3.4.0に上げたけど、その直前にカバレッジを測定したデータファイルがすでに使えなくなっていることがわかった。

% gcov main
main.gcno:cannot open graph file

GCC 3.3.xまではmain.daだったんだけどなあ。 GCCのlibgcc2.cを見ると3.2と3.3の内部構造も違う。 minorが上がるたびに何かいじってるのか。

lcovはどうかなと見に行ってみると、早速lcov 1.3でGCC 3.4.0に対応してるようだ。 素早い。


2004-05-14 (Fri)

[Soft] Dnsmasq 2.8

Changes:

This release fixes a bug which could result in dnsmasq losing track of DHCP leases under certain very specific circumstances. It also fixes interoperability with the Linux kernel's built-in DHCP client, and has the usual small crop of configuration enhancements.

[Ruby] 1.8.2

ruby_1_8 branchのversion.hが1.8.2になった。 configureの実行も忘れずに。


2004-05-15 (Sat)

[Bloglines] Bloglines Plumberおやじ

Downtime This Evening

Bloglines will be down this evening starting at 7pm Pacific Time. We've grown so much recently that we have run out of room to add more machines at our hosting provider, so we need to move to a larger area. We expect the move to take 4 hours.

またオーバーオールのおやじが登場。 しかし、Bloglinesが見られないとニュースを見るのも面倒なことに。 かなり依存してるなあと感じる今日この頃。

[Ruby] lily 0.1.5b

試すデータがなければ作ればいいわけで、10000個ほど用意してみた。

% mkdir log/tmp
% ruby -e '10000.times{|i| open("log/tmp/data%06d.txt" % i, "w"){|f|f.print "foo\nbar\n"}}'
% ruby httpd.rb &
% time wget -q -O /dev/null http://localhost:10080/lily.cgi
wget -q -O /dev/null http://localhost:10080/lily.cgi  0.01s user 0.00s system 1% cpu 0.689 total

結構速い。

でも、sort_byはrespond_to?か何かで調べて、なければ定義するほうがいいでしょう。

unless [].respond_to? :sort_by
  module Enumerable
    def sort_by
      ...
    end
  end
end

[Tips] zsh: argument list too long: mvの対処のしかた

実はさっき間違えてデータをlog/に作ってしまったんだが、ちょっと困ったことになった。 単純にmvすればいいやとmv *.txt tmpとしたら

zsh: argument list too long: mv

となってしまうのだ。まあ、そうだよな。10000個もあれば。 この場合は消してやりなおせばいいんだけど、消せないときはどうすればいいのか?

最初に思い浮かぶのはfindとxargsの組み合わせだが、

% find . -name '*.txt' -maxdepth 1 | xargs -i mv '{}' tmp

では、'{}'はファイル1個1個に展開されるようで時間がかかりすぎる。 というか、何のためのxargsだ。それならfindの-execでいい。

mv --helpを見ると

--target-directory=DIRECTORY move all SOURCE arguments into DIRECTORY

というオプションが見つかった。おぉ。流石GNU fileutilsだ。cpにもあるね。

% find . -name '*.txt' -maxdepth 1 | xargs mv --target-directory=tmp

でいいわけだ。

[Ruby] lilyの.entrydateバージョンの高速化

まさか(S)DBMを使う処理がそのまま取り込まれるとは思ってなかったので、今までの.entrydateを使うバージョンの高速化を考えてみる。

一番時間がかかっているのは.entrydateの読み込みの部分。 この部分を最初に1回だけ読んで、Hashで取っておけばよさそう。 そうすればsort_byを使う必要もない。

def get_post_time(file)
  unless @done
    @ptimes = {}
    begin
      File::open("#{@datadir}/.entrydate","r"){|f|
        f.readlines.each{|pts|
          file, time = pts.split(/@@/)
          @ptimes[file] = Time.rfc2822(time)
        }
      }
    rescue
    end
    @done = true
  end

  @ptimes[file] ||=
  begin
    mtime = File::stat(file).mtime
    @entrydate ||= File::open("#{@datadir}/.entrydate","a")
    @entrydate.puts "#{file}@@#{mtime.rfc2822}"
    mtime
  end
end

これでsortも元に戻して実行。

% time wget -q -O /dev/null http://localhost:10080/lily.cgi
wget -q -O hoge.html http://localhost:10080/lily.cgi  0.01s user 0.00s system 1% cpu 0.889 total

まずまずか。でもこうするなら読み込みはinitializeでやるべきだな。


2004-05-16 (Sun)

[Ruby] __END__と__DATA__

Perlには__DATA__があるが、Rubyにはない。 __END__と__DATA__の違いは簡単に言うと対象となるファイルが$0と__FILE__との違いと思えばいい。 main::DATAとPACKNAME::DATAという違いもあるか。

Rubyで書いてみると

DATA = open($0)
DATA.gets("__END__\n")

DATA = open(__FILE__)
DATA.gets("__DATA__\n")

かな。とlily.cgiを見てて思ったり。

つまり、lily.cgiをlily.rbと名前を変えたとしても

% ruby -rlily -rcgi -e 'Lily.new(CGI.new, {})' </dev/null
./lily.rb:81:in `initialize': uninitialized constant Lily::DATA (NameError)
      from -e:1:in `new'
      from -e:1

となってしまうので

open(__FILE__) do |data|
  data.gets("__END__\n")
  eval data.read
end

としたほうがいいのかもしれない。というか、Rubyにも__DATA__が必要か。

[Vim] 行の先頭で#をタイプしたときのインデント

vimを使ってRubyスクリプトを編集しているときに気になるのが、#を先頭でタイプしたとたんに勝手にインデントすることだ。 元々コメント文字である#をインデントするスタイルを取らないというのもあるが、 一時的なコメントであることが多いので、 それを強調するためにも#は先頭に残しておきたい。

:help 'indent*'あたりから調べてみると、どうもindentkeysがあやしい。

"0#" if you type '#' as the first character in a line

つまり"0#"をindentkeysから取り除けばいいわけだ。~/.vimrcで

au FileType ruby setlocal indentkeys-=0#

としてみた。おぉ、ビンゴ。快適快適。


2004-05-17 (Mon)

[Ruby] Lilyのplugin

disp_*もplugin/へ追い出してしまえば、かなり好きなようにいじれるんじゃないだろうかと、ふと思った。


2004-05-18 (Tue)

[socks] CVSのProxyCommand拡張 -- より多くの人に現実逃避を

すばらしい。早速明日現実逃避しなきゃ。

[Cygwin] Cygwin MLをunsubscribe

ここ1年ぐらい全然読んでないので講読を止めた。 cygwin-announce MLだけで十分かな。情報が欲しければ アーカイブも公開されてるので、googleで検索できるし。


2004-05-19 (Wed)

[Mail] グーグル、本気か?!--Gmailの実験で上限を1テラバイトに

まあ、要するに制限なしってことだよなあ。 実際に1TBも使うやつはいないだろうし。

まずは肝である The Google File System(PDF)を読んでみるか。


2004-05-20 (Thu)

[Soft] cvs 1.12.8

やばいので更新した。 ProxyCommand拡張パッチは1行だけのずれだったので、全然問題なし。 socks5を試すの忘れてたけど、http proxyが問題なく動いてるからいいや。

あ、もう出てる。

[Mail] グーグルのGmail、「1テラバイトのストレージはバグが原因」

バグって表現もなんか面白い。でも、1TBは無理だとしても10GBぐらいならありうる話だなと思ってみたり。 それぐらいの差別化はしてくるんじゃないだろうか?

いまここにある2,3年分のメールが900MBほどあるので、1GBじゃすぐ足りなくなる予感。 wormやらspamやら取っておくなという話ではあるが。 あ、そういえば半年ぐらい前からそいつらは別の場所に移動させたんだ。 500Mほど増えた。まじで消せって。


<Prev(,) | Next(.)> | Recent(/)>> | RDF


WWW を検索 jarp.does.notwork.org を検索

わたなべひろふみ
Key fingerprint = C456 1350 085F A320 C6C8 8A36 0F15 9B2E EB12 3885
Valid HTML 4.01!