2010年4月27日火曜日

etc - messagepack

3D独自フォーマット(気軽に出力して気軽にテストするためのフォーマット)として、
protocolbuffersを使っていて、大体満足していたのですが、
大容量のポリゴンにも耐えうる、テスト用に留まらない、メインで使えるシリアライザ/デシリアライザを探して、前から気になってたmessagepackをテスト中です。


MessagePack公式はこちら


導入は、結構自力で何とかなったのですが、後でまとめた記事を発見しましたorz
C++ですが、こちら。最初に発見していれば30分は短縮できた。。
糸且之入Eヨ言己 - MessagePackとProtocol Buffersを試してみた


さて、突貫で作った速度計測用コード。
個人的に最大のポイントは、なんと元々のstd::vector<um_vector4>(独自型)にデシリアライズ後変換できる!ということです。
protocolbuffersでは、メンバ変数へのアクセスが全てメソッド経由のクラスに強制的にされてしまい、デシリアライズ後に、自前のバッファにコピーしないと遅くて使い物にならないです。
一瞬で分かったprotocolbuffersのDSLより難しいのは間違いないですが、こっちのほうが速度も断然速そうです。


intを400万個、floatを800万個くらいシリアライズしてみました




// てきとーなベクタ
typedef union um_vector4
{
struct { float r, g, b, a; };
struct { float x, y, z, w; };
struct { int ix, iy, iz, iw; };
float rgba[4];
float xyzw[4];

um_vector4() {}
um_vector4(const float _x, const float _y, const float _z, const float _w)
{
x = _x; y = _y, z = _z; w = _w;
}

// ↓これでMessagePackでシリアライズ可能になるらしい
MSGPACK_DEFINE(x, y, z, w);
} um_vector4;

// てきとーなポリゴンクラス
class TestMessage {
private:
std::vector<um_vector4> f; //面です
std::vector<um_vector4> v; //頂点です
std::vector<um_vector4> n; //法線です
public:
// get const
const std::vector<um_vector4>& face_buffer() const { return f; };
const std::vector<um_vector4>& vertex_buffer() const { return v; };
const std::vector<um_vector4>& normal_buffer() const { return n; };
// get mutable
std::vector<um_vector4>& mutable_face_buffer() { return f; };
std::vector<um_vector4>& mutable_vertex_buffer() { return v; };
std::vector<um_vector4>& mutable_normal_buffer() { return n; };

// ↓これでMessagePackでシリアライズ可能になるらしい
MSGPACK_DEFINE(f, v, n);
};

int main(void)
{
TestMessage test;
// てきとーに100万ずつくらいぶち込んでおく
float t = ::timeGetTime();
std::vector<um_vector4>& face_buffer = test.mutable_face_buffer();
std::vector<um_vector4>& vertex_buffer = test.mutable_vertex_buffer();
std::vector<um_vector4>& normal_buffer = test.mutable_normal_buffer();
for (int i = 0; i < 1000000; ++i) {
face_buffer.push_back(um_vector4(xor128(), xor128(), xor128(), xor128()));
vertex_buffer.push_back(um_vector4(dxor128(), dxor128(), dxor128(), dxor128()));
normal_buffer.push_back(um_vector4(dxor128(), dxor128(), dxor128(), dxor128()));
}
dprintf(_T("generate: %f ms\n"), ::timeGetTime() - t);

// 5個くらい出力
for (int i = 0; i < 5; ++i) {
dprintf(_T("%d: %d, %d, %d, %d\n"), i, face_buffer[i].ix, face_buffer[i].iy, face_buffer[i].iz, face_buffer[i].iw);
dprintf(_T("%d: %f, %f, %f, %f\n"), i, vertex_buffer[i].x, vertex_buffer[i].y, vertex_buffer[i].z, vertex_buffer[i].w);
dprintf(_T("%d: %f, %f, %f, %f\n"), i, normal_buffer[i].x, normal_buffer[i].y, normal_buffer[i].z, normal_buffer[i].w);
}

// シリアライズ
t = ::timeGetTime();
msgpack::sbuffer sbuf;
msgpack::pack(sbuf, test);
dprintf(_T("serialize: %f ms\n"), ::timeGetTime() - t);

// デシリアライズと型変換
t = ::timeGetTime();
msgpack::object o;
msgpack::zone z;
msgpack::unpack(sbuf.data(), sbuf.size(), NULL, &z, &o);
TestMessage deserialized;
o.convert(&deserialized);
dprintf(_T("deserialize and convert: %f ms\n"), ::timeGetTime() - t);


// 5個くらい出力
const std::vector<um_vector4>& dface_buffer = deserialized.face_buffer();
const std::vector<um_vector4>& dvertex_buffer = deserialized.vertex_buffer();
const std::vector<um_vector4>& dnormal_buffer = deserialized.normal_buffer();
for (int i = 0; i < 5; ++i) {
dprintf(_T("%d: %d, %d, %d, %d\n"), i, dface_buffer[i].ix, dface_buffer[i].iy, dface_buffer[i].iz, dface_buffer[i].iw);
dprintf(_T("%d: %f, %f, %f, %f\n"), i, dvertex_buffer[i].x, dvertex_buffer[i].y, dvertex_buffer[i].z, dvertex_buffer[i].w);
dprintf(_T("%d: %f, %f, %f, %f\n"), i, dnormal_buffer[i].x, dnormal_buffer[i].y, dnormal_buffer[i].z, dnormal_buffer[i].w);
}

return 0;
}


結果
generate: 248.000000 ms(まぁ生成は関係ないか)
0: 1331203329, 1326780490, 1306167479, 1331471174
0: 0.845902, 0.582280, 0.106706, 0.861866
0: 0.166993, 0.605348, 0.553501, 0.120232
1: 1311440957, 1327167508, 1326297665, 1307982867
1: 0.402404, 0.302981, 0.092047, 0.032100
1: 0.945747, 0.539411, 0.276434, 0.823911
2: 1322125276, 1318789220, 1304199979, 1292073686
2: 0.217559, 0.149822, 0.104422, 0.495793
2: 0.635239, 0.104648, 0.915693, 0.168465
3: 1332878461, 1326061273, 1317898430, 1330834387
3: 0.126696, 0.479609, 0.193420, 0.554528
3: 0.188907, 0.408642, 0.185277, 0.004868
4: 1314834350, 1310288645, 1305860913, 1325258904
4: 0.781957, 0.098019, 0.581745, 0.787152
4: 0.966463, 0.302529, 0.916513, 0.091087
serialize: 280.000000 ms
deserialize and convert: 823.000000 ms
0: 1331203329, 1326780490, 1306167479, 1331471174
0: 0.845902, 0.582280, 0.106706, 0.861866
0: 0.166993, 0.605348, 0.553501, 0.120232
1: 1311440957, 1327167508, 1326297665, 1307982867
1: 0.402404, 0.302981, 0.092047, 0.032100
1: 0.945747, 0.539411, 0.276434, 0.823911
2: 1322125276, 1318789220, 1304199979, 1292073686
2: 0.217559, 0.149822, 0.104422, 0.495793
2: 0.635239, 0.104648, 0.915693, 0.168465
3: 1332878461, 1326061273, 1317898430, 1330834387
3: 0.126696, 0.479609, 0.193420, 0.554528
3: 0.188907, 0.408642, 0.185277, 0.004868
4: 1314834350, 1310288645, 1305860913, 1325258904
4: 0.781957, 0.098019, 0.581745, 0.787152
4: 0.966463, 0.302529, 0.916513, 0.091087

0 件のコメント: