•futures futures •yield (you are going to build lots of generators) yield (you are going to build lots of generators) •you'll use yield instead of return (most of the time) you'll use yield instead of return (most of the time) •don't think about threads don't think about threads •..._async ..._async •the query API changes the query API changes •an insanely great use for comparator overrides an insanely great use for comparator overrides
performance of your apps A good way to understand the performance of your apps •If you are doing something wrong, it'll become obvious If you are doing something wrong, it'll become obvious Easy to enable on app.yaml: Easy to enable on app.yaml: builtins: builtins: (...) (...) - appstats: on - appstats: on
= [] for i in range(10): for i in range(10): futures.append(Fact(text = 'Fact %d' % \ futures.append(Fact(text = 'Fact %d' % \ i).put_async()) i).put_async()) [ f.get_result() for f in futures ] [ f.get_result() for f in futures ] Gives the opportunity to aggregate puts into one large datastore Gives the opportunity to aggregate puts into one large datastore operation (and we don't have to worry about it) operation (and we don't have to worry about it)
a request handler – that will call the following tasklet) (decorating something – usually a request handler – that will call the following tasklet) @tasklets.tasklet @tasklets.tasklet def init_facts() def init_facts() futures = [] futures = [] for i in range(10): for i in range(10): futures.append(Fact(text = 'Fact %d' % \ futures.append(Fact(text = 'Fact %d' % \ i).put_async()) i).put_async()) yield futures yield futures Yield allows the toplevel event loop to manage other generators making asynchronous calls Yield allows the toplevel event loop to manage other generators making asynchronous calls
handler) (decorating your handler) @tasklets.tasklet @tasklets.tasklet def init_facts() def init_facts() Futures = [] Futures = [] for i in range(10): for i in range(10): futures.append(Fact(text = 'Fact %d' \ futures.append(Fact(text = 'Fact %d' \ % i).put_async()) % i).put_async()) raise tasklets.Return(futures) raise tasklets.Return(futures) Because it's considered polite to raise things when a generator has nothing else to generate Because it's considered polite to raise things when a generator has nothing else to generate
•context and its event loop context and its event loop •caches caches •new datatypes new datatypes •new names for old types new names for old types •repeated = True repeated = True •StructuredProperty, LocalStructuredProperty StructuredProperty, LocalStructuredProperty •compress compress •shorter response times and more efficient instance usage shorter response times and more efficient instance usage
on the appengine-ndb-discuss 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 group, in special to Guido and Vladimir, whose suggestions pointed me on the right direction. the right direction.