昨日のDataStoreの書き込み性能の測定の続きで、DataStoreの読み込みとMemcachedの読み書きの性能を測定した。
比較内容
以下の5項目の測定を行った。100バイトの読み書き50回を1セットとして、10回測定しグラフを作成した。
- Store/W
DataStoreへの保存 - Store/R
DataStoreから1レコード取得 - Mem/W
Memcachedへの保存 - Mem/R – s
Memcachedからの読込。データが存在する場合。 - Mem/R – m
Memcachedからの読込。データが存在しない場合。
結果グラフ
縦軸は1回当たりの処理時間(単位ms)、横軸は10回分の測定結果。
結果考察
MemcachedのReadが最も高速で、MemcachedのWrite、DataStoreのRead、DataStoreのWriteと順に遅くなった。平均処理時間と、MemcachedのReadを1とした時の実行時間を表にまとめてみた。
– | Store/W | Store/R | Mem/W | Mem/R-s | Mem/R-m |
時間[ms] | 17.94 | 7.1 | 2.29 | 2.12 | 2.07 |
Mem/R比 | 8.68 | 3.43 | 1.11 | 1.02 | 1 |
この結果から、Memcachedの性能は、DataStoreと比べてReadで3倍程度、Writeで8倍程度高速であることが分かる。Memcachedのキャッシュヒット率が50%を超えるようなサービスであれば、Memcached導入によるパフォーマンスアップが期待できそうだ。
測定用プログラム
測定に用いたプログラムを掲載しておく。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | #!/usr/bin/env python from google.appengine.ext import webapp,db from google.appengine.ext.webapp import util from google.appengine.api import memcache import datetime class MainHandler(webapp.RequestHandler): def get(self): count = 1 # Default number of trials size = 100 # Default string length if self.request.get("count"): count = int(self.request.get("count")) if self.request.get("size"): size = int(self.request.get("size")) self.response.out.write("-"*10 + "DataStore - write<br>") for j in xrange(10): start_time = datetime.datetime.now() for i in xrange(count): BenchData(text_data = "x" * size).put() timediff = datetime.datetime.now() - start_time self.response.out.write("%0.3f<br>" % (timediff.microseconds / 1000000.0 + timediff.seconds)) self.response.out.write("-"*10 + "DataStore - read<br>") for j in xrange(10): start_time = datetime.datetime.now() for i in xrange(count): BenchData.all().fetch(1) timediff = datetime.datetime.now() - start_time self.response.out.write("%0.3f<br>" % (timediff.microseconds / 1000000.0 + timediff.seconds)) self.response.out.write("-"*10 + "Memcached - write<br>") for j in xrange(10): start_time = datetime.datetime.now() for i in xrange(count): memcache.add("key", "x" * size, 60) timediff = datetime.datetime.now() - start_time self.response.out.write("%0.3f<br>" % (timediff.microseconds / 1000000.0 + timediff.seconds)) self.response.out.write("-"*10 + "Memcached - read - hit<br>") for j in xrange(10): start_time = datetime.datetime.now() for i in xrange(count): memcache.get("key") timediff = datetime.datetime.now() - start_time self.response.out.write("%0.3f<br>" % (timediff.microseconds / 1000000.0 + timediff.seconds)) self.response.out.write("-"*10 + "Memcached - read - miss<br>") for j in xrange(10): start_time = datetime.datetime.now() for i in xrange(count): memcache.get("key_") timediff = datetime.datetime.now() - start_time self.response.out.write("%0.3f<br>" % (timediff.microseconds / 1000000.0 + timediff.seconds)) def main(): application = webapp.WSGIApplication([('/', MainHandler)], debug=True) util.run_wsgi_app(application) class BenchData(db.Model): text_data = db.TextProperty() if __name__ == '__main__': main() |
実行結果の生データ
実行結果の生データは以下の通り。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | ----------DataStore - write 0.949 0.853 0.877 0.866 0.962 0.932 0.869 0.838 1.002 0.824 ----------DataStore - read 0.406 0.338 0.394 0.385 0.312 0.333 0.323 0.342 0.407 0.309 ----------Memcached - write 0.119 0.130 0.116 0.097 0.125 0.118 0.101 0.108 0.115 0.116 ----------Memcached - read - hit 0.096 0.105 0.111 0.113 0.093 0.101 0.115 0.109 0.130 0.085 ----------Memcached - read - miss 0.116 0.099 0.112 0.107 0.089 0.110 0.103 0.102 0.099 0.097 |