Boost Fertility New Invention Ups Success Rates.pdf
Boredom comes to_those_who_wait
1. Boredom comes to those
who wait
Asynchronous calls to Datastore Plus
2. What you should know
•toplevels/tasklets
•futures
•yield (you are going to build lots of generators)
•you'll use yield instead of return (most of the time)
•don't think about threads
•..._async
•the query API changes
•an insanely great use for comparator overrides
3. How it used to be done
class Fact(model.Model):
text = model.TextProperty()
rating = model.FloatProperty(default = 400.)
random_index = model.ComputedProperty(
lambda self : random.randint(0,
sys.maxint))
(...)
for i in range(10):
Fact(text = 'Fact %d' % i).put()
4. Digression: _ah/stats
•A good way to understand the performance of your apps
•If you are doing something wrong, it'll become obvious
Easy to enable on app.yaml:
builtins:
(...)
- appstats: on
7. The asynchronous way
futures = []
for i in range(10):
futures.append(Fact(text = 'Fact %d' %
i).put_async())
[ f.get_result() for f in futures ]
Gives the opportunity to aggregate puts into one large datastore
operation (and we don't have to worry about it)
10. Better: toplevel/tasklet
@context.toplevel
(decorating something – usually a request handler – that will call the following tasklet)
@tasklets.tasklet
def init_facts()
futures = []
for i in range(10):
futures.append(Fact(text = 'Fact %d' %
i).put_async())
yield futures
Yield allows the toplevel event loop to manage other generators making asynchronous calls
11. … even better
@context.toplevel
(decorating your handler)
@tasklets.tasklet
def init_facts()
Futures = []
for i in range(10):
futures.append(Fact(text = 'Fact %d'
% i).put_async())
raise tasklets.Return(futures)
Because it's considered polite to raise things when a generator has nothing else to generate
12. ab -n 10000 -c 50 (synchronous)
Connection Times (ms)
min mean[+/-sd] median max
Connect: 140 159 69.1 145 976
Processing: 338 7408 5452.2 6231 46247
Waiting: 338 7407 5452.2 6230 46247
Total: 482 7567 5442.4 6377 46401
Percentage of the requests served within a certain time (ms)
50% 6377
66% 8540
75% 10131
80% 11068
90% 13419
95% 16077
98% 23883
99% 30173
100% 46401 (longest request)
13. ab -n 10000 -c 50 (asynchronous)
Connection Times (ms)
min mean[+/-sd] median max
Connect: 140 669 1375.6 151 21193
Processing: 189 338 300.0 256 15320
Waiting: 189 335 243.7 255 4143
Total: 332 1007 1407.6 438 21450
Percentage of the requests served within a certain time (ms)
50% 438
66% 565
75% 732
80% 1272
90% 3372
95% 3456
98% 3762
99% 9366
100% 21450 (longest request)
19. What else should I know?
•context and its event loop
•caches
•new datatypes
•new names for old types
•repeated = True
•StructuredProperty, LocalStructuredProperty
•compress
•shorter response times and more efficient instance usage
20. Where do I find it?
•official builds
•http://code.google.com/p/appengine-ndb-experiment/downloads/list
•"Bleeding" edge
•hg clone https://code.google.com/p/appengine-ndb-experiment/
•version 0.7 released yesterday
21. To know more
•documentation:
http://code.google.com/p/appengine-ndb-experiment/
•Google group:
http://groups.google.com/group/appengine-ndb-discuss/
22. Thanks
Thanks to the fine people who hang out on the appengine-ndb-discuss
group, in special to Guido and Vladimir, whose suggestions pointed me on
the right direction.