読者です 読者をやめる 読者になる 読者になる

アジャイルジャパン2015 長野サテライト / NSEG 62

4/25 に NSEG 第62回勉強会として アジャイルジャパン2015 の長野サテライトを開催しました。

場所は株式会社ケイケンシステムさんの会議室をお借りしました。いつもありがとうございます。

長野サテライトは去年は開催されなかったので、二年ぶりです。参加者は21人だったので、コミュニティが開催する長野でのイベントとしては盛況な方だったと思います。

前半はアジャイルジャパンの本会の基調講演二本の録画ビデオを流し、休憩を挟んで長野独自の講演を行いました。


基調講演の1本目は、Janet Gregory さんで、チームのコミュニケーションの話でした。講演は英語でしたが、平鍋さんが逐次通訳してくれたので英語はさっぱりな私でも理解出来ました。

www.slideshare.net

基調講演2本目は、横塚裕志さんで、どちらかというとアジャイルを知らない経営者に向けたような話でした。参加者は現場の技術者が多かったのでちょっと期待とずれていたかもしれません。


後半1本目は、岩佐和紀さんの「ICONIXプロセス × FileMaker アジャイルプロジェクト実践事例」でした。お客さんとのコミュニケーションやプログラマの教育に動画をうまく活用してるのが印象的でした。契約満了の3週前にほぼ開発完了とのこと。

Q&Aで「いつもこんなホワイトなんですか?」という質問に対して「ぼく炎上プロジェクトって経験したことないのでこれが普通です」という回答でした。すばらしい。

www.slideshare.net

後半2本目は、中島祐樹さんの「大手Sierで見た!ウォーターフォール×下請け構造の闇」でした。ホワイトの話のあとはブラックな話で、絶妙なバランスでしたがこの構成は偶然です。

https://prezi.com/hs_b7hqtnwht/sier/

みんなの心がいい感じにダークサイドに染まりそうになったところで、時間となりました。

はじめは1時間くらい時間があまりそうだったので、こっそりスライドを用意したりしてたのですが、出番がなくてよかったです。


終了後、ビストロクーというお店で懇親会を行いました。美味しゅうございました。

www.deli-koma.com


当日のツイートをまとめました。

togetter.com

また来年もアジャイルジャパンのサテライトができれば良いと思います。

MyNA(日本MySQLユーザ会)会 2015年4月

4/22(水) に MyNA会が開催されたので久々に参加しました。 というか、私の東京出張に合わせて開催されたみたいなので強制参加です。

ちょっと前に話題になった「🍣=🍺問題」についてしゃべってきました。

スライド:

www.slideshare.net

他の発表者のスライドも貼っときます。

www.slideshare.net

www.slideshare.net

ツイートまとめ:

togetter.com

そういや、今年は日本MySQLユーザ会設立15周年みたいです。

「理論から学ぶデータベース実践入門 ― リレーショナルモデルによる効率的なSQL」

理論から学ぶデータベース実践入門 ~リレーショナルモデルによる効率的なSQL (WEB+DB PRESS plus)

理論から学ぶデータベース実践入門 ~リレーショナルモデルによる効率的なSQL (WEB+DB PRESS plus)

ひょんなことから著者の奥野さんから頂きました。読み終えたのは3月頭なのに、2ヶ月も経ってからブログを書くという遅筆ぶりです。

この本はもともと2月末に発売予定だったらしいのですが、3/10に販売延期になりました。

『理論から学ぶデータベース実践入門』 発売延期及びテスト販売購入のお客様への書籍交換対応のお詫びとお知らせ:重要なお知らせ|技術評論社

テスト販売という限られた部数とはいえ、一旦販売したものを正誤表対応ではなく刷り直して交換対応というのは、電子書籍ならともかく、紙の書籍でやるとはすばらしいです。神対応と言ってもいいのではないでしょうか。紙だけに。

ちなみに、これは「∀」が「∨」になってしまっているという問題だったのですが、みつけたのは自分です。

前から思っていたのですが、実は自分の誤字脱字検出能力は結構高いような気がします。書籍販売前に誤字脱字等のチェックをして欲しいという人はご相談ください :-)

本書の構成は、前半はほとんどSQLが登場せず、リレーショナルモデルの理論が解説されています。後半ではその理論を元にSQLを解説しています。

また、リレーショナルモデルになくてSQLにあるもの(NULLやトランザクションなど)や、リレーショナルモデルに適合しない現実世界のデータの扱い(履歴、グラフ、ツリー等)についても解説されています。

第1章の中で、自分が気になったキーワード:

  • 「実は、SQLにおいてリレーションに相当するものは、テーブルです!」
  • 「リレーションにNULLを含めることができない」
  • 「実はリレーショナルモデルに更新という概念は存在しません」

自分はRDBを触り始めてから二十数年くらいで、高度情報処理データベース試験も受かってたりするんですけど、実はリレーショナルモデルについてはほとんど知りませんでした。この前まで「リレーションってテーブル間の結合のことなんじゃないの?」と思ってましたし。

「はじめに」の中に次のようにあります:

SQLを改めて勉強し直したいと考えている、またはリレーショナルモデルについてよく知らないといった中級者が主なターゲットです。

自分だ…。

第1章の中に次のようにあります:

リレーショナルモデルを知らなくても、何となく困らずに済みます。そのため「SQLは知っているけれど、リレーショナルモデルを知らない」という状況に陥りがちです。

自分だ…。

ということで、そういう人に本書はおすすめです。

あと、5/13 から長野で本書の読書会が開催されます。長野市近辺の方で興味ある人は参加してみるのもいいと思います。

nseg.doorkeeper.jp

Ruby + jemalloc でメモリ使用量が増える場合

Ruby でスレッドを1000個ほど作るとプロセスサイズが 4GB ほどになります。

% ruby -e 'system "ps -o vsz -p #$$"; 1000.times{Thread.new{sleep}}; system "ps -o vsz -p #$$"'
   VSZ
 46392
   VSZ
4151572

jemalloc 使うと 2.5GB くらいになります。jemalloc すばらしい。

% LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e 'system "ps -o vsz -p #$$"; 1000.times{Thread.new{sleep}}; system "ps -o vsz -p #$$"'
   VSZ
 55672
   VSZ
2509080

ところが jemalloc を使ったほうが時間がかかります。

% time ruby -e '1000.times{Thread.new{sleep}}'
ruby -e '1000.times{Thread.new{sleep}}'  0.10s user 0.06s system 115% cpu 0.132 total
% time LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e '1000.times{Thread.new{sleep}}'
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e   0.23s user 0.81s system 109% cpu 0.941 total

jemalloc を使わない場合は 0.13秒ですが、jemalloc を使うと 0.94秒かかってます。

プロセスサイズではなく OS の使用メモリを見てみます。

% ruby -e 'system "free"; 1000.times{Thread.new{sleep}}; system "free"'
             total       used       free     shared    buffers     cached
Mem:       8056184    7719868     336316      97356     587492    5373632
-/+ buffers/cache:    1758744    6297440
Swap:      4194300       2800    4191500
             total       used       free     shared    buffers     cached
Mem:       8056184    7766988     289196      97356     587492    5373632
-/+ buffers/cache:    1805864    6250320
Swap:      4194300       2800    4191500

jemalloc を使わない場合は、プロセスサイズは 4GB くらいでしたが、実際に使われているメモリは 47MB くらいです (前後 の used の差分)。

% LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e 'system "free"; 1000.times{Thread.new{sleep}}; system "free"'
             total       used       free     shared    buffers     cached
Mem:       8056184    7721732     334452      89052     587520    5365352
-/+ buffers/cache:    1768860    6287324
Swap:      4194300       2800    4191500
             total       used       free     shared    buffers     cached
Mem:       8056184    7780264     275920      87260     587520    5363568
-/+ buffers/cache:    1829176    6227008
Swap:      4194300       2800    4191500

jemalloc を使った場合は 60MB くらいで、逆に多く使用してしまっています。

さらに 10個ほど fork してみます。

% ruby -e 'system "free"; 1000.times{Thread.new{sleep}}; 10.times{fork{sleep}}; sleep 1; system "free"'
             total       used       free     shared    buffers     cached
Mem:       8056184    2053828    6002356      68744     372796     613836
-/+ buffers/cache:    1067196    6988988
Swap:      4194300          0    4194300
             total       used       free     shared    buffers     cached
Mem:       8056184    2246508    5809676      68744     372804     613856
-/+ buffers/cache:    1259848    6796336
Swap:      4194300          0    4194300

メモリ使用量の増加分は 192MB 程度です。

% LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.1 ruby -e 'system "free"; 1000.times{Thread.new{sleep}}; 10.times{fork{sleep}}; sleep 1; system "free"'
             total       used       free     shared    buffers     cached
Mem:       8056184    2084772    5971412      67856     372892     613568
-/+ buffers/cache:    1098312    6957872
Swap:      4194300          0    4194300
             total       used       free     shared    buffers     cached
Mem:       8056184    4041740    4014444      67856     372892     613568
-/+ buffers/cache:    3055280    5000904
Swap:      4194300          0    4194300

jemalloc 使うと 2GB 程メモリを食ってしまっています。

なんでこういうことになるのか理屈は全然わかってませんが、jemalloc 使うことでメモリに悪影響を及ぼすこともあるという例でした。

まあ fork なんて使うのが悪いのかもしれませんけどね。

Postfix mruby plugin

Postfix の mruby plugin を作ってみました。

誰得かわからないんですけど、Postfix のルックアップテーブルで mruby スクリプトで結果を返すことができます。

たとえば、次のようなスクリプトを作れば、

class Hoge
  def lookup(key)
    key.reverse
  end
end
Hoge.new

与えられたキーを反転して返すことができます。

% postmap -q hoge mruby:/path/to/hoge.rb
egoh

Postfix で独自のルックアップテーブルを作る

Postfix 3.0 から導入された動的データベースプラグイン機構を使用して、独自のルックアップテーブルを作ってみます。

Postfix を次のようにしてインストールしてあります。

重要なのは dynamicmaps=yes なので、これさえあれば他のパラメータ指定はなんでもいいです。

% make makefiles dynamicmaps=yes\
 command_directory=/usr/local/postfix/sbin\
 config_directory=/usr/local/postfix/etc\
 default_database_type=hash\
 daemon_directory=/usr/local/postfix/libexec\
 data_directory=/var/local/postfix/lib\
 html_directory=no\
 mail_spool_directory=/var/mail\
 mailq_path=/usr/local/postfix/bin/mailq\
 manpage_directory=/usr/local/man\
 meta_directory=/usr/local/postfix/etc\
 newaliases_path=/usr/local/postfix/bin/newaliases\
 queue_directory=/var/local/postfix/spool\
 readme_directory=no\
 sendmail_path=/usr/local/postfix/sbin/sendmail\
 shlib_directory=/usr/local/postfix/lib
% make
% sudo make install
% sudo cp -r include /usr/local/postfix/

ルックアップテーブルは与えられた文字列に対して一つの値を返します。

今回は与えられた文字列中の小文字を大文字に変換して返すようなルックアップテーブルのプラグインを作成してみます。

#include "sys_defs.h"
#include "dict.h"

/* name に対応する値を返す */
static const char *dict_upcase_lookup(DICT *dict, const char *name)
{
  static char buf[256];
  int i = 0;

  /* 256バイト以上の文字列に対する値は見つからなかったことにする */
  if (strlen(name) > 255) {
    return NULL;
  }
  while (*name) {
    buf[i++] = toupper(*name++);
  }
  buf[i] = '\0';
  return buf;
}

/* 終了 */
static void dict_upcase_close(DICT *dict)
{
  dict_free(dict);
}

/* 初期化 */
DICT *dict_upcase_open(const char *name, int open_flags, int dict_flags)
{
  DICT *dict;

  dict = dict_alloc("upcase", name, sizeof(DICT));
  dict->lookup = dict_upcase_lookup;
  dict->close = dict_upcase_close;
  dict->flags = dict_flags;
  return dict;
}

作成

% gcc -I /usr/local/postfix/include -fPIC -g -O -DLINUX3 -c dict_upcase.c
% gcc -shared -o postfix-upcase.so dict_upcase.o
# sudo cp postfix-upcase.so /usr/local/postfix/lib

設定 [/usr/local/postfix/etc/dynamicmaps.cf]

upcase  postfix-upcase.so       dict_upcase_open

作成したライブラリのファイル名と初期化関数を dynamicmaps.cf に登録します。 shlib_directory 以外の場所に置くこともできます。その場合はフルパスで記述します。

postmap コマンドで試してみます。

% /usr/local/postfix/sbin/postmap -q hoge upcase:dummy
HOGE

ちゃんと動いてるようです。

ルックアップテーブルは hash:/etc/aliases のように type:name の形式で指定します。 今回は name 部分は特に使用していませんが、初期化関数の第一引数として渡されるので、必要な場合はそれを使えばいいです。

Postfix 3.0 の主な変更

Postfix 3.0.0 がリリースされたのでアナウンス文を勝手に翻訳してみました。

原文: http://www.postfix.org/announcements/postfix-3.0.0.html


Postfix stable release 3.0.0 が利用可能になりました。このリリースにより Postfix 2.8 のサポートは終了します。

主な変更(順不同):

  • RFC 6530 と関連ドキュメントで定義された国際化ドメイン名とアドレスのローカルパートのための SMTPUTF8 サポート。 この実装は Arnt Gulbrandsen が寄稿したコードをベースとし、CNNIC によってスポンサーされました。 SMTPUTF8 サポートはまだ途中です; Postfix 3.1 開発サイクル中で完了する予定です。 要約と制限については SMTPUTF8_README を参照してください。

  • Postfix 動的リンクライブラリとデータベースプラグインのサポート。 この実装は LaMont Jones による Debian Linux のためのコードをベースとしています。 有効なオプションの詳細な説明は INSTALL を参照してください。

  • 新しい Postfix デフォルト設定の選択的な採用のための OPT-IN 安全策。 何もしなければ、基本的には古い Postfix デフォルト設定は残ったままにすべきです (そうでなければ、あなたの下流のメンテナに文句を言ってください)。 Postfix ログファイルメッセージの詳細な説明は COMPATIBILITY_README を参照してください。

  • 複数のルックアップテーブル操作のサポート。 pipemap:{map1,map2...} データベースタイプはルックアップテーブルのパイプラインを実行します。 これは、一つのルックアップテーブルからの結果が次のテーブルのクエリになります; unionmap:{map1,map2,...} データベースタイプは、同じクエリを複数のルックアップテーブルに送り、その結果を結合します。

  • 単純なものを簡単に行う仮想テーブルのサポート。 inline:{key1=value1,key2=value2,...} テーブルは、少ないアイテムのためだけに外部のファイルを生成する必要を回避します; randmap{value1,value2,...} テーブルは、指定された値からのランダムな選択を実行します。

  • DNS ルックアップ結果と、配送エージェントステータスコードとメッセージのテーブル駆動変換。 通常は、問題のある DNS 応答を修正したり、配送エラーのハンドリングを修正するために、PCRE テーブルを使用します。 smtp_dns_reply_filter, smtp_delivery_status_filter と、他の Postfix デーモン用の類似の名前のパラメータを参照してください。

  • 設定ファイルの文法の改善。 ${name?{iftrue}:{iffalse}} のような三項演算子のサポート、${{expr1}==${expr2}?{iftrue}:{iffalse}} のような比較演算子、Milter毎とポリシーサーバー毎のタイムアウトと他の設定、空白を含む master.cf パラメータ、空白を含む import/export_environment 設定、空白を含む "static" テーブルルックアップ結果。 access(5) と header/body_checks(5) テーブルの複数のルックアップ結果のサポートは Postfix 3.1 開発サイクルで完了する予定です。

  • セッション毎のコマンドプロファイル。各インバウンド SMTP セッションの最後に記録されます。 たとえば、パスワード推測ボットは、"disconnect from name[addr] ehlo=1 auth=0/1 commands=1/2" と記録され、 これは、クライアントが、成功したひとつの EHLO コマンドと失敗したひとつの AUTH コマンドを送信し、QUIT コマンドを送信せずにハングアップしたことを意味しています。 この情報は常に記録され、冗長なロギングやネットワークの監視なしにパズルを解くことを助けます。

Postfix のソースコードは http://www.postfix.org/ にリストされたミラーにあります。