JSON/BSON/MessagePack å¦çé度ã»ãã¼ã¿ãµã¤ãºå®å ¨æ¯è¼
å¨ãã§BSONããMessagePackããã話é¡ã«ãªã£ã¦ãã¦ï¼ããã«æ¤è¨¼ãããã«ä½é¨ãã§ãã ãã¨æã£ã¦ãããï¼åªç§ãªè¥ãé£ä¸ãé ã¾ããªããJSONã¨MessagePackã®ãªã¢ã«æ¤è¨¼ããã¦ããã®ã§ï¼ãããªæ¤è¨¼ã¯åç´éããã¨ããã®ã¨ä¸¡æ¥µç«¯ã®äºã¤ã ãæ¤è¨¼ãã¦ã©ãããã¨ããæãããï¼ã¡ããã¨ç§ãæ¤è¨¼ä½æ¥ããã¦ã¿ã¾ããï¼
ã¾ãï¼ä½¿ç¨è¨èªã¯ï¼åçãªã¬ãã¼ã¸ã³ã¬ã¯ã·ã§ã³ãªã©ã§å¦çé度測å®ãä¸å®å®ã«ãªãã®ãé¿ããããã«ï¼APIãã¤ã³ãã£ã³ã°ã¯C/C++ï¼
対象ã¨ããã·ãªã¢ã©ã¤ãºã©ã¤ãã©ãªã¯ï¼ä»£è¡¨çãªãã¬ã¼ã³JSONã¨ï¼MongoDBã§ä½¿ããã¦ããBSONï¼RedisãKumoFSã§ä½¿ããã¦ããMessagePackã®3ã¤ã§ãï¼ã ãããï¼æè¿ã®è»å¼±ãªJavaããã°ã©ãã¼ã¯ï¼JavaScriptã§ããªãã®ã«çJSONãªãã¦ãããã使ãããããã¼ãã£ã¦æãã§ããï¼ããã説æã§ããã°ãããªã¨æã£ã¦ãã³ããã¼ã¯ããã°ã©ã ãä½ã£ã¦ã¿ã¾ããï¼
ãã³ããã¼ã¯ã¯ï¼åç´ã«C++ã§å ããªHashã¨ãã¼ã¿ã¨ãã¦ããã¨é·ãç¶ãé åãã·ãªã¢ã©ã¤ãºå¾ï¼å¤ãæ¤è¨¼ãã¤ã¤ãã·ãªã¢ã©ã¤ãºããåç´ãªãã®ã§ãï¼
測å®çµæããããã¾ãï¼
ãã¼ã¿ã®é åã5åã£ã¦ãããããã ãªå ´åï¼ããããåã ã«ãã¦ãã£ã¦ï¼ãã¼ã¿é åã10åï¼20åã¾ã§å¤åããï¼ã·ãªã¢ã©ã¤ãºã»ãã·ãªã¢ã©ã¤ãºã®é度ã¨ã·ãªã¢ã©ã¤ãºçµæã®ãã¼ã¿ãµã¤ãºãæ¯è¼ãã¦ã¿ã¾ããï¼
ã¾ãï¼ãã¼ã¿æ°ã5åï¼10åï¼20åã®å ´åã®ï¼ãã¬ã¼ã³JSONï¼BSONï¼MessagePackã®å¦çé度測å®çµæã§ãï¼
ãã¼ã¿æ°ãã©ã®å ´åã§ãï¼3種é¡ã®ãã©ã¼ãããã®ãã¡ï¼MessagePackãæå°ãµã¤ãºã«ãªã£ã¦ããã®ãåããã¾ãï¼
次ã«ï¼ã·ãªã¢ã©ã¤ãºã¨ãã·ãªã¢ã©ã¤ãºã®æéã足ãããã¼ã¿ã«ãªå¦çæéãX軸ã«ï¼ãã¼ã¿ãµã¤ãºãY軸ã«ããããããã°ã©ããä½ã£ã¦ã¿ã¾ãï¼
縦軸ã横軸ãåç¹ã«è¿ãã¦å°ããã»ã©ï¼åªç§ã¨è¨ã£ã¦è¯ãã¨æãã¾ãï¼
ä¸è§ãMessagePackï¼åè§ãããJSONï¼ä¸¸ãBSONã§ãï¼
BSONã¯ï¼æå¤ã«ãããããä¸çªä¸ã«æ¥ã¦ããã®ãåããã¨æãã¾ãï¼ããã¯ï¼BSONãå¹æçãªé
åã¹ãã¢ããµãã¼ããã¦ããªãã¦ï¼å
é¨ã§ããã·ã¥ã«ç´ãã¦ãããã¨ã«ç±æ¥ãã¾ãï¼
ãã ï¼ã·ãªã¢ã©ã¤ãºã»ãã·ãªã¢ã©ã¤ãºé度ã¯JSONããã¯BSONãéããã¨ãåããã¾ãï¼
ã¾ï¼æå¼·ã¯ï¼ãã®ä¸ã§ã¯MessagePackã¨ãããã¨ã§ï¼
使ç¨ããããã°ã©ã ã以ä¸ã«ç¤ºãã¾ãï¼
ã¾ãï¼JSONã§ãï¼JSON-Cã¨ããã©ã¤ãã©ãªã使ãã¾ããï¼
FreeBSDã§ã¯ï¼ãããªæãã«ç°¡åã«å
¥ãã¾ãï¼
# cd /usr/ports/devel/json-c/ # make # make install
ã¡ã¤ã³ããã°ã©ã ã¯ãããªæãã§ãï¼
/********** * c++ json-c.cc -o json-c -Wall -I/usr/local/include -L/usr/local/lib -ljson **********/ #include <string> #include <stdio.h> #include <time.h> #include <iostream> #include <fstream> #include <json/json.h> using namespace std; #define MAX_LOOP 100000 #define MAX_ITEMS 30 #define ITEM_PROPERTIES 1 #define MAX_BUF 32768 int main() { time_t start, set_end, get_end; int suc = 0; start = time(NULL); json_object *obj, *keyobj, *headerobj, *valobj, *valarray, *itemarray; ofstream os("json-c.obj"); for(int i=0; i<MAX_LOOP; ++i) { obj = json_object_new_array(); char keybuf[MAX_BUF]; snprintf(keybuf,MAX_BUF, "%010d", i); keyobj = json_object_new_object(); json_object_object_add(keyobj, "key", json_object_new_string(keybuf)); headerobj = json_object_new_object(); json_object_object_add(headerobj, "v", json_object_new_int(1)); json_object_object_add(headerobj, "t", json_object_new_int(time(NULL))); json_object_object_add(headerobj, "n", json_object_new_int(MAX_ITEMS)); valobj = json_object_new_object(); valarray = json_object_new_array(); for(int j=0; j<MAX_ITEMS; ++j) { itemarray = json_object_new_array(); for(int k=0; k<ITEM_PROPERTIES; ++k) { json_object_array_add(itemarray, json_object_new_int(k)); } json_object_array_add(itemarray, json_object_new_int(time(NULL))); json_object_array_add(valarray, itemarray); } json_object_object_add(valobj, "val", valarray); json_object_array_add(obj, keyobj); json_object_array_add(obj, headerobj); json_object_array_add(obj, valobj); ++suc; os<<json_object_to_json_string(obj)<<endl; array_list_free(json_object_get_array(obj)); } ifstream is("json-c.obj"); set_end = time(NULL); for(int i=0; i<MAX_LOOP; ++i) { char keybuf[MAX_BUF], line[MAX_BUF]; is.getline(line, MAX_BUF); obj = json_tokener_parse(line); if(obj == NULL) { cout<< "ERROR" <<flush<<endl; exit(0); } snprintf(keybuf,MAX_BUF, "%010d", i); json_object *key = json_object_object_get(json_object_array_get_idx(obj, 0), "key"); // Get key if(strncmp(keybuf, json_object_get_string(key), 10) != 0) continue; json_object *valobj = json_object_array_get_idx(obj, 1); // Get header json_object *v = json_object_object_get(valobj, "v"); json_object *t = json_object_object_get(valobj, "t"); json_object *n = json_object_object_get(valobj, "n"); if(json_object_get_int(v) != 1 || json_object_get_int(t) < 0 || json_object_get_int(n) != MAX_ITEMS) continue; valarray = json_object_object_get(json_object_array_get_idx(obj, 2), "val"); // Get value json_object ** item = new json_object*[ITEM_PROPERTIES]; for(int j=0; j<MAX_ITEMS; ++j) { itemarray = json_object_array_get_idx(valarray, j); for(int k=0; k<ITEM_PROPERTIES; ++k) { item[k] = json_object_array_get_idx(itemarray, k); if(json_object_get_int(item[k]) != k) { k = ITEM_PROPERTIES; j = MAX_ITEMS; delete[] item; item = NULL; } } } if(item == NULL) continue; ++suc; array_list_free(json_object_get_array(obj)); } get_end = time(NULL); printf("try=%d success=%d ratio=%f\n",MAX_LOOP,suc/2,(double)suc/2/MAX_LOOP*100.0); printf("set=%d[sec], get=%d[sec], total=%d[sec]\n", set_end-start, get_end-set_end, get_end-start); return(0); }
次ã«BSONã§ãï¼
æ¬å®¶ï¼MongoDBã®ãã®ã使ãã¾ããï¼ãªã®ã§ï¼ä½è¨ãªboostã¿ãããªãã«ã¤ã©ã¤ãã©ãªãå¿
è¦ã¨ãã¦ãã¾ãï¼
ããã§ãï¼FreeBSDã§ã¤ã³ã¹ãã¼ã«ããã«ã¯ï¼ãããªæãã§ç°¡åã§ãï¼
# cd /usr/ports/databases/mongodb/ # make # make install
ãã³ããã¼ã¯ããã°ã©ã ã¯ãããªæãã§ãï¼
/********** * c++ bson.cc -o bson -Wall -I/usr/local/include -L/usr/local/lib -lboost_filesystem -lboost_system -lboost_thread -lmongoclient **********/ #include <string> #include <stdio.h> #include <time.h> #include <iostream> #include <fstream> #include <mongo/bson/bson.h> using namespace std; using namespace mongo; #define MAX_LOOP 100000 #define MAX_ITEMS 30 #define ITEM_PROPERTIES 1 #define MAX_BUF 32768 int main() { time_t start, set_end, get_end; int suc = 0; start = time(NULL); BSONObj obj, keyobj, headerobj, valobj, valarray, itemarray; ofstream os("bson.obj"); for(int i=0; i<MAX_LOOP; ++i) { BSONObjBuilder objb, keyobjb, headerobjb, valobjb; char keybuf[MAX_BUF]; snprintf(keybuf,MAX_BUF, "%010d", i); keyobjb.append("key", keybuf); headerobjb.append("v", 1); headerobjb.append("t", time(NULL)); headerobjb.append("n", MAX_ITEMS); BSONArrayBuilder objarrayb, valarrayb; for(int j=0; j<MAX_ITEMS; ++j) { BSONArrayBuilder itemarrayb; for(int k=0; k<ITEM_PROPERTIES; ++k) { itemarrayb.append(k); } itemarrayb.append(time(NULL)); valarrayb.append(itemarrayb.arr()); } valobjb.append("val", valarrayb.arr()); objarrayb.append(keyobjb.obj()); objarrayb.append(headerobjb.obj()); objarrayb.append(valobjb.obj()); obj = objarrayb.arr(); ++suc; os.write(obj.objdata(),obj.objsize()); } ifstream is("bson.obj"); set_end = time(NULL); for(int i=0; i<MAX_LOOP; ++i) { char keybuf[MAX_BUF], line[MAX_BUF]; int size; is.read((char *)&size, sizeof(int)); is.read(line+sizeof(int), size-sizeof(int)); memcpy(line, (char *)&size, sizeof(int)); obj = BSONObj(line); vector<BSONElement> objarrayb; obj.elems(objarrayb); snprintf(keybuf,MAX_BUF, "%010d", i); BSONElement key = objarrayb[0]["key"]; // Get key if(strncmp(keybuf, key.String().c_str(), 10) != 0) continue; BSONElement valobj = obj[1]; // Get header BSONElement v = valobj["v"]; BSONElement t = valobj["t"]; BSONElement n = valobj["n"]; if(v.Int() != 1 || t.Int() < 0 || n.Int() != MAX_ITEMS) continue; vector<BSONElement> itemarray = objarrayb[2]["val"].Array(); for(int j=0; j<MAX_ITEMS; ++j) { vector<BSONElement> item = itemarray[j].Array(); for(int k=0; k<ITEM_PROPERTIES; ++k) { if(item[k].Int() != k) { k = ITEM_PROPERTIES; j = MAX_ITEMS; itemarray.clear(); } } } if(itemarray.size() == 0) continue; ++suc; } get_end = time(NULL); printf("try=%d success=%d ratio=%f\n",MAX_LOOP,suc/2,(double)suc/2/MAX_LOOP*100.0); printf("set=%d[sec], get=%d[sec], total=%d[sec]\n", set_end-start, get_end-set_end, get_end-start); return(0); }
ææã¯MessagePackçã§ãï¼
ã©ã¤ãã©ãªã®ã¤ã³ã¹ãã¼ã«ã¯ï¼FreeBSDã§ã¯ãããªæãã§ãï¼
# cd /usr/ports/devel/msgpack/ # make # make install
ãã³ããã¼ã¯ããã°ã©ã ã¯ãããªæãã§ãï¼ã¹ããªã¼ãã³ã°ã»ãã·ãªã¢ã©ã¤ãºã«ã¼ãã³ã使ã£ã¦ãã¾ãï¼
/********** * c++ msgpack.cc -o msgpack -Wall -I/usr/local/include -L/usr/local/lib -lmsgpack **********/ #include <string> #include <stdio.h> #include <time.h> #include <iostream> #include <fstream> #include <msgpack.hpp> using namespace std; using namespace msgpack; #define MAX_LOOP 100000 #define MAX_ITEMS 30 #define ITEM_PROPERTIES 1 #define MAX_BUF 32768 int main() { time_t start, set_end, get_end; int suc = 0; start = time(NULL); sbuffer obj, keyobj, headerobj, valobj, valarray, itemarray; ofstream os("msgpack.obj"); typedef type::tuple<map<string, string>, map<string, int>, map<string, vector<vector<int> > > >doctype; doctype doc; for(int i=0; i<MAX_LOOP; ++i) { map<string, string> keyb; map<string, int> headerobjb; map<string, vector<vector<int> > > valobjb; char keybuf[MAX_BUF]; snprintf(keybuf,MAX_BUF, "%010d", i); keyb["key"] = keybuf; headerobjb["v"] = 1; headerobjb["t"] = time(NULL); headerobjb["n"] = MAX_ITEMS; vector<vector<int> > valarrayb; for(int j=0; j<MAX_ITEMS; ++j) { vector<int> itemarrayb; for(int k=0; k<ITEM_PROPERTIES; ++k) { itemarrayb.push_back(k); } itemarrayb.push_back(time(NULL)); valarrayb.push_back(itemarrayb); } valobjb["val"] = valarrayb; doc = doctype(keyb, headerobjb, valobjb); pack(obj, doc); ++suc; os.write(obj.data(),obj.size()); obj.clear(); } ifstream is("msgpack.obj"); set_end = time(NULL); char keybuf[MAX_BUF]; unpacker line; int i = 0; while(i < MAX_LOOP) { line.reserve_buffer(MAX_BUF); ssize_t len = is.readsome(line.buffer(), line.buffer_capacity()); if(len == 0) break; line.buffer_consumed(len); while(line.execute()) { object msg = line.data(); line.release_zone(); line.reset(); snprintf(keybuf,MAX_BUF, "%010d", i); doctype doc = msg.as<doctype>(); string key = doc.get<0>()["key"]; if(strncmp(keybuf, key.c_str(), 10) != 0) continue; else ++i; map<string, int> valobj = doc.get<1>(); int v = valobj["v"]; int t = valobj["t"]; int n = valobj["n"]; if(v != 1 || t < 0 || n != MAX_ITEMS) continue; map<string, vector<vector<int> > >itemarrayval = doc.get<2>(); vector<vector<int> > itemarray = itemarrayval["val"]; for(int j=0; j<MAX_ITEMS; ++j) { vector<int> item = itemarray[j]; for(int k=0; k<ITEM_PROPERTIES; ++k) { if(item[k] != k) { k = ITEM_PROPERTIES; j = MAX_ITEMS; itemarray.clear(); } } } if(itemarray.size() == 0) continue; ++suc; } } get_end = time(NULL); printf("try=%d success=%d ratio=%f\n",MAX_LOOP,suc/2,(double)suc/2/MAX_LOOP*100.0); printf("set=%d[sec], get=%d[sec], total=%d[sec]\n", set_end-start, get_end-set_end, get_end-start); return(0); }