aufsでCopy on writeな簡易実験環境を作る

プログラムをインストールするとどこに書き込まれるのか(インストールしてシステムを汚す前に)手っ取り早く知りたかったので、aufsでCOWな実験環境を作った。

$ sudo mkdir /tmp/sandbox{,-root,-home}
$ sudo mount -t aufs -o dirs=/tmp/sandbox-root:/=ro none /tmp/sandbox
$ sudo mount -t aufs -o dirs=/tmp/sandbox-home:/home=ro none /tmp/sandbox/home
$ sudo mount -t tmpfs none /tmp/sandbox/tmp
$ sudo mount --bind /dev /tmp/sandbox/dev
$ sudo mount --bind /proc /tmp/sandbox/proc
$ sudo chroot /tmp/sandbox su - ytoku

/をreadonlyで/tmp/sandboxにマウントして、差分は/tmp/sandbox-rootに書き込む。/homeも同様。/tmpについては複製する必要がなかったのでtmpfsをマウントした。/devと/procはシステムの状態に関わるので--bindを用いて/tmp/sandbox内にもマウントした。一通りマウントし終わった所でchrootによって/tmp/sandboxを/に見せかける。


マウントされているファイルシステムごとに、aufsなりbindなりでマウントし直さなければならないのだろうか。

Re: Python Spam and Eggs: 'pass' vs '...'

http://d.hatena.ne.jp/kyogoku42/20091213/1260710835 の追試を行った。

$ ./python /tmp/test0.py
'pass' for 10^6: 0.0767240524292
'...'  for 10^6: 0.0933971405029
'None' for 10^6: 0.0935978889465
$ ./python /tmp/test0.py
'pass' for 10^6: 0.0788168907166
'...'  for 10^6: 0.0958371162415
'None' for 10^6: 0.0938339233398

"..."のほうが"pass"よりも早いという結果は私の環境では出ていない。
また、実行順序に影響される可能性があるので、これを排除するために次のように書き換えてみた。

import time
import random

def test_pass():
    for i in range(10**6):
        pass
def test_ellipsis():
    for i in range(10**6):
        ...
def test_none():
    for i in range(10**6):
        None

def benchmark(f):
    t0 = time.time()
    f()
    t1 = time.time()
    return t1 - t0

sum_time_pass = 0
sum_time_ellipsis = 0
sum_time_none = 0
def f1():
    global sum_time_pass
    sum_time_pass += benchmark(test_pass)
def f2():
    global sum_time_ellipsis
    sum_time_ellipsis += benchmark(test_ellipsis)
def f3():
    global sum_time_none
    sum_time_none += benchmark(test_none)

for i in range(10**2):
    x = [f1, f2, f3]
    random.shuffle(x)
    for f in x:
        f()

print("'pass' for 10^8: {0}".format(sum_time_pass))
print("'...'  for 10^8: {0}".format(sum_time_ellipsis))
print("'None' for 10^8: {0}".format(sum_time_none))
$ ./python /tmp/test.py 
'pass' for 10^8: 4.6522705555
'...'  for 10^8: 6.02508592606
'None' for 10^8: 5.8259973526
$ ./python /tmp/test.py 
'pass' for 10^8: 4.44432783127
'...'  for 10^8: 5.71288895607
'None' for 10^8: 5.8271188736

やはり、"None"と"..."は大差なく、"pass"は他よりも速いようだ。テストした環境はPython 3.1.1(tar ballからビルド), Ubuntu 9.04 AMD64, Core2 Quad Q6600である。実行にあたってはCPUの動作クロックを2.39GHzに固定した。


なお、私は"pass"の代わりに"..."を使うことには反対したい。"..."は省略を意味するが、"pass"を用いる時は省略しているわけではなくそこに処理がないのである。これはサンプルコードなどを読んでいる時に、何かが省略されていると誤解を与える原因となるのではないだろうか。

LaTeXに関するメモ

7月中旬に書いて何故か公開していなかったLaTeXに関するメモ。

\documentstyleと\documentclassの違いは?

http://pub.cozmixng.org/~hiki/cis/?%5Cdocumentclass%A4%C8%5Cdocumentstyle
\documentclassの方が新しい書式。どうやら\documentstyleだと\usepackageが通らない。

ホームディレクトリに追加のスタイルファイルを置きたい。

http://hooktail.org/computer/index.php?%B4%C4%B6%AD%CA%D1%BF%F4TEXINPUTS
http://www.le.chiba-u.ac.jp/~aoyama/tex/texinputs.html
TEXINPUTS環境変数をセットする。最後に:をつけるとデフォルトの設定に追加されるらしい。また、ディレクトリのセパレータに//を書くとサブディレクトリも検索する。

ファイルを取り込むには

複数行にわたって枠をつけるには

ascmacパッケージのitembox環境やitembkbxパッケージのbreakitembox環境など。breakitemboxならページも跨げる。
http://emath.s40.xrea.com/ydir/Wiki/index.php?%CF%C8%B0%CF%A4%DF

Emacsのauto-fill-modeのようなことをVimでしたい

Emacsはauto-fill-modeにすると一行が指定した文字数に達した時点で適切に改行を加えてくれる。Vimで同じことをしたい場合にはどうすればいいのだろうか。以下調べて分かったこと。

  • このような機能はVimでは「自動折り返し」"automatic formatting"と呼ばれるらしい。ドキュメントはchange.txtのformattingあたりにある。
  • 有効にするためには、デフォルト設定だとtextwidth変数に折り返したい一行の長さを設定するだけでよい。
  • 挙動の設定はformatoptions変数で行うことができる。
  • 日本語は分かち書きしないためデフォルト設定ではうまく改行されないので、formatoptionsにmMを加えるとよい。mはマルチバイト文字の間で改行させる設定、Mは行を連結する時にマルチバイト文字の間に空白文字を入れない設定である。
  • 手動でformattingするにはgq{motion}なりビジュアルモードで選択してgqなり。

Scientific Linux 5.3でkvm上にrpmbuild環境を作成(2)

Scientific Linux 5.3でkvm上にrpmbuild環境を作成(1) / それぞれのサービスの機能 - ytokuがつまずいた跡の続き。

SSHでログインできるように設定してビルド用のユーザを作った。


二回目以降のコンパイルの効率化を期待してccacheを導入することにした。ccacheはdagにある物を使うことにする。dagから余計な物がインストールされないようにyum-prioritiesプラグインを設定しておく。
参考: yumのまとめ - 3.yumプラグインの説明とインストール手順 - 一分一秒真剣勝負!

# yum -y install yum-priorities

次にpriorityの設定……と思いきや/etc/yum.repos.d/にdag.repoがあった。まだ追加していなかったのだが、どうやらCentOSと違い最初から配置されているらしい。しかもご丁寧にpriorityまで設定済みだ。そのままdagをenable=1にして、ccacheをインストールした。
ccacheを使うため、ビルド用のユーザにPATHを設定……ログインしてみたらこれも必要なかった。/etc/profile.d/ccache.shでログイン時にPATHに/usr/lib/ccache/binを加えるようになっていた。実に気が利きすぎで涙が出てくる。


ビルド用のユーザでディレクトリを掘って

$ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

~/.rpmmacrosを以下の内容で作った。各ソースパッケージの中身が衝突しないよう、SOURCES下だけはパッケージ別のサブディレクトリを用意した。

%_topdir                /home/packaging/rpmbuild
%_builddir              %{_topdir}/BUILD
%_rpmdir                %{_topdir}/RPMS
%_sourcedir             %{_topdir}/SOURCES/%{name}
%_specdir               %{_topdir}/SPECS
%_srcrpmdir             %{_topdir}/SRPMS

これで一通り設定が終わったのでテストのビルドを行ったところ正常にrpmが生成された。


ところで、ターゲットアーキテクチャi686としたい。.rpmmacrosや.rpmrcでデフォルトのアーキテクチャを設定する方法がわからなかったので、~/.bashrcでのalias設定で妥協した。

alias rpmbuild='rpmbuild --target i686'

仮想マシン用のMACアドレス

以前、MACアドレスの付け方でつまづいたことがあるのでこの機会に書いておくことにする。
本来MACアドレスはネットワーク機器の製造時に一意になるように割り振られる物であるが、仮想マシンにはどのようにつけると良いのだろうか。MAC address - Wikipediaを見ると先頭から7bit目最初のオクテットの第2下位ビットにlocally administeredのフラグ*1というものがある。ここが1になっているMACアドレスネットワーク管理者は自由に使うことが出来るようだ。
また、8bit目最初のオクテットの最下位ビットにはunicast/multicastのフラグ*2が用意されている。でたらめなMACアドレスを設定してみた所、一部のMACアドレスが通信が出来ないという事態になったことがあったがこのためであった。
というわけで、7bit目最初のオクテットの第2下位ビットが1、8bit目最初のオクテットの最下位ビットが0になっているようなMACアドレスを、02:00:00:01:00:05など好きなようにつければよい。

*1:2009-09-28追記: IEEE Std 802-2001によればThe Universally or Locally administered (U/L) address bitと言うらしい

*2:2009-09-28追記: IEEE Std 802-2001によればThe Individual/Group (I/G) address bitと言うらしい