天泣記

2012-02-01 (Wed)

#1

Ruby の tarball の中身のサイズの変化を可視化してみる。

ruby-tarsize.png

ruby-tarsize.R:

library(ggplot2)
d <- read.csv("2012-02/ruby-tarsize.csv")
print(qplot(version, size, data=d, fill=path, geom="bar") + opts(axis.text.x=theme_text(angle=30)))

うぅむ。ggplot2 でお気楽に作ったグラフはあまり見やすくないな。

まず、デフォルトではバージョン名が重なってしまう。まぁ、これは 30度傾けて対処したが。

また、積み上げ棒グラフと凡例の順番が反対だし、隣り合った色が似すぎていて凡例との対応を取るのが不可能に近い。

ext 以下はさらに分割して表示したいのだが、そうやって種類を増やしてもこのままでは区別不可能だろう。

なお、データは以下のような感じ。

% head 2012-02/ruby-tarsize.csv 
version,path,size
1.4.0,(root),1822254
1.4.0,beos,0
1.4.0,cygwin,382
1.4.0,ext,540248
1.4.0,lib,185938
1.4.0,misc,41707
1.4.0,missing,99246
1.4.0,sample,89417
1.4.0,win32,77416

このデータは以下のようにして作った。

% cat Makefile
z2.csv: z1.csv
        tb gsub -f path '\A[^/]+/' '' $^ | \
          tb gsub -f path '(\A|/)[^/]*\z' '' | \
          tb gsub -f path '\A([^/]+).*' '\1' | \
          tb gsub -f path '\A\z' '(root)' | \
          tb group version,path -a 'sum(size),size' -o $@

z1.csv: z0.csv
        tb cut version,size,path $^ -o $@

z0.csv: tarballs
        rm -f $@.tmp0; \
        touch $@.tmp0; \
        for f in tarballs/*.tar.gz tarballs/*.tar.bz2; do \
          tb tar-tvf $$f -l -o $@.tmp; \
          tb newfield version "\"$$f\""'.sub(/tarballs\/ruby-/, "").sub(/\.tar.*/, "")' $@.tmp -o $@.tmp; \
          tb cat $@.tmp0 $@.tmp -o $@.tmp0; \
        done; \
        rm $@.tmp; \
        mv $@.tmp0 $@

tarballs ディレクトリ以下に ruby の tarball を置いておけば動く。tb tar-tvf により、展開せずにサイズを抽出している。

2012-02-21 (Tue)

#1

最近、Ruby の dbm 拡張で、ヘッダとライブラリのミスマッチの検出をがんばってみた。

場合分けが多くて、頭の中で把握するのは無理だったので、整理してみた。

library:
  libc          libc の中にあるものを使う
  ndbm          4.3BSD ndbm を libndbm として外部に出したもの
  db1           Berkeley DB 1
  db2           Berkeley DB 2以降
  gdbm17        GDBM 1.8.0以前 : libgdbm に ndbm 関数が同梱      : -lgdbm でリンク
  gdbm18        GDBM 1.8.1以降 1.8.3以前 : libgdbm_compat が分離 : -lgdbm でリンク
  gdbm19        GDBM 1.9以降 : dbm_clearerr が提供される         : -lgdbm でリンク
  gdbm18c       GDBM 1.8.1以降 1.8.3以前 : libgdbm_compat が分離 : -lgdbm_compat -lgdbm でリンク
  gdbm19c       GDBM 1.9以降 : dbm_clearerr が提供される         : -lgdbm_compat -lgdbm でリンク

libc-type:
  ndbm-libc     libc に 4.3BSD ndbm が入っている (4.3BSD および、Solaris などの商用 Unix)
  db1-libc      libc に Berkeley DB 1 が入っている (NetBSD など、4.4BSD から派生したもの)
  glibc         libc に ndbm 関数が入っていない (glibc 2.2以降、uClibc など)

header:
  ndbmh         4.3BSD ndbm : _DBM_IOERR を定義する
  db1h          Berkeley DB 1 : _DB_H_ を定義する
  db2h          Berkeley DB 2以降 : _DB_H_ を定義する
  gdbm18h       GDBM 1.8.3以前 : dbm_clearerr が空 (1.8.0 と 1.8.1 の間でヘッダは変化なし)
  gdbm19h       GDBM 1.9以降 : _GDBM_H_ を定義する

library libc-type       ndbmh   db1h    db2h    gdbm18h gdbm19h
libc    ndbm-libc       O       B       AB      D       DB
libc    db1-libc                O       AB      D       D
libc    glibc           A       AB      AB      AD      ABD
ndbm    ndbm-libc       O       B       AB      D       BD
ndbm    db1-libc        O               AB      D       D
ndbm    glibc           O       B       AB      D       BD
db1     ndbm-libc       E       O       AB      DE      DE
db1     db1-libc        E       O       AB      DE      DE
db1     glibc           E       O       AB      DE      DE
db2     ndbm-libc       E       B       O       DE      BDE
db2     db1-libc        E               O       DE      DE
db2     glibc           AE      AB      O       ADE     ABDE
gdbm17  ndbm-libc       E       BE      ABE     O       BC
gdbm17  db1-libc        E       E       ABE     O       C
gdbm17  glibc           E       BE      ABE     O       BC
gdbm18  ndbm-libc       E       BE      ABE             BC
gdbm18  db1-libc        E       E       ABE             C
gdbm18  glibc           AE      ABE     ABE     A       ABC
gdbm19  ndbm-libc       E       BE      ABE             BC
gdbm19  db1-libc        E       E       ABE             C
gdbm19  glibc           AE      ABE     ABE     A       ABC
gdbm18c ndbm-libc       E       BE      ABE     O       B
gdbm18c db1-libc        E       E       ABE     O
gdbm18c glibc           E       BE      ABE     O       B
gdbm19c ndbm-libc       E       E       ABE             O
gdbm19c db1-libc        E       E       ABE             O
gdbm19c glibc           E       E       ABE             O

O. 正しいヘッダとライブラリの組み合わせ

A. dbm_open がリンクできる。
  4.3BSD ndbm: DBM *dbm_open();
  Berkeley DB 1.85: DBM *dbm_open(const char *, int, int);
  Berkeley DB 2.7.7: #define dbm_open(a, b, c) __db_ndbm_open(a, b, c)
                     DBM *__db_ndbm_open(const char *, int, int);
  GDBM 1.7: DBM *dbm_open ()
  GDBM 1.8.3: DBM *dbm_open ();
  GDBM 1.9: DBM *dbm_open (char *file, int flags, int mode);
  db2h は db2 以外のすべての組み合わせで失敗する (db2 以外は __db_ndbm_open を提供していないから)
  また、gdbm1[89] は libgdbm だけで、そこには dbm_open はないので、glibc の場合は失敗する
  もちろん、dbm_open の実体が存在しない libc+glibc の場合も失敗する
  db2+glibc も、dbm_open の実体が存在しないので、db2h 以外は失敗する

B. dbm_clearerr がリンクできる。
  4.3BSD ndbm: #define dbm_clearerr(db) ((db)->dbm_flags &= ~_DBM_IOERR)
  Berkeley DB 1.85: 宣言なし。ライブラリ内に int dbm_clearerr(DBM *db) が存在。
  FreeBSD 8.2: int dbm_clearerr(DBM *);
  Berkeley DB 2.7.7: #define dbm_clearerr(a) __db_ndbm_clearerr(a)
                     int __db_ndbm_clearerr(DBM *);
  GDBM 1.7: #define dbm_clearerr(dbf)
  GDBM 1.8.3: #define dbm_clearerr(dbf)
  GDBM 1.9: extern void dbm_clearerr (DBM *dbf); 実体は libndbm_compat に入っている。
  ndbm, db2, gdbm1[789], gdbm18c はライブラリ内に dbm_clearerr がないので、
  関数として宣言するヘッダとの組み合わせで失敗する。

C. _GDBM_H_ が定義されているなら、gdbm_compat なので、gdbm は禁止
  GDBM 1.8.0 までは libgdbm に ndbm 関数が同梱されている
  GDBM 1.8.1 以降は libgdbm_compat に分かれている
  GDBM 1.9 以降は ndbm.h に #include <gdbm.h> とされていて、_GDBM_H_ が定義される

D. GDBM のヘッダなら、gdbm_version があるはず
  gdbm_version は少なくとも GDBM 1.5 からあるので、GDBM のヘッダを使うときはかならずある。
  ただし、libgdbm_compat でなく、libgdbm に入っている点は注意。

E. ヘッダの種類とリンクするライブラリがマッチしない
  ndbmh * {db[12], gdbm1[789], gdbm[89]c}
  db[12]h * {gdbm1[789], gdbm[89]c}
  gdbm1[89]h * db[12]

うぅむ。まだ表に穴があるな。埋められるのかどうか良く分からないが。

まぁ、最終的に動かしてしまえば、生成したデータベースの形式を調べて確認できるので、間違いを見逃すことはない、と思われるけれど。

2012-02-25 (Sat)

#1

「無限なめこ」なるものを知って、ふと

#!/usr/bin/ruby

xmin = 610
ymin = 140

xmax = 760
ymax = 300

10.times {
  ymin.step(ymax, (ymax-ymin)/5.0) {|y|
    xmin.step(xmax, (xmax-xmin)/5.0) {|x|
      system("xwit -warp #{x} #{y}")
      sleep 0.1
    }
  }
}

というものを書いてみた。


[latest]


田中哲