Google App Engineのmemcacheを試してみた

練習もかねてGoogle App Engine上のmemcacheを試してみました。

下記がそのコードなんですが、簡単なモデルデータ(Record)をBigTableに保存して
そのデータに対して、BigTableから直接取得するのと、予め登録したmemcacheから
取得するのをそれぞれ1000回繰り返す処理をプロファイラで集計・表示しています。

# -*- coding: utf-8 -*-

import uuid, random, logging, sys
from google.appengine.ext import webapp, db
from google.appengine.api import memcache
from google.appengine.ext.webapp.util import run_wsgi_app

class Record(db.Model):
  guid   = db.StringProperty()
  status = db.StringProperty(choices=('good', 'normal', 'bad'))

class PrepareRecord(webapp.RequestHandler):
  def get(self):
    choices = ['good', 'normal', 'bad']
    for i in range(0, 100):
      status  = choices[int(random.random() * 3) * i % 3]
      record  = Record(guid = str(uuid.uuid1()), status=status)
      record.put()
    self.response.out.write('please access /')

class Test(webapp.RequestHandler):
  def get(self):
    if (Record.all() != None):
      memcache.add('all', Record.all(), 60)
      memcache.add('good', Record.all().filter('status =', 'good'), 60)
      for i in range(0, 1000):
        self.fromStored()
        self.fromCached()
      self.response.out.write('profile completed')
    else:
      self.response.out.write('no stored data. please access /prepare')
  # BigTableから取得
  def fromStored(self):
    memcache.get('all')
    memcache.get('good')
  # memcacheから取得
  def fromCached(self):
    Record.all()
    Record.all().filter('status =', 'good')

application = webapp.WSGIApplication(
  [
    ('/', Test),
    ('/prepare', PrepareRecord),
    ],
  debug=True)

def real_main():
  run_wsgi_app(application)

# プロファイル用のコード
def profile_html_main():
  import cProfile, pstats
  prof = cProfile.Profile()
  prof = prof.runctx("real_main()", globals(), locals())
  print "< pre>"
  stats = pstats.Stats(prof).strip_dirs()
  stats.sort_stats("cumulative")
  stats.print_stats('from*')
  print ""

# エントリポイント
if __name__ == "__main__":
  profile_html_main()

そして下記が結果なんですけど、開発環境で試したところ、大体10 ~ 15倍の差で、まーこんなもんかという感じだったのですが、本番環境だと70 ~ 150倍くらいの差がでました。思ったよりも効果があります。

開発環境、本番環境ともに上段がBigTableからのデータ取得、
下段がmemcacheからのデータ取得を1000回繰り返した時の累積時間等になります。

[開発環境]
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  1000    0.011    0.000    0.689    0.001 main.py:30(fromStored)
  1000    0.009    0.000    0.055    0.000 main.py:34(fromCached)
[本番環境]
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  1000    0.017    0.000    8.494    0.008 main.py:34(fromStored)
  1000    0.016    0.000    0.116    0.000 main.py:38(fromCached)

これだと使わざるを得ない雰囲気ですが、BigTableからデータを取得する度にmemcacheみてどうのこうのって面倒なので、データモデルが自動的にmemcacheを使ってくれる仕組みを、作らないと駄目だという事ですか。そうですか。

1 thought on “Google App Engineのmemcacheを試してみた”

Leave a Reply

Your email address will not be published. Required fields are marked *