2

Hello I want to know if in the appengine env the things I did is usefull Because I don't know why this page is very slow.

class Foo(db.Model):
    id = db.StringProperty(multiline=True)
    name = db.StringProperty(multiline=True)
    date = db.DateTimeProperty(auto_now_add=True)
    description = db.TextProperty()    
    carac = db.StringProperty(multiline=True)



class FoosPage(webapp.RequestHandler):
  def get(self):
    foos =  memcache.get("all-foos")
    if foos is None:
        foos = Foo.all()
        size = foo.count()
    else :
        size = len(foo)

    foosTab=[]
    for i in range(size) :
        foosTab.insert(i,foos[i])
        memcache.set("all-foos", foosTab, 60)
    template_values = {
        'foos': foos
            }
    path = os.path.join(os.path.dirname(__file__) + '/../templates/', 'foos.html')
    self.response.out.write(template.render(path, template_values))
4
  • Slow relative to what? Can you provide some timing data for this vs. something similar? Commented Sep 16, 2011 at 17:24
  • how many objects are in foo? are you running this on your dev machine or is it deployed? Does it go faster if you do a fetch(1000) right before you do the call to foo.count()? Commented Sep 16, 2011 at 17:26
  • Hi very slow, for about 50 object 4sec,something strange In local it is faster, @peter I will test for the fetch Commented Sep 16, 2011 at 17:35
  • Have you used appstats? It's designed to answer exactly this sort of question. Commented Sep 19, 2011 at 4:40

2 Answers 2

5

You have the memcache.set() inside the loop. That's a lot of unnecessary traffic to the memcache service. Do it once, after the loop.

Further, the way you have that coded, there's no need for establishing size.

foosTab = []
for foo in foos:
    foosTab.append(foo)

or, more idiomatically

foosTab = [foo for foo in foos]

That'll save you doing a separate count().

Sign up to request clarification or add additional context in comments.

2 Comments

+1, good answer. Also, i usually store the entity keys instead of the hole elements.
Iterating over query results is a bad idea - it results in one RPC call per 20 results.
2

This block of code:

foos =  memcache.get("all-foos")
if foos is None:
    foos = Foo.all()
    size = foo.count()
else :
    size = len(foo)

foosTab=[]
for i in range(size) :
    foosTab.insert(i,foos[i])
    memcache.set("all-foos", foosTab, 60)

Can be replaced with this (much simpler) code:

foos = memcache.get("all-foos")
if not foos:
  foos = Foo.all.fetch(1000) # At most 1000 foos
  memcache.set("all-foos", foos, 60)

Specifically, it avoids the unnecessary call to count() (which issues an expensive RPC for something you'll find out anyway when you fetch the result), it does a single fetch call instead of iterating over the results and fetching in batches of 20, and it only calls memcache set (once!) if it had to fetch the list in the first place.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.