My apps all use webkit/0.96 django templates. Cold start times are <10ms for handlers that don't use templates and closer to 50ms for handlers that do.
On Mar 25, 2:50 pm, cz <czer...@gmail.com> wrote: > Django is pretty resource intensive what with all the middleware and > template processing so it makes sense that a more minimal app would be > much faster. As for using .96 my guess is that you'd save ~180ms by > skipping zipimport and a fair bit more by not having to compile all > the imports (assuming the default GAE libraries are *.pyc). I'm still > kind of a Python newbie (old Java/C++ prgmr) so this explanation might > be completely wrong. Please post your results if you try it out! > You're probably right about memcache, I was trying to figure out where > all that extra response time (not startup time) came from on a cold > start (500ms cold vs 10ms warm). Maybe it's just the Python > interpreter having to compile all the response processing code. > My app serves uploaded images and other longer term datastore > blobjects, and using a Django view to serve them up is super slow when > cold. I'm thinking of using the lighter weight webapp framework just > to serve this kind of content. I didn't want to use more than one > framework for the app, but it's probably worth it in this case. For > lower traffic apps anyway. > regards, > - Claude > > On Mar 24, 11:58 pm, Robert <rjaa...@gmail.com> wrote: > > > Useful stuff, thanks! > > > Just yesterday I was looking into this same issue. I was wondering if > > plain 0.96 Django use (without appengine helper or patch) would be > > significantly faster, and your post really makes me want to try that. > > I changed the handling of a single url in my app to be a "plain" GAE > > (webapp.WSGIApplication) handler. This URL was for a cron-triggered > > task that runs every minute. In the absence of other traffic this > > resulted in a cold start every minute and this processing this trivial > > request now only uses approx. 200 ms CPU quota. When it was part of > > the main Django app, it would take over 2000 ms CPU quota. > > > BTW I'm fairly convinced that memcached data doesn't get flushed out. > > > On Mar 24, 6:27 am, cz <czer...@gmail.com> wrote: > > > > I added some timing code to see how expensive a cold app startup is. > > > This is a Django1.x app so YMMV. > > > > The typical numbers are: > > > > Zipimport of Django: 180ms > > > Appengine-django-helper monkeypatching: 430ms > > > Misc imports, app-specific patching, etc: 20ms > > > ------------------------------------------------------------------------ > > > Total app startup: 630ms > > > > This is for startup only, not the time it takes to then process the > > > request, so this is a fixed expense. Also, this is real time not cpu > > > quota time which is much higher. > > > > The biggest hog is the django-helper monkeypatcher. I'm eventually > > > going to try appengine-patch with the hope that it will be faster. > > > > Additionally, on a cold startup my app processes a request in about > > > 500ms, but on a warm app it only takes 10ms due to some aggressive > > > caching. I think that when all your app instances expire so does all > > > it's memcached data. > > > > If anybody has done something similar and found different numbers > > > please post the results and let me know what I did wrong. > > > > Here's the main.py I'm using in case you'd like to point out any > > > errors in my methodology: > > > ---------------------------------------- > > > > from time import clock > > > t_main_start = clock() > > > > # Standard Python imports. > > > import os > > > import sys > > > import logging > > > import settings > > > > logging.getLogger().setLevel(settings.LOGGING_LEVEL) > > > > # Fix (hack) for missing unlink > > > if os.name == 'nt': > > > os.unlink = lambda: None > > > > # TODO (after gathering stats): remove this since appengine_django > > > does it for us > > > # Import Django 1.x from a zipfile and get rid of v.96. > > > t_zip_start = clock() > > > django_zip_path = os.path.abspath('django.zip') > > > if django_zip_path not in sys.path: > > > sys.path.insert(0, django_zip_path) > > > for k in [k for k in sys.modules if k.startswith('django')]: > > > del sys.modules[k] > > > # TODO (after gathering stats): remove this line > > > from django import template # provoke django zipimport > > > t_zip = (clock() - t_zip_start) * 1000 > > > > # Install appengine_django. Patches Django 1.x for use with GAE > > > t_patch_start = clock() > > > from appengine_django import InstallAppengineHelperForDjango > > > InstallAppengineHelperForDjango() > > > t_patch = (clock() - t_patch_start) * 1000 > > > > # Patch the appengine_django patch to fix User object creation > > > # Remove this when switching to appengine-patch > > > from monkeypatch import patch > > > patch() > > > > # Google App Engine imports. > > > from google.appengine.ext.webapp import util > > > > # Import the part of Django that we use here. > > > import django.core.handlers.wsgi > > > > t_main = (clock() - t_main_start) * 1000 > > > logging.info('[TIME] main.py startup: %.1fms (zipimport: %.1fms, > > > appengine-django: %.1fms)' % (t_main,t_zip,t_patch)) > > > > def real_main(): > > > t_request_start = clock() > > > # Create a Django application for WSGI. > > > application = django.core.handlers.wsgi.WSGIHandler() > > > > # Run the WSGI CGI handler with that application. > > > util.run_wsgi_app(application) > > > t_request = (clock() - t_request_start) * 1000 > > > logging.info('[TIME] request: %.1fms' % t_request) > > > > def profile_main(): > > > # Rename this to main() for profiling > > > import cProfile, pstats > > > prof = cProfile.Profile() > > > prof = prof.runctx("real_main()", globals(), locals()) > > > print "<pre>" > > > stats = pstats.Stats(prof) > > > stats.sort_stats("time") # Or cumulative > > > stats.print_stats(80) # 80 = how many to print > > > # The rest is optional. > > > #stats.print_callees() > > > #stats.print_callers() > > > print "</pre>" > > > > main = real_main > > > > if __name__ == '__main__': > > > main() --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Google App Engine" group. To post to this group, send email to google-appengine@googlegroups.com To unsubscribe from this group, send email to google-appengine+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en -~----------~----~----~----~------~----~------~--~---