ストレージエンジンの実装、4.1、5.0、5.1で結構違うのね

どのバージョンで自作ストレージエンジンの練習をするか悩んでいるわけですが、kdiff3あたりで3つのソースを並べて見てみたりしてるんですが、5.1はプラガブルストレージエンジンになり明らかに一線を画してるのは予想通りではあるんですが、4.1と5.0でも結構違うんですね。

とりあえずGAの5.0かなーと思ったわけですが、Understanding MySQL Internalsは、4.1と5.1の実装例が載ってるけど5.0のは載ってなかったり。

うーん、、5.1かなー。



ちなみに前述の本、渋谷のBook1stには7000円強で売ってました。。
amazonで買えば5000円弱なのに。。

コンストラクタの初期化子

なんてこったい。C++でのハンドラもそこそこ書いてたのに全然理解できてない説浮上。
浮上というか確定。勉強しなおすかな。。

class HogeFuga
{
private:
string foo;

public:
HogeFuga(const char* q) : foo(q) {} // ←ウワサの初期化子
// HogeFuga(const char* q) { foo = q; }   // ←通常の書き方。今までこう書いてた。。
};

通常の書き方だと、

  1. HogeFugaクラスのインスタンス生成、メンバ変数が作られる.
  2. メンバ変数の初期化に伴い、string fooのデフォルトコンストラクタが呼ばれる.
  3. その後、HogeFuga コンストラクタが実行される
  4. オペレータオーバーロード関数(やコピーコンストラクタ)によって、望んだ初期化(qのコピー)が行われる.

ただ、よく見るとfooのデフォルトコンストラクタが呼ばれているのは無意味なわけです。
一方、初期化子の場合は、

  1. HogeFugaクラスのインスタンスを生成しようとする
  2. 初期化リスト中の定義(fooの初期化)を実施する
  3. HogeFugaクラスのコンストラクタ本体を実行する

となるので無駄が削減されています。

でもこれって…メンバ変数(コンストラクタを持つメンバ変数)の数だけズラズラ記述するんですかね??ちょっと見苦しくないです??うーむ。。。

ちなみに、アセンブラレベルでどれくらい違うのか見てみようと思い、objdumpしてみましたが、案の定サパーリ分かりませんでした^^;

unlikelyマクロについて

MySQLのソースやLinuxカーネルのソースを眺めるとしばしば出てくる、


if (unlikely(a == b)){
....
}
みたいな構文ですが、これの解説。

このunlikelyはマクロ関数で、引数として渡された条件がほとんどの場合に偽になることをコンパイラに教えるものです。コンパイラはこの指示に従い、条件が成り立たない場合に有利となるアセンブラコードを出力します。unlikelyの対はlikelyです。

具体的にどういうマクロかというと、MySQLのソースにおいては include/my_global.h にて下記のように宣言されています


#if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
#define __builtin_expect(x, expected_value) (x)
#endif

#define likely(x) __builtin_expect((x),1)
#define unlikely(x) __builtin_expect((x),0)

これにより、コンパイラがGNUCでなかったり、あるいは、GNUCのバージョンが2.96以下で、__builtin_expectに対応できていない場合は、通常のif文に置換されコンパイルが通ります。

Linuxカーネルでの宣言は詳細未確認ですが、たしか


#ifndef likely
...
#endif /* !likely */
で囲まれているので、MySQLでの宣言が優先されるはずです。(とはいえ内容はどっちでも殆ど変わりませんが)

MySQLソースコード解析ことはじめ

環境

FreeBSD-6.2

準備

MySQLコンパイル


$ cd mysql-5.0.45;
$ CC=gcc CXX=gcc CFLAGS=-g CXXFLAGS=-g ./configure \
--prefix=/home/$USER/mysql \
--localstatedir=/home/$USER/mysql/data \
--libexecdir=/home/$USER/mysql/bin \
--with-mysqld-user=$USER && make -j2;
-gをつけてデバッグ情報を残しておくところが重要です。

できあがるバイナリ

サーバー … sql/mysqld
クライアント … client/mysql

インストール

実行時に「ディレクトリがない」とか怒られるのがメンドクサイのでインストールしておきます。


$ make install;
$ /home/$USER/mysql/bin/mysql_install_db;

デバッグ

GUIデバッガdddインストール
  • ddd


$ sudo pkg_add -r ddd;

    • 依存性高いので色々コッテリ入っていきます。
    • Xクライアントアプリなので、環境変数DISPLAYの設定やXサーバーの用意は別途必要です。
出来上がったバイナリをdddに食わせる


$ ddd sql/mysqld

dddの使い方

起動後、とりあえずまずはmain関数にbreakpointを貼りましょう。その後、Run。でステップ実行とか変数をダブルクリックしてグラフィカル表示などしているうちに感覚がつかめると思います。

  • Step

カレント行を実行する。カレント行が関数であれば関数の中に入ります。

  • Next

カレント行を実行する。カレント行が関数であれば関数の中に入らずに関数全体を実行します。

  • Stepi

マシン語レベルでのstep

  • Nexti

マシン語レベルでのnext

  • Until

for文を抜けます

  • Finish

現在の関数を実行して呼び出し元に戻ります

  • Cont

コンティニュー。次のブレークポイントまで一気にすすみます。

  • Kill

プロセスをkillします

  • Up

自分を呼んだ関数を表示します。表示するだけで、カレント行は変わりません。

  • Down

Upと逆の動作

  • Undo

Undo Nextします

Redo Next。Undoを実行しないと有効になりません。

  • Edit

ファイルを編集します。

  • Make

makeを実行します。

GoogleReaderが少し良くなった(でももう一歩)

http://d.hatena.ne.jp/i_youhei/20070830
先日こんな日記を書いたんですが、Google Readerがちょっと良くなりました。
きっとこのブログを読んで改善してくれたんだと思います!(多分違う)
http://googlereader.blogspot.com/
具体的には、ダメ出しをしていた下記の3つに対し、


1. 検索機能がない
 →検索機能が付きました。検索結果も期待通りの動作です。


2. 100件を超えると「100+」となり正確な数がわからない
 →1000件までは正確に出るようになりました。
 →1000を越すと「1000+」の表示。。。もう一歩!1000なんて2,3日で溜まるじゃないですか。。


3. 範囲指定で「既読」に出来ない。
 →今回も改善されず。。Google関係者の方、ぜひこのブログを見てたら開発チームに提案してください!よろしくお願いします!

Google Readerのイケてないところ

1. 検索機能がない
おたくは何の会社でしたっけ?と聞きたくなります


2. 100件を超えると「100+」となり正確な数がわからない
読んでも読んでも100を下回らないと凹むんです。


3. 範囲指定で「既読」に出来ない。
「All Items」でざーっと読んでタイトルを見ていってて、一区切りつけたいなと思った時に、読んだところまでを既読にする手段がない


そんなところでしょうか。
livedoor Readerよりは気に入ってます ^^