datastore和memcache的性能测试

标签:Google App Engine, Python, 性能

刚才看到GAE论坛里有人问memcache.get()和model.get_by_id()的性能哪个好,按平均一个模型有10个字符串属性来计算,如果差距不是很大的话,是否有必要使用memcache。

正好无事可做,便帮他写了个性能测试(页面不保证长期有效)。
不过发现波动很大,只好随便取了一次结果:
IndexedModel
    Datastore:
        Put time: 0.0358800888062
        Get time: 0.00752592086792
    Memcache:
        Set time: 0.00419998168945
        Get time: 0.00492906570435
    Memcache with entity_pb:
        Set time: 0.00509190559387
        Get time: 0.00729894638062

NonIndexedModel
    Datastore:
        Put time: 0.0374398231506
        Get time: 0.0158569812775
    Memcache:
        Set time: 0.00582790374756
        Get time: 0.00310897827148
    Memcache with entity_pb:
        Set time: 0.0041720867157
        Get time: 0.00335097312927
可以看出memcache还是比datastore快1~5倍的。奇怪的是entity_pb的性能并不好,大概是pickle的时间并不被hook吧。
而不加索引有时比加索引更慢,大概是这个模型只有1个实体,所以生成索引基本不费时间吧。

源码:
from time import time
from google.appengine.api import apiproxy_stub_map, memcache
from google.appengine.ext import db
from google.appengine.datastore import entity_pb

result = {}
models = {}

def createModel(name, indexed, size=10):
  properties = dict([('property_%s' % i, db.StringProperty(indexed=indexed)) for i in xrange(size)])
  models[name] = type(name, (db.Model,), properties)
  return models[name]

IndexedModel = createModel('IndexedModel', True)
NonIndexedModel = createModel('NonIndexedModel', False)

def before_db(service, call, request, response):
  result['DbStart%sTime' % call] = time()

def after_db(service, call, request, response):
  result['DbFinish%sTime' % call] = time()

def before_cache(service, call, request, response):
  result['CacheStart%sTime' % call] = time()

def after_cache(service, call, request, response):
  result['CacheFinish%sTime' % call] = time()

apiproxy_stub_map.apiproxy.GetPreCallHooks().Append('before_db', before_db, 'datastore_v3')
apiproxy_stub_map.apiproxy.GetPostCallHooks().Push('after_db', after_db, 'datastore_v3')
apiproxy_stub_map.apiproxy.GetPreCallHooks().Append('before_cache', before_cache, 'memcache')
apiproxy_stub_map.apiproxy.GetPostCallHooks().Push('after_cache', after_cache, 'memcache')

def test(name, size=10):
  model = models[name]
  values = dict([['property_%s' % i] * 2 for i in xrange(size)])

  print '\n%s\n\tDatastore:' % name
  entity = model(key_name=name, **values)
  entity.put()
  print '\t\tPut time:', result['DbFinishPutTime'] - result['DbStartPutTime']
  assert model.get_by_key_name(name).key().name() == name
  print '\t\tGet time:', result['DbFinishGetTime'] - result['DbStartGetTime']

  print '\tMemcache:'
  memcache.set(name, entity)
  print '\t\tSet time:', result['CacheFinishSetTime'] - result['CacheStartSetTime']
  assert memcache.get(name).key().name() == name
  print '\t\tGet time:', result['CacheFinishGetTime'] - result['CacheStartGetTime']

  print '\tMemcache with entity_pb:'
  memcache.set(name, db.model_to_protobuf(entity).Encode())
  print '\t\tSet time:', result['CacheFinishSetTime'] - result['CacheStartSetTime']
  assert db.model_from_protobuf(entity_pb.EntityProto(memcache.get(name))).key().name() == name
  print '\t\tGet time:', result['CacheFinishGetTime'] - result['CacheStartGetTime']

def main():
  print 'Content-Type: text/plain'

  test('IndexedModel')
  test('NonIndexedModel')

if __name__ == '__main__':
  main()

1条评论 你不来一发么↓ 顺序排列 倒序排列

    向下滚动可载入更多评论,或者点这里禁止自动加载

    想说点什么呢?