Ruby の tarball の中身のサイズの変化を可視化してみる。
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 により、展開せずにサイズを抽出している。
最近、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]
うぅむ。まだ表に穴があるな。埋められるのかどうか良く分からないが。
まぁ、最終的に動かしてしまえば、生成したデータベースの形式を調べて確認できるので、間違いを見逃すことはない、と思われるけれど。
「無限なめこ」なるものを知って、ふと
#!/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]