...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

Policyと実行時間

今回

Policyを使ったコードに比べて,boost::function + boost::bind がどれほど遅いのかを調べてみた.
VS2008のmsvcでReleaseビルド,最大限の最適化あり.
そしたら,Policyを使ったコードは最適化がうまく働いて実際には何も処理されなかったのか,実行時間がゼロになってしまった・・・.
なんてこったい.


一応,実験したコードを続きに張っておく.

追記

バカでかい数値をintで使うとか色々間違えていたので直した.
それと,何もない処理に展開されてしまうことがないように,mouse_event_loggerクラスのメソッドを副作用のあるものに変更した.
それでもやはりPolicyを使ったコードはゼロ秒(正確には1秒未満か?)で終わってしまった.

#include "stdafx.h"

#include <ctime>
#include <iostream>
using namespace std;

#include <boost/function.hpp>
#include <boost/bind.hpp>
using namespace boost;

// 本来はどこかで定義されているものたち
typedef int HWND;
void MouseCapture(HWND){}
void ReleaseCapture(){}
HWND GetHWnd(){return 0;}

class mouse_event_logger {
  long count_;
public:
  mouse_event_logger() : count_(0) {}
  void on_left_button_down(){++count_;}
  void on_left_button_up(){++count_;}
  void on_right_button_down(){++count_;}
  void on_right_button_up(){++count_;}
  //...
  long count(){return count_;}
};

#if 0

void f(function<void()> mouse_capture, function<void()> logger_method, bool enabled)
{
  mouse_capture();
  if (enabled)
    logger_method();
};

class context {
  bool enabled;
  mouse_event_logger logger;
public:
  context() : enabled(false) {}
  void set_enabled(bool b) {enabled = b;}

  void on_left_button_down(HWND hwnd) {
    f(bind(::MouseCapture, hwnd), bind(&mouse_event_logger::on_left_button_down, &logger), enabled);
  }
  void on_left_button_up() {
    f(::ReleaseCapture, bind(&mouse_event_logger::on_left_button_up, &logger), enabled);
  }
  void on_right_button_down(HWND hwnd) {
    f(bind(::MouseCapture, hwnd), bind(&mouse_event_logger::on_right_button_down, &logger), enabled);
  }
  void on_right_button_up() {
    f(::ReleaseCapture, bind(&mouse_event_logger::on_right_button_up, &logger), enabled);
  }
};

#else

template <typename MouseEventPolicy>
struct mouse_button_event_holder {
  void operator()(HWND hwnd, mouse_event_logger* logger, bool enabled) {
    MouseEventPolicy::mouse_capture(hwnd);
    if (enabled)
      MouseEventPolicy::logger_method(logger);
  };
};

struct on_left_button_down_policy {
  static void mouse_capture(HWND hwnd) {
    ::MouseCapture(hwnd);
  }
  static void logger_method(mouse_event_logger* logger) {
    logger->on_left_button_down();
  }
};
struct on_left_button_up_policy {
  static void mouse_capture(HWND hwnd) {
	  ::ReleaseCapture();
  }
  static void logger_method(mouse_event_logger* logger) {
    logger->on_left_button_up();
  }
};
struct on_right_button_down_policy {
  static void mouse_capture(HWND hwnd) {
    ::MouseCapture(hwnd);
  }
  static void logger_method(mouse_event_logger* logger) {
    logger->on_right_button_down();
  }
};
struct on_right_button_up_policy {
  static void mouse_capture(HWND ) {
    ::ReleaseCapture();
  }
  static void logger_method(mouse_event_logger* logger) {
    logger->on_right_button_up();
  }
};

class context {
  bool enabled;
  mouse_event_logger logger;
public:
  context() : enabled(false) {}
  ~context() { cout << logger.count() << endl; }
  void set_enabled(bool b) {enabled = b;}

  void on_left_button_down(HWND hwnd) {
    mouse_button_event_holder<on_left_button_down_policy>()(hwnd, &logger, enabled);
  }
  void on_left_button_up() {
    mouse_button_event_holder<on_left_button_up_policy>()(0, &logger, enabled);
  }
  void on_right_button_down(HWND hwnd) {
    mouse_button_event_holder<on_right_button_down_policy>()(hwnd, &logger, enabled);
  }
  void on_right_button_up() {
    mouse_button_event_holder<on_right_button_up_policy>()(0, &logger, enabled);
  }
};

#endif

int main()
{
	time_t t1, t2;
	time(&t1);

	context c;
	c.set_enabled(true);
	for (long i=0; i<20000000; ++i)
	{
		c.on_left_button_down(GetHWnd());
		c.on_left_button_up();
		c.on_right_button_down(GetHWnd());
		c.on_right_button_up();
	}

	time(&t2);
	cout << t2-t1 << endl;

	return 0;
}