gae アプリ 開発メモ

Google App Engine アプリの開発メモ / 言語: python, javascript / ビギナー

DataStoreのorder()のあり/なしで速度を比べてみた

sortedとDataStoreのorder()の速度を比べてみたでは、order()しない読み取り速度を計測していなかった。
そんな調査結果で開発方針を判断しちゃマズいかな、と思い再度計測。

ソース

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import util
import StringIO
import timeit
import random

class Person(db.Model):
    name = db.StringProperty(required=True, indexed=False)
    age = db.IntegerProperty(required=True, indexed=True)

class Person2(db.Model):
    name = db.StringProperty(required=True, indexed=False)
    age = db.IntegerProperty(required=True, indexed=False)

class RootHandler(webapp.RequestHandler):
    def get(self):
        output = StringIO.StringIO()

        times = 3
        self.in_memory_sort(output, times)
        self.datastore_sort(output, times)
        self.datastore(output, times)

        self.response.out.write(output.getvalue())
        output.close()

    def in_memory_sort(self, output, times):
        t = timeit.Timer(
            setup = """
import random

persons = {}
for n in range(1000):
    persons['item' + str(n)] = {
        'name': 'name' + str(n),
        'age': random.randint(1, 80)
    }
            """,
            stmt = """
result = sorted(persons.itervalues(), key = lambda person: person['age'])
            """
        )
        output.write("in_memory_sort = %.5f usec/pass<br>" % (1000000 * min(t.repeat(repeat = times, number=1)) / times))

    def datastore_sort(self, output, times):
        # データを一旦消去
        keys = Person.all(keys_only = True)
        db.delete(keys)

        persons = []
        for n in range(1000):
            persons.append(Person(name = 'name' + str(n), age = random.randint(1, 80)))
        db.put(persons)

        t = timeit.Timer(
            setup = """
from google.appengine.ext import db

class Person(db.Model):
    name = db.StringProperty(required=True, indexed=False)
    age = db.IntegerProperty(required=True, indexed=True)
            """,
            stmt = """
persons = Person.all().order('age')
result = [person for person in persons]
            """
        )
        output.write("datastore_sort = %.5f usec/pass<br>" % (1000000 * min(t.repeat(repeat = times, number=1)) / times))

    def datastore(self, output, times):
        # データを一旦消去
        keys = Person2.all(keys_only = True)
        db.delete(keys)

        persons = []
        for n in range(1000):
            persons.append(Person2(name = 'name' + str(n), age = random.randint(1, 80)))
        db.put(persons)

        t = timeit.Timer(
            setup = """
from google.appengine.ext import db

class Person2(db.Model):
    name = db.StringProperty(required=True, indexed=False)
    age = db.IntegerProperty(required=True, indexed=False)
            """,
            stmt = """
persons = Person2.all()
result = [person for person in persons]
            """
        )
        output.write("datastore&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= %.5f usec/pass<br>" % (1000000 * min(t.repeat(repeat = times, number=1)) / times))

def main():
    global request_handlers

    application = webapp.WSGIApplication([('/', RootHandler)], debug=True)
    util.run_wsgi_app(application)

if __name__ == '__main__':
    main()

結果

# 1回目
in_memory_sort =     160.46158 usec/pass
datastore_sort = 153,583.24278 usec/pass
datastore      = 155,220.48863 usec/pass

# 2回目
in_memory_sort =     160.33937 usec/pass
datastore_sort = 153,148.05337 usec/pass
datastore      = 151,476.71095 usec/pass

うーん。
order()なしの速度が安定しないけど、要するに共に150msec/1000件くらいで大差がないってことみたい。
で、sorted()の実行速度はDataStoreのやりとりに比べれば、無視できるものと解釈していいのかな。

ということは

  • DataStoreとのやりとりは最小に。
  • DataStoreにはソート目的のインデックスはWriteOpsを増加させるだけのメリットがない

ってことだな。

これだけでも収穫。