Quem espera sempre cansa

22
Quem espera sempre Quem espera sempre cansa cansa Chamadas assíncronas ao Datastore Plus Chamadas assíncronas ao Datastore Plus

description

Apresentação feita na Pythonbrasil[7], em setembro de 2011, sobre a API assíncrona de acesso a dados do Google App Engine

Transcript of Quem espera sempre cansa

Page 1: Quem espera sempre cansa

Quem espera sempre Quem espera sempre cansacansaChamadas assíncronas ao Datastore PlusChamadas assíncronas ao Datastore Plus

Page 2: Quem espera sempre cansa

As coisas que você deveria As coisas que você deveria sabersaber•toplevels/taskletstoplevels/tasklets

•futuresfutures

•yield (você vai fazer muitos generators)yield (você vai fazer muitos generators)

•você vai usar raise em vez de return (às vezes) você vai usar raise em vez de return (às vezes)

•não são threadsnão são threads

•..._async..._async

•a API de query mudoua API de query mudou

•Um uso insanamente legal de override de comparadoresUm uso insanamente legal de override de comparadores

Page 3: Quem espera sempre cansa

Como se faziaComo se fazia

class Fact(model.Model):class Fact(model.Model): text = model.TextProperty()    text = model.TextProperty()            rating = model.FloatProperty(default = 400.)rating = model.FloatProperty(default = 400.) random_index = model.ComputedProperty(    random_index = model.ComputedProperty(   

                lambda self : random.randint(0,lambda self : random.randint(0,                         sys.maxint))sys.maxint))

(...)(...)

for i in range(10):for i in range(10): Fact(text = 'Fact %d' % i).put()    Fact(text = 'Fact %d' % i).put()   

Page 4: Quem espera sempre cansa

Digressão: _ah/statsDigressão: _ah/stats

•Um bom jeito de entender o desempenho de suas aplicaçõesUm bom jeito de entender o desempenho de suas aplicações

•Se você estiver fazendo algo errado, vai ficar óbvioSe você estiver fazendo algo errado, vai ficar óbvio

Fácil de ligar no app.yaml:Fácil de ligar no app.yaml:

builtins:builtins:(...)(...)- appstats: on- appstats: on

Page 5: Quem espera sempre cansa

Como o código anterior se Como o código anterior se comportacomporta

Page 6: Quem espera sempre cansa

… … e no servidore no servidor

Page 7: Quem espera sempre cansa

O jeito assíncronoO jeito assíncrono

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())[ f.get_result() for f in futures ][ f.get_result() for f in futures ]

  

Dá a oportunidade de agregar os puts em uma grande operação com o Dá a oportunidade de agregar os puts em uma grande operação com o datastore (sem que tenhamos que nos preocupar muito com isso)datastore (sem que tenhamos que nos preocupar muito com isso)

Page 8: Quem espera sempre cansa

_ah/stats_ah/stats

Page 9: Quem espera sempre cansa

No servidorNo servidor

Page 10: Quem espera sempre cansa

Fazendo melhor: Fazendo melhor: toplevel/tasklettoplevel/[email protected]@context.toplevel

(decorando algo que vai chamar o tasklet abaixo)(decorando algo que vai chamar o tasklet abaixo)

  

@[email protected]

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 permite que o event loop do toplevel gerencie generators que estejam esperando por uma Yield permite que o event loop do toplevel gerencie generators que estejam esperando por uma resposta do servidorresposta do servidor

Page 11: Quem espera sempre cansa

… … ainda melhorainda melhor

@[email protected]

(decorando o que chama o tasklet)(decorando o que chama o tasklet)

@[email protected]

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)

Porque quando você retorna o último resultado de um iterador, você deve lançar uma exceçãoPorque quando você retorna o último resultado de um iterador, você deve lançar uma exceção

Page 12: Quem espera sempre cansa

ab -n 10000 -c 50 (síncrono)ab -n 10000 -c 50 (síncrono)

Connection Times (ms)Connection Times (ms) min mean[+/-sd] median max                   min mean[+/-sd] median max                  

Connect: 140 159 69.1 145 976                  Connect: 140 159 69.1 145 976                  Processing: 338 7408 5452.2 6231 46247        Processing: 338 7408 5452.2 6231 46247        Waiting: 338 7407 5452.2 6230 46247           Waiting: 338 7407 5452.2 6230 46247           Total: 482 7567 5442.4 6377 46401             Total: 482 7567 5442.4 6377 46401             

Percentage of the requests served within a certain time (ms)Percentage of the requests served within a certain time (ms) 50% 6377     50% 6377     66% 8540     66% 8540     75% 10131    75% 10131    80% 11068    80% 11068    90% 13419    90% 13419    95% 16077    95% 16077    98% 23883    98% 23883    99% 30173    99% 30173   100% 46401 (longest request)   100% 46401 (longest request)   

Page 13: Quem espera sempre cansa

ab -n 10000 -c 50 ab -n 10000 -c 50 (assíncrono)(assíncrono)Connection Times (ms)Connection Times (ms)

min mean[+/-sd] median max                   min mean[+/-sd] median max                  Connect: 140 669 1375.6 151 21193              Connect: 140 669 1375.6 151 21193              Processing: 189 338 300.0 256 15320           Processing: 189 338 300.0 256 15320           Waiting: 189 335 243.7 255 4143               Waiting: 189 335 243.7 255 4143               Total: 332 1007 1407.6 438 21450               Total: 332 1007 1407.6 438 21450               

Percentage of the requests served within a certain time (ms)Percentage of the requests served within a certain time (ms) 50% 438      50% 438      66% 565      66% 565      75% 732      75% 732      80% 1272     80% 1272     90% 3372     90% 3372     95% 3456     95% 3456     98% 3762     98% 3762     99% 9366     99% 9366    100% 21450 (longest request)   100% 21450 (longest request)   

Page 14: Quem espera sempre cansa

Qual a diferença?Qual a diferença?

Page 15: Quem espera sempre cansa

ErradoErrado

for f in Fact.query():for f in Fact.query():

f.rating = random.normalvariate(400, 20)f.rating = random.normalvariate(400, 20)

f.put() f.put()

Page 16: Quem espera sempre cansa

Porque errado?Porque errado?

Page 17: Quem espera sempre cansa

Certo: map_asyncCerto: map_async

@[email protected] randomize_rating(f):def randomize_rating(f): f.rating = random.normalvariate(400, 20)  f.rating = random.normalvariate(400, 20)  raise tasklets.Return(f.put_async())  raise tasklets.Return(f.put_async()) 

@[email protected] randomize_all():def randomize_all(): Fact.query().map_async(randomize_rating)  Fact.query().map_async(randomize_rating) 

Page 18: Quem espera sempre cansa

Certo: map_asyncCerto: map_async

Page 19: Quem espera sempre cansa

O que mais eu preciso O que mais eu preciso saber?saber?•context e seu event loopcontext e seu event loop

•cachescaches

•novos tipos de dadosnovos tipos de dados

•novos nomes para os tipos conhecidosnovos nomes para os tipos conhecidos

•repeated = True repeated = True

•StructuredProperty, LocalStructuredPropertyStructuredProperty, LocalStructuredProperty

•compresscompress

•tempos de resposta mais curtos e melhor uso das instânciastempos de resposta mais curtos e melhor uso das instâncias

Page 20: Quem espera sempre cansa

Onde eu encontro?Onde eu encontro?

•Builds oficiaisBuilds oficiais

•http://code.google.com/p/appengine-ndb-experiment/downloads/listhttp://code.google.com/p/appengine-ndb-experiment/downloads/list

•"Bleeding" edge "Bleeding" edge

•hg clone https://code.google.com/p/appengine-ndb-experiment/hg clone https://code.google.com/p/appengine-ndb-experiment/

•Versão 0.7 foi lançada ontemVersão 0.7 foi lançada ontem

Page 21: Quem espera sempre cansa

Para saber maisPara saber mais

•Documentação:Documentação:

http://code.google.com/p/appengine-ndb-experiment/http://code.google.com/p/appengine-ndb-experiment/

•Google Group:Google Group:

http://groups.google.com/group/appengine-ndb-discuss/http://groups.google.com/group/appengine-ndb-discuss/

Page 22: Quem espera sempre cansa

AgradecimentosAgradecimentos

Agradecimentos são devidos ao pessoal do grupo appengine-ndb-discuss, Agradecimentos são devidos ao pessoal do grupo appengine-ndb-discuss, em especial ao Guido e ao Vladimir, que sugeriram assuntos e me em especial ao Guido e ao Vladimir, que sugeriram assuntos e me apontaram na direção certa.apontaram na direção certa.