High PerformanceWeb Applicationswith Python and TurboGearsAlessandro Molina - @__amol__ - amol@turbogears.org
About me● Python Developer since 2001● Work @ on Python and iOS● development team member since 2.1
Whats this talk about?● Some general rules which apply to any framework● Some quick-wins for TurboGears● Some real cases r...
Raw Speed● People seem obsessed with webservers● The truth is that it doesnt matter so much○ You are not going to serve "H...
About TurboGears● Framework for rapid development encouragingflexibility● Created in 2005, 2.0 was a major rewrite in 2009...
Looking at the codeclass RootController(BaseController):@expose(myproj.templates.movie)@expose(json)@validate({movie:SQLAE...
What it looks like
Features vs Speed● TurboGears is a full-stack framework. That makes itquite slow by default!● The team invested effort to ...
Use only what you need● Only use what you really need. Disabling some featurescan make a big difference:○ full featured ->...
Avoid serving staticsCascading files serving is a common pattern:static_app = StaticURLParser(statics)app = Cascade([stati...
Using Caching● Caching means preorganizing your data the way you aregoing to use it, if you already did that during design...
Use HTML5 & JS● If only small portions of your page change, cache thepage and use JS to perform minor changes.○ Invalidati...
Template Caching● Template caching means prerendering yourtemplate based on controller computation results.● Its common fo...
WikiPage Caching● WikiPage caching is the standard template cachingexample in TurboGears documentation@expose(wikir.templa...
Caching Partials● Case study: Notifications○ Page delivered in 2.16s○ Query took only 2ms○ Most of the work wasactually in...
Entity CachingMap each object to a partial: @entitycached decoratormakes easy to cache each notification by itself.from tg...
Caching can be harmfulIf you content changestoo often, caching onfirst reuqest canactually be harmful.If you have multiple...
Cache Stampede● During football matches there were thousands of usersconstantly pressing "refresh" button to reload page.●...
Proactive Update● To solve cache stampede the cache generation has beenbound to an hook on the article update so it happen...
A real solution● The source of the issue were users pressing "reload" buttonlike theres no tomorrow.● Solutions has been t...
Real-Time Box
Think Different● If you are struggling too much at improving performances,you are probabling doing something your applicat...
Offload Work● The only person that know that something changes is theauthor of the change itself.○ Only update the core ca...
Maste-Slave replication is easy● SQLAlchemy unit of work pattern makes easy forframeworks to do the right thing 90% of the...
Fast enough● Speed should not be your primary focus, but it makessense to care a lot about it, users tend to get frustrate...
Development Tools● Its easy to introduce changes with heavy impacts onperformances without noticing. Development tools can...
Profiling
Keep an eye on your queries
Check even after release● Users use your application more widely than youmight have expected● Fast now, doesnt mean fast f...
There is no silver bullet● Sorry, there is no silver bullet.● Every application is a separate case, general andframework o...
Upcoming SlideShare
Loading in …5
×

PyGrunn2013 High Performance Web Applications with TurboGears

3,779 views
3,632 views

Published on

Users are getting more and more used to fast websites, a second or two is way too much before they leave the page. Since version 2.2 TurboGears has focused on providing more tools to create faster web applications and improving its speed constantly. The latest 2.3 version, the first to support Python3 is up to 4x faster than the previous and provides a great toolset to make fast pages. The talk will focus on showcasing the tools provided by the framework to increase speed of your web applications and provide some tips and tricks to get maximum speed from the framework itself.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,779
On SlideShare
0
From Embeds
0
Number of Embeds
56
Actions
Shares
0
Downloads
13
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

PyGrunn2013 High Performance Web Applications with TurboGears

  1. 1. High PerformanceWeb Applicationswith Python and TurboGearsAlessandro Molina - @__amol__ - amol@turbogears.org
  2. 2. About me● Python Developer since 2001● Work @ on Python and iOS● development team member since 2.1
  3. 3. Whats this talk about?● Some general rules which apply to any framework● Some quick-wins for TurboGears● Some real cases reported● My personal experiences and preferences, feel freeto disagree!
  4. 4. Raw Speed● People seem obsessed with webservers● The truth is that it doesnt matter so much○ You are not going to serve "Hello World"s(If you are asking my personal stack isnginx+mod_wsgi or nginx+Circus-Chaussette-gevent)● Avoid the great idea of serving mostly empty pagesperforming hundreds of ajax requests○ Browser have limited concurrency○ HTTP has overhead○ You will actually slow down things● Learn your framework for real
  5. 5. About TurboGears● Framework for rapid development encouragingflexibility● Created in 2005, 2.0 was a major rewrite in 2009 toembrace the WSGI standard.● Object Dispatch based. Regular expressions can getmessy, write them only when you must.● By default an XML template engine with error detection● Declarative Models with transactional unit of work● Built in Validation, Authentication, Authorization,Caching, Sessions, Migrations, MongoDB Support andmany more.
  6. 6. Looking at the codeclass RootController(BaseController):@expose(myproj.templates.movie)@expose(json)@validate({movie:SQLAEntityConverter(model.Movie)}def movie(self, movie, **kw):return dict(movie=movie, user=request.identity and request.identity[user])Serving /movie/3 as a webpage and /movie/3.json as ajson encoded response
  7. 7. What it looks like
  8. 8. Features vs Speed● TurboGears is a full-stack framework. That makes itquite slow by default!● The team invested effort to constantly speed it up since2.1 release.● Still keeping all thefeatures around hasits price● To cope with thisminimal mode gotintroduced
  9. 9. Use only what you need● Only use what you really need. Disabling some featurescan make a big difference:○ full featured -> ~900 req/sec○ browser language detection -> ~1000 req/sec○ widgets support -> ~1200 req/sec○ sessions -> ~1300 req/sec○ transaction manager -> ~1400 req/sec○ minimal mode -> ~2100 req/secMeasures are on wsgiref, purpose is only to show delta
  10. 10. Avoid serving staticsCascading files serving is a common pattern:static_app = StaticURLParser(statics)app = Cascade([static_app, app])What it is really happening is a lot:○ path gets parsed to avoid ../../../etc/passwd○ path gets checked on file system○ a 404 response is generated○ The 404 response is caught by the Cascademiddleware that forwards the requests to your app
  11. 11. Using Caching● Caching means preorganizing your data the way you aregoing to use it, if you already did that during designphase you are already half done. Let the template driveyour data, not the opposite.● Frameworks usually provide various type of caching.TurboGears specifically provides:○ @cached_property○ tg.cache object for custom caching○ @beaker_cache for controllers caching○ Template Caching○ Entity Caching
  12. 12. Use HTML5 & JS● If only small portions of your page change, cache thepage and use JS to perform minor changes.○ Invalidating your whole cache to say: "Welcome backMister X" is not a great idea.● If you are using Varnish, nginx or any other frontendcache consider using JS+localstorage instead of cookiesfor trivial customizations. Cookies will skip frontendcaching
  13. 13. Template Caching● Template caching means prerendering yourtemplate based on controller computation results.● Its common for template to access related entities,those will be cached for you.● If correctly organized its the caching behavior withbest trade-off○ Simple to implement○ Guarantees correctly updates results● An updated_at field on models is often all you need
  14. 14. WikiPage Caching● WikiPage caching is the standard template cachingexample in TurboGears documentation@expose(wikir.templates.page)@validate({page:SQLAEntityConverter(model.WikiPage, slugified=True)},error_handler=fail_with(404))def _default(self, page, *args, **kw):cache_key = %s-%s % (page.uid,page.updated_at.strftime(%Y%m%d%H%M%S))return dict(wikipage=page, tg_cache={key:cache_key,expire:24*3600,type:memory})
  15. 15. Caching Partials● Case study: Notifications○ Page delivered in 2.16s○ Query took only 2ms○ Most of the work wasactually in renderingeach notification● Caching was useless asnotifications happenedoften, constantly changingcontent.
  16. 16. Entity CachingMap each object to a partial: @entitycached decoratormakes easy to cache each notification by itself.from tgext.datahelpers.caching import entitycached@entitycached(notification)def render_post(notification):return Markup(notification.as_html)● Page with cached notifications is now delivered in 158ms● A single notification can be cached up for days, it willnever change.
  17. 17. Caching can be harmfulIf you content changestoo often, caching onfirst reuqest canactually be harmful.If you have multipleprocesses and a lot ofrequests you can endup having a racecondition on cacheupdate.
  18. 18. Cache Stampede● During football matches there were thousands of usersconstantly pressing "refresh" button to reload page.● Content constantly changed due to match being reportedon real time.● After each update, all the running processes decided thatthe cache was not valid anymore at the same time,starting to regenerate the cache.● Sometimes the content changed even while processes werestill updating cache for previous update.
  19. 19. Proactive Update● To solve cache stampede the cache generation has beenbound to an hook on the article update so it happened onlyonce.● Easy to achieve using Template caching in together withtg.template_render on article id as cache key● SQLALchemy @event.listens_for supports even notificationson relationships, so its reasy to update page cache evenwhen related comments, tags, and so on change.
  20. 20. A real solution● The source of the issue were users pressing "reload" buttonlike theres no tomorrow.● Solutions has been to push updates to the users through abox that updates in real-time.○ No more insane reloads○ Users were actually more satisfied○ Was a lot easier to maintain○ Not only solved match article issues but also reducedthe load on other parts of the website
  21. 21. Real-Time Box
  22. 22. Think Different● If you are struggling too much at improving performances,you are probabling doing something your application is notmeant to do.● Lesson learnt?○ Soccer fans are eager for updates (no... for real!)○ There is only one thing that gets more visits than afootball match: Rumors on football players trading
  23. 23. Offload Work● The only person that know that something changes is theauthor of the change itself.○ Only update the core cache to provide author with animmediate feedback○ Dont be afraid of updating related cachesasynchronously. Author usually understands that itmight take some time before his changes propagateand other users dont know that a change happenedyet.● You can often provide an answer to user with little instantcomputation, messages and notifications are a typicalexample.
  24. 24. Maste-Slave replication is easy● SQLAlchemy unit of work pattern makes easy forframeworks to do the right thing 90% of the time○ Read from slaves unless we are flushing the session● Wont require changes to your code for most common cases● Exceptions are as easy as @with_engine(master)● As easy assqlalchemy.master.url = mysql://masterhost/dbnamesqlalchemy.slaves.slave1.url = mysql://slavehost/dbnamesqlalchemy.slaves.slave2.url = mysql://slavehost/dbname
  25. 25. Fast enough● Speed should not be your primary focus, but it makessense to care a lot about it, users tend to get frustratedby slow responses.● New Relic App Speed Index reports an average of 5.0seconds of response time for accepted experience.● That is End-User time, not request time, to achieve 5seconds you have to aim a lot lower● Mean Opinion Score degrades quickly when surpassing200ms. Less than 200ms is perceived as "right now".http://newrelic.com/ASI
  26. 26. Development Tools● Its easy to introduce changes with heavy impacts onperformances without noticing. Development tools canhelp keeping under control impact of changes● The DebugBar provides core utilities to track yourapplication speed while developing:○ Controller Profiling○ Template & Partials Timing○ Query Reporting○ Query Logging for AJAX/JSON requests
  27. 27. Profiling
  28. 28. Keep an eye on your queries
  29. 29. Check even after release● Users use your application more widely than youmight have expected● Fast now, doesnt mean fast forever. Like test unitsavoid breaking things, rely on a speed feedback tokeep acceptable speed.● Keep your Apdex T index updated, userexpectations evolve!
  30. 30. There is no silver bullet● Sorry, there is no silver bullet.● Every application is a separate case, general andframework optimizations can usually provide littlebenefit when compared to domain specificoptimizations● Understanding how users interact with your applicationis the golden rule of optimization● Dont understimate how its easy to do something reallyslow unconsciously: development tools can helpcatching those.

×