« 2008年05月 | メイン | 2008年07月 »

2008年06月27日

C++ で自動型変換

 C++ の拡張ライブラリである boost には、lexical_cast というライブラリがあって、iostream への入出力ができる型ならなんでも文字列化 (その逆も) できるので、とても便利です。でも、lexical_cast は、int → long のような変換の場合にも iostream を使った変換をしてしまうので、汎用のリフレクションコードを書こうとすると、そのままでは使いにくいです (オーバーヘッドが大きすぎる)。というわけで、変換前後の型に応じて、static_cast と lexical_cast を自動的に切り替えるようなキャスト関数を作ってみました。こんな感じで使います。

// calls lexical_cast<int>(123)
int i = intelligent_cast<int>("123");

// calls static_cast<long>(123)
long l = intelligent_cast<int>(123);

// calls std::string(const char*)
std::string s = intelligent_cast<std::string>("abc");

 これで、不用意に数値型間や std::string → std::string のような変換 (コピー) が必要になる場合でも、速度の低下を心配する必要がなくなりました。

 ライブラリのコードは以下のような感じ。boost におんぶにだっこなので簡単です (std::string については、実用上の観点から専用コードを追加しています) 。最新版は CodeRepos (/lang/cplusplus/reflection) においてあるので、バグ等ありましたら、指摘もしくは修正いただければ幸いです。

続きを読む "C++ で自動型変換"

投稿者 kazuho : 2008年06月27日 17:22 | トラックバック (0) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

2008年06月25日

なんとなくリフレクション in C++

 C++ はとてもいい言語なのですが、リフレクションがありません。昨夜、1年ぶりくらいに C++ でリフレクションしたい熱に感染したのですが、ちょっとググった範囲では良いものが見つからなかったので、作ってみました (単に作りたかっただけという説も)。こんな感じで使います。

#include "reflection.hpp"

struct Foo {
  int i;
  std::string s;
};

// リフレクション情報を定義
namespace reflection {
  template <> struct def<Foo> : public def_base<Foo> {
    def() {
      REFLECTION(i);
      REFLECTION(s);
    }
  };
};

  // リフレクションを通してデータを読み込み
  // 変数が見つからない場合は reflection::name_not_found_error が、
  // キャストできない場合は std::bad_cast 例外が送出されます
  int t = reflection::get<int>(f, "i");
  cout << "i=" << t << endl;
  
  // リフレクションを通してデータを書き込み
  reflection::set(f, "s", string("hello world"));
  
  // リフレクション情報を iterate して表示
  for (reflection::def<Foo>::const_iterator i =
         reflection::def<Foo>::map.begin();
       i != reflection::def<Foo>::map.end();
       ++i)
    cout << i->first << " = "
      << i->second->get<std::string>(f) <<endl;

 このリフレクションライブラリの特徴は、以下のようなものになります。

続きを読む "なんとなくリフレクション in C++"

投稿者 kazuho : 2008年06月25日 08:34 | トラックバック (0) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

2008年06月20日

MySQL の ORDER BY を高速化

 Pathtraq の拡張にむけて、いろいろ技術的な可能性を調査していると、MySQL の ORDER BY に負荷がかかっていることが分かりました。他にもボトルネックはあるのですが、ここは比較的最適化しやすそうだったので、試しに書いてみました。

mysql51-sort-opt.patch

 やっていることは、ソートルーチンのベタな最適化です。ORDER BY 句によって悪名高き filesort が実行される場合に、最大30%〜50%ほど高速に動作するようになりました。ただ、自分が書く類いのクエリだと、本質的には top n sort を実装すべきなので、どうしたものかと思っています。現状、x86-64 向けに書いているので、RISC だと確実に落ちると思いますが、at your own risk で試したい方はどうぞ。

投稿者 kazuho : 2008年06月20日 15:46 | コメント (1) | トラックバック (0) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

2008年06月12日

MySQL (InnoDB) に直接アクセスしてタイムライン処理を高速化する話

 フレンド・タイムライン処理の原理と実践 の続きです。

 先のエントリでは、プルモデルの速度が当初予測していたよりも遅かった (というより SQL レイヤでのオーバーヘッドが大きそうだった) ので、MySQL Internals メーリングリストで質問したりしながら、C++ で直接 InnoDB にアクセスするようなコードを書いてみました。

タイムライン構築速度
タイムライン/秒
SQL56.7
ストアドプロシージャ136
C++ での直接アクセス1,7102,000 (追記参照)

 そしたら、10倍以上高速に! ベンチマークを perl ベースのものから mysqlslap に変えたのですが、プッシュモデルの 2/3 の速度が出ています。これなら、データサイズが約 1/10 になることを考えると、メモリの代わりに CPU に投資するほうが良い、という判断も非常に現実味を帯びてきます。また、最近のクアッドコアな CPU を使えば 10,000 タイムライン/秒クラスも夢じゃないでしょうから、memcached による支援の必要もないのかもしれません。

続きを読む "MySQL (InnoDB) に直接アクセスしてタイムライン処理を高速化する話"

投稿者 kazuho : 2008年06月12日 17:12 | コメント (1) | トラックバック (0) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

2008年06月09日

フレンド・タイムライン処理の原理と実践

MySQL (InnoDB) に直接アクセスしてタイムライン処理を高速化する話に続きます。

 Twitter が注目されるようになって久しい今日この頃ですが、友人の投稿を時系列に並べて表示する、というのは、Twitter に限らず Mixi の「マイミクシィ最新日記」やはてなブックマークの「お気に入り」等、ソーシャルなウェブサービスにおいては一般的な手法です。ですが、この処理 (以下「フレンド・タイムライン」と呼ぶ) は、一見簡単そうに見えて、実装には様々な困難が伴います。本記事では、「フレンド・タイムライン」を実現する、プッシュ型とプル型の二種類の手法について、その原理的な特徴と問題、および実践的なテクニックについて説明したいと思います。

 なお、以下では基本的に SQL を用いて話を進めて行きますが、原理的な部分は、どのようなストレージを使おうと、あるいはスケールアウトしようがしまいが、変わらないと思います。

1. プッシュ型

続きを読む "フレンド・タイムライン処理の原理と実践"

投稿者 kazuho : 2008年06月09日 14:06 | コメント (8) | トラックバック (6) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク

MySQL のクエリ最適化における、もうひとつの検証方法

 EXPLAIN を使用して MySQL の SQL を最適化するというのは、良く知られた手法だと思います。しかし、EXPLAIN の返す結果が、かならずしもアテになるわけではありません。たとえば、以下のような EXPLAIN を見て、このクエリが最適かどうか、判断ができるでしょうか。私には分かりません。

続きを読む "MySQL のクエリ最適化における、もうひとつの検証方法"

投稿者 kazuho : 2008年06月09日 11:38 | トラックバック (0) このエントリーを含むはてなブックマーク このエントリーを含むはてなブックマーク