前回の記事ã§è¿°ã¹ãæ§è½è©ä¾¡ã«ãã£ã¦ãgRPCã«ããæä½ãåä¸ãã·ã³ä¸ãªã2ä¸QPSã®ã¹ã«ã¼ãããã§å®è¡ã§ãããã¨ãåãã£ããããã¯ãã¼ã¿ãã¼ã¹èªä½ã®æ§è½ã«æ¯ã¹ãã¨é
ãããã®ã§ãããé«ãã¹ã«ã¼ããããåºããããã«gRPCã®ä½¿ãæ¹ã工夫ããããªããä»åã¯ããããåã¨ã¹ããªã¼ã åãè¡ã£ã¦ã©ã®ç¨åº¦æ§è½ãåä¸ã§ãããã確ãããã
ä¸åã®RPCå¼ã³åºãã§è¤æ°ã¬ã³ã¼ãã®æ¤ç´¢ãæ´æ°ãè¡ããã¨ããããåã¨å¼ã¶ãä¾ãã°ã以ä¸ã®ã¡ã½ããã¯3ã¤ã®ã¬ã³ã¼ãã®ãã¼ã¿ãä¸æ°ã«åå¾ããã
std::vector<std::string> keys = {"foo", "bar", "baz"}; std::map<std::string, std::string> records = dbm.GetMulti(keys);
以ä¸ã®ã¡ã½ããã¯ã3ã¤ã®ã¬ã³ã¼ãã®æ ¼ç´ã¨åé¤ãé ã«è¡ãã
std::map<std::string, std::string> records = {{"foo", "hop"}, {"bar", "step"}, {"baz", "jump"}}; dbm.SetMulti(records); std::vector<std::string> keys = {"foo", "bar", "baz"}; dbm.Remove(keys);
GetMultiã®gRPCã®ã¡ã½ããå®ç¾©ã¯ä»¥ä¸ã®ããã«ãªãã
// GetMultiã®ãªã¯ã¨ã¹ã message GetMultiRequest { // æä½å¯¾è±¡ã®ãã¼ã¿ãã¼ã¹ã®ã¤ã³ããã¯ã¹ int32 dbm_index = 1; // åå¾ããã¬ã³ã¼ãã®ãã¼ã®ãªã¹ã repeated bytes keys = 2; } // GetMultiã®ã¬ã¹ãã³ã¹ message GetMultiResponse { // ã¹ãã¼ã¿ã¹ã³ã¼ã StatusProto status = 1; // 該å½ã¬ã³ã¼ãã®key-valueãã¢ã®ãªã¹ã repeated BytesPair records = 2; } service DBMService { rpc GetMulti(GetMultiRequest) returns (GetMultiResponse); }
ã¢ããªã±ã¼ã·ã§ã³å´ã®å·¥å¤«ã§è¤æ°æä½ã®ãããåãã§ãããªãã°ãæãå¹çãè¯ããåã ã®RPCã®ã¡ãã»ã¼ã¸ã¯å¤§ãããªãããå¼ã³åºãåæ°ãæ¸ãã®ã§ãåçã«é«éåãããã¨ã¯ãããç©ã«ã¯é åºããããè¨ç®å¦çã«ã¯ä¾åé¢ä¿ãããã®ã§ããã¾ããã¨ãããåãã§ããã¦ã¼ã¹ã±ã¼ã¹ã¯ãããªã«å¤ããªãã
次åçã¯ãã¹ããªã¼ã åã§ãããgRPCã®ã¹ããªã¼ã APIã§ã¯ãä¸åã®RPCå¼ã³åºãã®ä¸ã§è¿½å ã®ãã¼ã¿ã®æåãã§ãããããã¯ã¤ãã¬ã¼ã¿ã®å®è£ ã§ä½¿ã£ãã®ã¨åãæ¹æ³ã ãã¹ããªã¼ã ãªãã¸ã§ã¯ããä½ã£ã¦ããããããä»ãã¦GetãSetãªã©ã®æä½ãè¡ãã®ã ã
std::unique_ptr<RemoteDBM::Stream> stream = dbm.GetStream(); stream.Set("foo", "hop"); stream.Set("bar", "step"); std::string value; stream.Get("foo", &value); stream.Remove("foo");
ã¹ããªã¼ã ã®gRPCã®ã¡ã½ããå®ç¾©ã¯ä»¥ä¸ã®ããã«ãªããã¹ããªã¼ã ã§ãªãAPIã®ãªã¯ã¨ã¹ãã¨ã¬ã¹ãã³ã¹ããã£ãããã®ã¾ã¾ã¹ããªã¼ã ã«æµãè¾¼ãã§ããã ãã ã
// å æ¥ã®Getã®ãªã¯ã¨ã¹ã message GetRequest { int32 dbm_index = 1; bytes key = 2; bool omit_value = 3; } // å æ¥ã®Getã®ã¬ã¹ãã³ã¹ message GetResponse { StatusProto status = 1; bytes value = 2; } // Streamã¡ã½ããã®ãªã¯ã¨ã¹ã message StreamRequest { // å æ¥ã®ã¡ã½ããã®ãªã¯ã¨ã¹ããoneofã§åãè¾¼ã oneof request_oneof { EchoRequest echo_request = 1; GetRequest get_request = 2; SetRequest set_request = 3; RemoveRequest remove_request = 4; } // æ´æ°ç³»ã®å ´åãã¬ã¹ãã³ã¹ãçç¥ãã¦é«éåã§ãã bool omit_response = 101; } // Streamã¡ã½ããã®ã¬ã¹ãã³ã¹ message StreamResponse { // ãªã¯ã¨ã¹ãã®æä½ã«å¯¾å¿ããã¬ã¹ãã³ã¹ãåãè¾¼ã oneof response_oneof { EchoResponse echo_response = 1; GetResponse get_response = 2; SetResponse set_response = 3; RemoveResponse remove_response = 4; } } service DBMService { rpc Stream(stream StreamRequest) returns (stream StreamResponse); }
ã¹ããªã¼ã ã®å©ç¨ã§æ³¨æãã¹ãã¯ãåã ã®ã¹ããªã¼ã ã¯ãµã¼ãå´ã®ä¸ã¤ã®ã¹ã¬ãããå°æããã¨ãããã¨ã§ããããã®ãã¨ã¯ãµã¼ãå´ã®å®è£ ãè¦ãã¨ããããããã
grpc::Status StreamImpl(grpc::ServerContext* context, grpc::ServerReaderWriterInterface< tkrzw::StreamResponse, tkrzw::StreamRequest>* stream) { // ã¹ããªã¼ã ãçµããã¾ã§ã«ã¼ã while (true) { // ãã£ã³ã»ã«ããããæãã if (context->IsCancelled()) { return grpc::Status(grpc::StatusCode::CANCELLED, "cancelled"); } // 次ã®ãªã¯ã¨ã¹ããèªã¿è¾¼ã tkrzw::StreamRequest request; if (!stream->Read(&request)) { break; } // ãªã¯ã¨ã¹ãã®å 容ã«å¿ããå¦çãè¡ã tkrzw::StreamResponse response; switch (request.request_oneof_case()) { case tkrzw::StreamRequest::kGetRequest: { const grpc::Status status = Get(context, &request.get_request(), response.mutable_get_response()); if (!status.ok()) { return status; } break; } ... default: { return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "unknow request"); } } // çµæãæ¸ãè¾¼ã if (!request.omit_response() && !stream->Write(response)) { break; } } return grpc::Status::OK; }
ã¤ã¾ããã¹ããªã¼ã APIã¯ãRPCã®åæåå¦çãå¼ã³åºãããåæ°ãæ¸ããã¦ãªã¼ãã¼ããããåæ¸ããå¹æãããåé¢ã並åå¦çæ§è½ãä¸ãã¦ãã¾ããè¨ãæããã¨ãå ¨ä½ã®ã¹ã«ã¼ããããä¸ããå¹æã¯ããããåã ã®RPCå¼ã³åºãã®ã¬ã¤ãã³ã·ã®åå·®ãä¸ãã¦ãã¾ãå¯ä½ç¨ãããããã£ã¦ãã¹ããªã¼ã APIãä¸è½ã¨ããããã§ã¯ãªããé©æé©æã§ä½¿ãåããã°ãªããªãã
ã¾ã¨ããã¨ããããåã§ããã¨ãã¯ãããAPIã使ããããã§ã¯ãªããçæéã«è¤æ°ã®ãã¼ã¿ãã¼ã¹æä½ãéä¸çã«è¡ãå ´åã«ã¯ã¹ããªã¼ã APIã使ããããã§ããªãå ´åã«ã¯é常ã®APIã使ãã¨ããã ããã
ãã¦ãæ§è½è©ä¾¡ãããããååã¨åæ§ã«ã100ä¸ã¬ã³ã¼ããæ ¼ç´ãããã¨ãæ³å®ãã¦ã200ä¸ãã±ããã«è¨å®ããããã·ã¥ãã¼ã¿ãã¼ã¹ãéç¨ãããã¼ã¿ãã¼ã¹ãµã¼ãã¹ãç«ã¦ãããããã¯ã¼ã¯å±¤ã«ã¯ãUNIXãã¡ã¤ã³ã½ã±ããã¨IPv4ã使ãåããã
# UNIXãã¡ã¤ã³ã½ã±ããã®å ´å $ tkrzw_server --address "unix:$HOME/tkconn" "casket.tkh#num_buckets=2m" # IPv4ã®TCPã½ã±ããã®å ´å $ tkrzw_server --address "127.0.0.1:1978" casket.tkh#num_buckets=2m"
ã¯ã©ã¤ã¢ã³ãã¯ã以ä¸ã®ããã«å®è¡ãããå®éã«ã¯ãå®é¨å 容ã«å¿ãã¦ãããããªãã·ã§ã³ãä»ããã
$ tkrzw_dbm_remote_perf sequence --address "unix:$HOME/tkconn" --iter 1000000 --threads 1 $ tkrzw_dbm_remote_perf sequence --address "127.0.0.1" --iter 1000000 --threads 1
以ä¸ã®æä½ã測å®ãããæä½ã¯åè¨100ä¸åè¡ããã¯ã©ã¤ã¢ã³ãå´ã®ã¹ã¬ããã¯1ã2ã4ã¨ããã
- normal-Echo : é常APIã®Echo
- normal-Set : é常APIã®Set
- normal-Get : é常APIã®Get
- normal-Remove : é常APIã®Get
- multi-Echo-10 : Echoã10ã¡ãã»ã¼ã¸åã¾ã¨ãã¦å®è¡
- multi-Set-10 : ãããAPIã®SetMultiã10ã¬ã³ã¼ããã¾ã¨ãã¦å®è¡
- multi-Get-10 : ãããAPIã®GetMultiã10ã¬ã³ã¼ããã¾ã¨ãã¦å®è¡
- multi-Remove-10 : ãããAPIã®RemoveMultiã10ã¬ã³ã¼ããã¾ã¨ãã¦å®è¡
- multi-Echo-100 : Echoã100ã¡ãã»ã¼ã¸åã¾ã¨ãã¦å®è¡
- multi-Set-100 : ãããAPIã®SetMultiã100ã¬ã³ã¼ããã¾ã¨ãã¦å®è¡
- multi-Get-100 : ãããAPIã®GetMultiã100ã¬ã³ã¼ããã¾ã¨ãã¦å®è¡
- multi-Remove-100 : ãããAPIã®RemoveMultiã100ã¬ã³ã¼ããã¾ã¨ãã¦å®è¡
- Stream-Echo : ã¹ããªã¼ã APIã®Echo
- Stream-Set : ã¹ããªã¼ã APIã®Set
- Stream-Get : ã¹ããªã¼ã APIã®Get
- Stream-Remove : ã¹ããªã¼ã APIã®Remove
- Stream-Set-NR : ã¹ããªã¼ã APIã®Setãã¬ã¹ãã³ã¹ã®ç¢ºèªãçç¥
- Stream-Remove-NR : ã¹ããªã¼ã APIã®Removeãã¬ã¹ãã³ã¹ã®ç¢ºèªãçç¥
çµæã¯ä»¥ä¸ã®ããã«ãªããæ°å¤ã®åä½ã¯QPSï¼ã¯ã¨ãªæ¯ç§ï¼ã§ããã
UNIX 1 thread | UNIX 2 thread | UNIX 4 thread | IPv4 1thread | IPv4 2thread | IPv4 4thread | |
normal-Echo | 20,347 | 28,197 | 25,292 | 16,887 | 24,168 | 26,510 |
normal-Set | 19,013 | 21,791 | 21,563 | 15,523 | 19,143 | 21,479 |
normal-Get | 18,356 | 20,762 | 24,483 | 16,679 | 20,678 | 21,714 |
normal-Remove | 17,557 | 19,272 | 22,204 | 16,469 | 19,636 | 22,102 |
multi-Echo-10 | 180,145 | 253,989 | 308,470 | 155,716 | 232,544 | 258,576 |
multi-Set-10 | 140,446 | 192,152 | 260,460 | 123,170 | 188,309 | 226,687 |
multi-Get-10 | 137,117 | 193,273 | 237,894 | 120,738 | 178,721 | 215,959 |
multi-Remove-10 | 155,806 | 166,968 | 258,288 | 138,660 | 196,866 | 255,105 |
multi-Echo-100 | 1,439,564 | 1,973,220 | 2,720,126 | 1,000,875 | 1,827,947 | 2,473,265 |
multi-Set-100 | 458,714 | 746,803 | 1,188,727 | 323,048 | 761,758 | 1,036,163 |
multi-Get-100 | 493,673 | 769,554 | 1,067,237 | 286,206 | 732,079 | 1,066,825 |
multi-Remove-100 | 703,227 | 987,542 | 1,310,496 | 544,677 | 1,019,257 | 1,331,260 |
Stream-Echo | 26,849 | 32,829 | 30,449 | 22,452 | 29,155 | 25,800 |
Stream-Set | 24,921 | 26,524 | 23,256 | 21,058 | 24,131 | 20,255 |
Stream-Get | 22,635 | 25,337 | 24,260 | 20,445 | 23,463 | 22,550 |
Stream-Remove | 22,792 | 26,432 | 22,796 | 20,693 | 23,231 | 20,645 |
Stream-Set-NR | 170,516 | 122,711 | 100,274 | 104,200 | 67,788 | 67,992 |
Stream-Remove-NR | 183,737 | 122,710 | 93,004 | 105,652 | 61,283 | 61,939 |
ã¾ãã1åç®ã®ãUNIXãã¡ã¤ã³ã¹ã¬ããã®1ã¹ã¬ããã®çµæã«çç®ããããä¸ç®çç¶ãªã®ã¯ããããåæå¼·ã¨ãããã¨ã ã10åã®æä½ããããåã§ããã°ãRPCã®å¼ã³åºãåæ°ã1/10ã«ã§ããã®ã§ãããã ãé«éåãããå½ç¶ã¨ããã°å½ç¶ã ãEchoã¨ãã®ä»ã®ã¡ã½ããã®å·®ããã¼ã¿ãã¼ã¹æä½ã®ãªã¼ãã¼ãããã¨ã¿ãªãããããããå100åã®4ã¹ã¬ããã«ãªãã¨å§ãã¦ãã¼ã¿ãã¼ã¹ã®æ§è½ãç®ã«è¦ããããã«ãªããEcho272ä¸QPSã«å¯¾ãã¦Set118ä¸QPSã«ãªãããã£ã¨ãã¼ã¿ãã¼ã¹ãããã«ããã¯ã«ãªãã
2åç®ã¨3åç®ãè¦ã¦ãã¹ã¬ããæ°ã¨ã¹ã«ã¼ãããã®é¢ä¿ãèå¯ãããé常ã®APIã§ã¯ã2ã¹ã¬ããã¾ã§ã¯ã¹ã«ã¼ãããåä¸ã®å¹æããããã4ã¹ã¬ããã«ãã¦ãæå³ããªãã¨ãããã¨ãããããä¸æ¹ã§ããããåããå ´åãã¹ã¬ããæ°ã«å¿ãã¦ã¹ã«ã¼ããããé¡èã«ä¸ããããã®ãã¨ããèããã¨ãgRPCã®ã¡ã½ããå¼ã³åºãã«ããããªã¼ãã¼ãããã¯ãã«ãã¹ã¬ããã«ãã並åå¦çã§ã¯æ¹åããªããããã
次ã«ç®ãã¤ããã¹ãã¯ãã¹ããªã¼ã APIã§ã¬ã¹ãã³ã¹ã®ç¢ºèªãçç¥ããå ´åã ã17ä¸QPSã§Setã§ãã18ä¸QPSã§Removeã§ãããã¬ã¹ãã³ã¹ã®ç¢ºèªãããªãGetã¯æå³ããªãã®ã§æ¸¬å®ãã¦ããªããã¬ã¹ãã³ã¹ã確èªããªãã¨ãªãããã¾ã§é«éåãããã¨ããã¨ãã¹ããªã¼ã ãåæ¹åã«ãªãããã ãReadã¨Writeãç¹°ãè¿ãåæ¹åã¹ããªã¼ã ã ã¨ãepollãªã©ã§å ¥åºåã®ã¢ã¼ããåãæ¿ããå¿ è¦ãããããåæ¹åã ã¨ãã®å¿ è¦ããªããã¬ã¹ãã³ã¹ã®ç¢ºèªçç¥ã§æãé«ãã¹ã«ã¼ããããåºãã®ã1ã¹ã¬ããã ã¨ããã®ãèå³æ·±ãã¨ããã ããµã¼ãå´ã§ãªã¯ã¨ã¹ããç´ååããå¦çã«ããã«ããã¯ãããæ°ãããããããã¾ã§æ¨æ¸¬ã ã
æå¾ã«ãUNIXãã¡ã¤ã³ã½ã±ããã¨IPv4ãæ¯è¼ããããå½ç¶ãªããUNIXãã¡ã¤ã³ã½ã±ããã®æ¹ãæ©ãã®ã ããã¹ã¬ããæ°ãå¢ããã¨å·®ã縮ã¾ãã¨ãããèå³æ·±ããåç´ãªãã¼ã¿è»¢éé度ã§ã¯UNIXãã¡ã¤ã³ã½ã±ããã«åªä½æ§ãããã®ã ããããã¹ã¬ãããåãæ¿ããªããç´°ãããã¼ã¿ã®æåãè¡ããããªå ´åã ã¨ãTCP/IPã¨å¤§ãã¦å¤ãããªãæ§è½ã«ãªã£ã¦ãã¾ããããã
ã¾ã¨ããTkrzw-RPCã®APIã«ãããåAPIã¨ã¹ããªã¼ã åAPIãå ãã¦ãã¦ã¼ã¹ã±ã¼ã¹ã«ãã£ã¦æé©ãªã¢ã¼ããé¸ã¹ãããã«ãããäºæ³éãããããåã¯åçãªå¹æãããã100ä¸QPSãè¶ ããã¹ã«ã¼ããããåºããããã«ãªããã¨ã¯ãããããåã¯å¸¸ã«é©ç¨ã§ããããã§ã¯ãªããæ´æ°ç³»ã«é¢ãã¦ã¯ã¹ããªã¼ã APIã®ã¬ã¹ãã³ã¹çç¥ã¢ã¼ãã便å©ã§ããã®å ´åã10ä¸QPSã¨ãã§æä½ã§ããããã«ãªããåç §ç³»ã«é¢ãã¦ã¯ãããå以å¤ã®æã¯ãªãã次åã¯ãéåæåã§ã¹ã«ã¼ããããä¸ãããã©ããæ¤è¨ããã