お手軽並列処理1. お手軽並列処理
斉藤 博文 (hi_saito@yk.rim.or.jp)
@hi_saito
4. 自宅の構成
Web サーバー
モデム
DNS サーバー
iMac Fedora
1.5M ADSL Proxy サーバー
ルーター
40M
iPhone iPhone iPhone
WiFi ルーター Wii DS
Win Win Fedora
5. 今日のお題
hosts ファイルの自動更新
●
ローカルの hosts ファイルにブラックリストの書
かれた hosts を入手してマージする。
●
ちなみに、DNS キャッシュの dnsmasq が
hosts を見てくれるので楽です。
これをどう書くか?
6. やりたいことを書こう!
●
今の hosts をバックアップ
●
ブラックリストを入手する
●
ブラックリストを hosts 形式にする
●
新しい hosts を作る
●
新しい host を上書きする
●
以前の hosts との差分を取る
●
古いバックアップを削除する
書くだけなら、簡単ですね。
7. 順序を決めよう!
今の hosts をバックアップ
ブラックリストを入手する
ブラックリストを hosts 形式にする
新しい hosts を作る
新しい host を上書きする
以前の hosts との差分を取る
古いバックアップを削除する
8. 並列処理できるかな?
今の hosts をバックアップ
ブラックリストを入手する
ブラックリストを hosts 形式にする
新しい hosts を作る
新しい host を上書きする
以前の hosts との差分を取る
古いバックアップを削除する
9. グループ分けしよう!
●
今の hosts をバックアップ
準備 ●
ブラックリストを入手する
●
ブラックリストを hosts 形式にする
●
新しい hosts を作る
実行 ●
新しい host を上書きする
確認 ●
以前の hosts との差分を取る
後処理 ●
古いバックアップを削除する
大体この 4 つに分割されます。
12. 変数の設定 【ワンポイント】
GNU make だと := で展開後
# Settings - 設定 の変数が代入できて便利だよ。
SHELL = /bin/bash
MAKEFLAGS = -j 4 -l 4 -s
TMP = /tmp
HOSTS = /etc/hosts
HOSTS_LAN = /etc/hosts.lan
BLACKLIST_URL = http://someonewhocares.org/hosts/
GENERATION = 3
TODAY := $(shell date +%Y%m%d%H%M%S)
-j が同時処理数、-l が負荷の設定
13. Makefile の骨子
all: Prepare
Execute
Check
Clean
# Prepare - 準備
Prepare: backup_hosts
get_blacklist
format_blacklist_to_hosts
make_new_hosts
# Execute - 実行
Execute: overwrite_hosts
# Check - チェック
Check: diff_hosts
# Clean - 後処理
Clean: remove_older_hosts
14. backup_hosts:
backup_hosts:
cp ${HOSTS} ${HOSTS}.${TODAY}
get_blacklist:
get_blacklist:
wget -q -o /dev/null ${BLACKLIST_URL}
-O ${TMP}/get_blacklist
15. format_blacklist_to_hosts:
format_blacklist_to_hosts: get_blacklist
awk '$$0 ~ /^127/ {print $$0}' ${TMP}/get_blacklist
> ${TMP}/format_blacklist_to_hosts
【ワンポイント】
make_new_hosts:
Makefile で $ は $$ と記載
する。
make_new_hosts: format_blacklist_to_hosts
cat ${HOSTS_LAN} ${TMP}/format_blacklist_to_hosts
> ${TMP}/make_new_hosts
16. overwrite_hosts:
overwrite_hosts: make_new_hosts
rm ${HOSTS}
mv ${TMP}/make_new_hosts ${HOSTS}
【ワンポイント】
diff_hosts:
「実行」は可能な限り一瞬で完
了する方法を使おう。
diff_hosts: make_new_hosts
diff -u ${HOSTS}.${TODAY} ${TMP}/make_new_hosts
17. remove_older_hosts:
remove_older_hosts: backup_hosts
ls -1 ${HOSTS}.* |
egrep '${HOSTS}.[0-9]{14}$$' |
sort -r | 【ワンポイント】
awk 'NR > ${GENERATION}' | grep よりも egrep を使うと
xargs rm -f 便利だよ。リテラルなら
fgrep が便利だよ。
うまく分割して、小さくまとめる。
18. 本当に高速化されているの?
全 7 項目に sleep 1 を割り当てて実行してみる。
$ time make -f Makefile
0.02s user 0.03s system 0% cpu 7.061 total
$ time make -j 4 -f Makefile
0.02s user 0.03s system 1% cpu 4.040 total
ちゃんと並列処理されている。
19. もうひとつの並列処理コマンド
xargs も並列処理できるよ。
$ time seq 5 | xargs -n 1 sleep
0.00s user 0.00s system 0% cpu 15.111 total
$ time seq 5 | xargs -P 5 -n 1 sleep
0.00s user 0.01s system 0% cpu 5.007 total
ちゃんと並列処理されている。