SlideShare ist ein Scribd-Unternehmen logo
1 von 30
Downloaden Sie, um offline zu lesen
High Performance
Web Applications
with Python and TurboGears
Alessandro Molina - @__amol__ - amol@turbogears.org
About me
● Python Developer since 2001
● Work @ on Python and iOS
● development team member since 2.1
What's 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 free
to disagree!
Raw Speed
● People seem obsessed with webservers
● The truth is that it doesn't matter so much
○ You are not going to serve "Hello World"s
(If you are asking my personal stack is
nginx+mod_wsgi or nginx+Circus-Chaussette-gevent)
● Avoid the great idea of serving mostly empty pages
performing hundreds of ajax requests
○ Browser have limited concurrency
○ HTTP has overhead
○ You will actually slow down things
● Learn your framework for real
About TurboGears
● Framework for rapid development encouraging
flexibility
● Created in 2005, 2.0 was a major rewrite in 2009 to
embrace the WSGI standard.
● Object Dispatch based. Regular expressions can get
messy, 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 and
many more.
Looking at the code
class 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 a
json encoded response
What it looks like
Features vs Speed
● TurboGears is a full-stack framework. That makes it
quite slow by default!
● The team invested effort to constantly speed it up since
2.1 release.
● Still keeping all the
features around has
its price
● To cope with this
minimal mode got
introduced
Use only what you need
● Only use what you really need. Disabling some features
can 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/sec
Measures are on wsgiref, purpose is only to show delta
Avoid serving statics
Cascading 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 Cascade
middleware that forwards the requests to your app
Using Caching
● Caching means preorganizing your data the way you are
going to use it, if you already did that during design
phase you are already half done. Let the template drive
your 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
Use HTML5 & JS
● If only small portions of your page change, cache the
page and use JS to perform minor changes.
○ Invalidating your whole cache to say: "Welcome back
Mister X" is not a great idea.
● If you are using Varnish, nginx or any other frontend
cache consider using JS+localstorage instead of cookies
for trivial customizations. Cookies will skip frontend
caching
Template Caching
● Template caching means prerendering your
template based on controller computation results.
● It's common for template to access related entities,
those will be cached for you.
● If correctly organized it's the caching behavior with
best trade-off
○ Simple to implement
○ Guarantees correctly updates results
● An updated_at field on models is often all you need
WikiPage Caching
● WikiPage caching is the standard template caching
example 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'})
Caching Partials
● Case study: Notifications
○ Page delivered in 2.16s
○ Query took only 2ms
○ Most of the work was
actually in rendering
each notification
● Caching was useless as
notifications happened
often, constantly changing
content.
Entity Caching
Map each object to a partial: @entitycached decorator
makes 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 will
never change.
Caching can be harmful
If you content changes
too often, caching on
first reuqest can
actually be harmful.
If you have multiple
processes and a lot of
requests you can end
up having a race
condition on cache
update.
Cache Stampede
● During football matches there were thousands of users
constantly pressing "refresh" button to reload page.
● Content constantly changed due to match being reported
on real time.
● After each update, all the running processes decided that
the cache was not valid anymore at the same time,
starting to regenerate the cache.
● Sometimes the content changed even while processes were
still updating cache for previous update.
Proactive Update
● To solve cache stampede the cache generation has been
bound to an hook on the article update so it happened only
once.
● Easy to achieve using Template caching in together with
tg.template_render on article id as cache key
● SQLALchemy @event.listens_for supports even notifications
on relationships, so it's reasy to update page cache even
when related comments, tags, and so on change.
A real solution
● The source of the issue were users pressing "reload" button
like there's no tomorrow.
● Solutions has been to push updates to the users through a
box 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 reduced
the load on other parts of the website
Real-Time Box
Think Different
● If you are struggling too much at improving performances,
you are probabling doing something your application is not
meant to do.
● Lesson learnt?
○ Soccer fans are eager for updates (no... for real!)
○ There is only one thing that gets more visits than a
football match: Rumors on football players trading
Offload Work
● The only person that know that something changes is the
author of the change itself.
○ Only update the core cache to provide author with an
immediate feedback
○ Don't be afraid of updating related caches
asynchronously. Author usually understands that it
might take some time before his changes propagate
and other users don't know that a change happened
yet.
● You can often provide an answer to user with little instant
computation, messages and notifications are a typical
example.
Maste-Slave replication is easy
● SQLAlchemy unit of work pattern makes easy for
frameworks to do the right thing 90% of the time
○ Read from slaves unless we are flushing the session
● Won't require changes to your code for most common cases
● Exceptions are as easy as @with_engine('master')
● As easy as
sqlalchemy.master.url = mysql://masterhost/dbname
sqlalchemy.slaves.slave1.url = mysql://slavehost/dbname
sqlalchemy.slaves.slave2.url = mysql://slavehost/dbname
Fast enough
● Speed should not be your primary focus, but it makes
sense to care a lot about it, users tend to get frustrated
by slow responses.
● New Relic App Speed Index reports an average of 5.0
seconds of response time for accepted experience.
● That is End-User time, not request time, to achieve 5
seconds you have to aim a lot lower
● Mean Opinion Score degrades quickly when surpassing
200ms. Less than 200ms is perceived as "right now".
http://newrelic.com/ASI
Development Tools
● It's easy to introduce changes with heavy impacts on
performances without noticing. Development tools can
help keeping under control impact of changes
● The DebugBar provides core utilities to track your
application speed while developing:
○ Controller Profiling
○ Template & Partials Timing
○ Query Reporting
○ Query Logging for AJAX/JSON requests
Profiling
Keep an eye on your queries
Check even after release
● Users use your application more widely than you
might have expected
● Fast now, doesn't mean fast forever. Like test units
avoid breaking things, rely on a speed feedback to
keep acceptable speed.
● Keep your Apdex T index updated, user
expectations evolve!
There is no silver bullet
● Sorry, there is no silver bullet.
● Every application is a separate case, general and
framework optimizations can usually provide little
benefit when compared to domain specific
optimizations
● Understanding how users interact with your application
is the golden rule of optimization
● Don't understimate how its easy to do something really
slow unconsciously: development tools can help
catching those.

Weitere ähnliche Inhalte

Was ist angesagt?

Automated Web App Performance Testing Using WebDriver
Automated Web App Performance Testing Using WebDriverAutomated Web App Performance Testing Using WebDriver
Automated Web App Performance Testing Using WebDriver
seleniumconf
 
Performance Metrics in a Day with Selenium
Performance Metrics in a Day with SeleniumPerformance Metrics in a Day with Selenium
Performance Metrics in a Day with Selenium
Mark Watson
 
Web performance testing with web driver
Web performance testing with web driverWeb performance testing with web driver
Web performance testing with web driver
Michael Klepikov
 
Essential Javascript -- A Javascript <b>Tutorial</b>
Essential Javascript -- A Javascript <b>Tutorial</b>Essential Javascript -- A Javascript <b>Tutorial</b>
Essential Javascript -- A Javascript <b>Tutorial</b>
tutorialsruby
 

Was ist angesagt? (18)

Use Xdebug to profile PHP
Use Xdebug to profile PHPUse Xdebug to profile PHP
Use Xdebug to profile PHP
 
Single page apps with drupal 7
Single page apps with drupal 7Single page apps with drupal 7
Single page apps with drupal 7
 
Html5 web storage
Html5 web storageHtml5 web storage
Html5 web storage
 
Varnish Cache and its usage in the real world!
Varnish Cache and its usage in the real world!Varnish Cache and its usage in the real world!
Varnish Cache and its usage in the real world!
 
Automated Web App Performance Testing Using WebDriver
Automated Web App Performance Testing Using WebDriverAutomated Web App Performance Testing Using WebDriver
Automated Web App Performance Testing Using WebDriver
 
Javascript why what and how
Javascript why what and howJavascript why what and how
Javascript why what and how
 
Altitude SF 2017: Reddit - How we built and scaled r/place
Altitude SF 2017: Reddit - How we built and scaled r/placeAltitude SF 2017: Reddit - How we built and scaled r/place
Altitude SF 2017: Reddit - How we built and scaled r/place
 
How to investigate and recover from a security breach in WordPress
How to investigate and recover from a security breach in WordPressHow to investigate and recover from a security breach in WordPress
How to investigate and recover from a security breach in WordPress
 
More efficient, usable web
More efficient, usable webMore efficient, usable web
More efficient, usable web
 
Performance Metrics in a Day with Selenium
Performance Metrics in a Day with SeleniumPerformance Metrics in a Day with Selenium
Performance Metrics in a Day with Selenium
 
Varnish Cache
Varnish CacheVarnish Cache
Varnish Cache
 
Automated Testing with Google Chrome - WebDriver- ChromeDriver
Automated Testing with Google Chrome - WebDriver- ChromeDriverAutomated Testing with Google Chrome - WebDriver- ChromeDriver
Automated Testing with Google Chrome - WebDriver- ChromeDriver
 
The MEAN Stack: MongoDB, ExpressJS, AngularJS and Node.js
The MEAN Stack: MongoDB, ExpressJS, AngularJS and Node.jsThe MEAN Stack: MongoDB, ExpressJS, AngularJS and Node.js
The MEAN Stack: MongoDB, ExpressJS, AngularJS and Node.js
 
Web performance testing with web driver
Web performance testing with web driverWeb performance testing with web driver
Web performance testing with web driver
 
HTML 5
HTML 5HTML 5
HTML 5
 
Essential Javascript -- A Javascript <b>Tutorial</b>
Essential Javascript -- A Javascript <b>Tutorial</b>Essential Javascript -- A Javascript <b>Tutorial</b>
Essential Javascript -- A Javascript <b>Tutorial</b>
 
Node.js primer
Node.js primerNode.js primer
Node.js primer
 
20 tips for website performance
20 tips for website performance20 tips for website performance
20 tips for website performance
 

Ähnlich wie PyGrunn2013 High Performance Web Applications with TurboGears

Intro to XPages for Administrators (DanNotes, November 28, 2012)
Intro to XPages for Administrators (DanNotes, November 28, 2012)Intro to XPages for Administrators (DanNotes, November 28, 2012)
Intro to XPages for Administrators (DanNotes, November 28, 2012)
Per Henrik Lausten
 
kranonit S06E01 Игорь Цинько: High load
kranonit S06E01 Игорь Цинько: High loadkranonit S06E01 Игорь Цинько: High load
kranonit S06E01 Игорь Цинько: High load
Krivoy Rog IT Community
 
Tech meetup: Web Applications Performance
Tech meetup: Web Applications PerformanceTech meetup: Web Applications Performance
Tech meetup: Web Applications Performance
Santex Group
 

Ähnlich wie PyGrunn2013 High Performance Web Applications with TurboGears (20)

Web performance optimization - MercadoLibre
Web performance optimization - MercadoLibreWeb performance optimization - MercadoLibre
Web performance optimization - MercadoLibre
 
Ad109 - XPages Performance and Scalability
Ad109 - XPages Performance and ScalabilityAd109 - XPages Performance and Scalability
Ad109 - XPages Performance and Scalability
 
Intro to XPages for Administrators (DanNotes, November 28, 2012)
Intro to XPages for Administrators (DanNotes, November 28, 2012)Intro to XPages for Administrators (DanNotes, November 28, 2012)
Intro to XPages for Administrators (DanNotes, November 28, 2012)
 
Web performance mercadolibre - ECI 2013
Web performance   mercadolibre - ECI 2013Web performance   mercadolibre - ECI 2013
Web performance mercadolibre - ECI 2013
 
Drupal 7 performance and optimization
Drupal 7 performance and optimizationDrupal 7 performance and optimization
Drupal 7 performance and optimization
 
Dust.js
Dust.jsDust.js
Dust.js
 
Developing high performance and responsive web apps using web worker
Developing high performance and responsive web apps using web workerDeveloping high performance and responsive web apps using web worker
Developing high performance and responsive web apps using web worker
 
PyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development UpdatedPyConUK 2014 - PostMortem Debugging and Web Development Updated
PyConUK 2014 - PostMortem Debugging and Web Development Updated
 
JavascriptMVC: Another choice of web framework
JavascriptMVC: Another choice of web frameworkJavascriptMVC: Another choice of web framework
JavascriptMVC: Another choice of web framework
 
Drupal performance and scalability
Drupal performance and scalabilityDrupal performance and scalability
Drupal performance and scalability
 
Journey through high performance django application
Journey through high performance django applicationJourney through high performance django application
Journey through high performance django application
 
Scaling symfony apps
Scaling symfony appsScaling symfony apps
Scaling symfony apps
 
Node.js Web Apps @ ebay scale
Node.js Web Apps @ ebay scaleNode.js Web Apps @ ebay scale
Node.js Web Apps @ ebay scale
 
Scaling PHP apps
Scaling PHP appsScaling PHP apps
Scaling PHP apps
 
kranonit S06E01 Игорь Цинько: High load
kranonit S06E01 Игорь Цинько: High loadkranonit S06E01 Игорь Цинько: High load
kranonit S06E01 Игорь Цинько: High load
 
AD113 Speed Up Your Applications w/ Nginx and PageSpeed
AD113  Speed Up Your Applications w/ Nginx and PageSpeedAD113  Speed Up Your Applications w/ Nginx and PageSpeed
AD113 Speed Up Your Applications w/ Nginx and PageSpeed
 
Orlando DNN Usergroup Pres 12/06/11
Orlando DNN Usergroup Pres 12/06/11Orlando DNN Usergroup Pres 12/06/11
Orlando DNN Usergroup Pres 12/06/11
 
Company Visitor Management System Report.docx
Company Visitor Management System Report.docxCompany Visitor Management System Report.docx
Company Visitor Management System Report.docx
 
Evolution of DBA in the Cloud Era
 Evolution of DBA in the Cloud Era Evolution of DBA in the Cloud Era
Evolution of DBA in the Cloud Era
 
Tech meetup: Web Applications Performance
Tech meetup: Web Applications PerformanceTech meetup: Web Applications Performance
Tech meetup: Web Applications Performance
 

Mehr von Alessandro Molina

PyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profitPyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profit
Alessandro Molina
 
Reactive & Realtime Web Applications with TurboGears2
Reactive & Realtime Web Applications with TurboGears2Reactive & Realtime Web Applications with TurboGears2
Reactive & Realtime Web Applications with TurboGears2
Alessandro Molina
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2
Alessandro Molina
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
Alessandro Molina
 
From SQLAlchemy to Ming with TurboGears2
From SQLAlchemy to Ming with TurboGears2From SQLAlchemy to Ming with TurboGears2
From SQLAlchemy to Ming with TurboGears2
Alessandro Molina
 

Mehr von Alessandro Molina (16)

PyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdfPyCon Ireland 2022 - PyArrow full stack.pdf
PyCon Ireland 2022 - PyArrow full stack.pdf
 
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
PyconIE 2016 - Kajiki, the fast and validated template engine your were looki...
 
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For AssetsEP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
EP2016 - Moving Away From Nodejs To A Pure Python Solution For Assets
 
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...EuroPython 2015 - Storing files for the web is not as straightforward as you ...
EuroPython 2015 - Storing files for the web is not as straightforward as you ...
 
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATESPyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
PyConIT6 - MAKING SESSIONS AND CACHING ROOMMATES
 
PyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profitPyConIT6 - Messing up with pymongo for fun and profit
PyConIT6 - Messing up with pymongo for fun and profit
 
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrongPyConFR 2014 - DEPOT, Story of a file.write() gone wrong
PyConFR 2014 - DEPOT, Story of a file.write() gone wrong
 
Reactive & Realtime Web Applications with TurboGears2
Reactive & Realtime Web Applications with TurboGears2Reactive & Realtime Web Applications with TurboGears2
Reactive & Realtime Web Applications with TurboGears2
 
Post-Mortem Debugging and Web Development
Post-Mortem Debugging and Web DevelopmentPost-Mortem Debugging and Web Development
Post-Mortem Debugging and Web Development
 
MongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profitMongoTorino 2013 - BSON Mad Science for fun and profit
MongoTorino 2013 - BSON Mad Science for fun and profit
 
PyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with MingPyConUK2013 - Validated documents on MongoDB with Ming
PyConUK2013 - Validated documents on MongoDB with Ming
 
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
EuroPython 2013 - FAST, DOCUMENTED AND RELIABLE JSON BASED WEBSERVICES WITH P...
 
EuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears TrainingEuroPython 2013 - Python3 TurboGears Training
EuroPython 2013 - Python3 TurboGears Training
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2
 
TurboGears2 Pluggable Applications
TurboGears2 Pluggable ApplicationsTurboGears2 Pluggable Applications
TurboGears2 Pluggable Applications
 
From SQLAlchemy to Ming with TurboGears2
From SQLAlchemy to Ming with TurboGears2From SQLAlchemy to Ming with TurboGears2
From SQLAlchemy to Ming with TurboGears2
 

Kürzlich hochgeladen

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Kürzlich hochgeladen (20)

Ransomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdfRansomware_Q4_2023. The report. [EN].pdf
Ransomware_Q4_2023. The report. [EN].pdf
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024FWD Group - Insurer Innovation Award 2024
FWD Group - Insurer Innovation Award 2024
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
Navigating the Deluge_ Dubai Floods and the Resilience of Dubai International...
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 

PyGrunn2013 High Performance Web Applications with TurboGears

  • 1. High Performance Web Applications with Python and TurboGears Alessandro Molina - @__amol__ - amol@turbogears.org
  • 2. About me ● Python Developer since 2001 ● Work @ on Python and iOS ● development team member since 2.1
  • 3. What's 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 free to disagree!
  • 4. Raw Speed ● People seem obsessed with webservers ● The truth is that it doesn't matter so much ○ You are not going to serve "Hello World"s (If you are asking my personal stack is nginx+mod_wsgi or nginx+Circus-Chaussette-gevent) ● Avoid the great idea of serving mostly empty pages performing hundreds of ajax requests ○ Browser have limited concurrency ○ HTTP has overhead ○ You will actually slow down things ● Learn your framework for real
  • 5. About TurboGears ● Framework for rapid development encouraging flexibility ● Created in 2005, 2.0 was a major rewrite in 2009 to embrace the WSGI standard. ● Object Dispatch based. Regular expressions can get messy, 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 and many more.
  • 6. Looking at the code class 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 a json encoded response
  • 8. Features vs Speed ● TurboGears is a full-stack framework. That makes it quite slow by default! ● The team invested effort to constantly speed it up since 2.1 release. ● Still keeping all the features around has its price ● To cope with this minimal mode got introduced
  • 9. Use only what you need ● Only use what you really need. Disabling some features can 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/sec Measures are on wsgiref, purpose is only to show delta
  • 10. Avoid serving statics Cascading 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 Cascade middleware that forwards the requests to your app
  • 11. Using Caching ● Caching means preorganizing your data the way you are going to use it, if you already did that during design phase you are already half done. Let the template drive your 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. Use HTML5 & JS ● If only small portions of your page change, cache the page and use JS to perform minor changes. ○ Invalidating your whole cache to say: "Welcome back Mister X" is not a great idea. ● If you are using Varnish, nginx or any other frontend cache consider using JS+localstorage instead of cookies for trivial customizations. Cookies will skip frontend caching
  • 13. Template Caching ● Template caching means prerendering your template based on controller computation results. ● It's common for template to access related entities, those will be cached for you. ● If correctly organized it's the caching behavior with best trade-off ○ Simple to implement ○ Guarantees correctly updates results ● An updated_at field on models is often all you need
  • 14. WikiPage Caching ● WikiPage caching is the standard template caching example 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. Caching Partials ● Case study: Notifications ○ Page delivered in 2.16s ○ Query took only 2ms ○ Most of the work was actually in rendering each notification ● Caching was useless as notifications happened often, constantly changing content.
  • 16. Entity Caching Map each object to a partial: @entitycached decorator makes 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 will never change.
  • 17. Caching can be harmful If you content changes too often, caching on first reuqest can actually be harmful. If you have multiple processes and a lot of requests you can end up having a race condition on cache update.
  • 18. Cache Stampede ● During football matches there were thousands of users constantly pressing "refresh" button to reload page. ● Content constantly changed due to match being reported on real time. ● After each update, all the running processes decided that the cache was not valid anymore at the same time, starting to regenerate the cache. ● Sometimes the content changed even while processes were still updating cache for previous update.
  • 19. Proactive Update ● To solve cache stampede the cache generation has been bound to an hook on the article update so it happened only once. ● Easy to achieve using Template caching in together with tg.template_render on article id as cache key ● SQLALchemy @event.listens_for supports even notifications on relationships, so it's reasy to update page cache even when related comments, tags, and so on change.
  • 20. A real solution ● The source of the issue were users pressing "reload" button like there's no tomorrow. ● Solutions has been to push updates to the users through a box 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 reduced the load on other parts of the website
  • 22. Think Different ● If you are struggling too much at improving performances, you are probabling doing something your application is not meant to do. ● Lesson learnt? ○ Soccer fans are eager for updates (no... for real!) ○ There is only one thing that gets more visits than a football match: Rumors on football players trading
  • 23. Offload Work ● The only person that know that something changes is the author of the change itself. ○ Only update the core cache to provide author with an immediate feedback ○ Don't be afraid of updating related caches asynchronously. Author usually understands that it might take some time before his changes propagate and other users don't know that a change happened yet. ● You can often provide an answer to user with little instant computation, messages and notifications are a typical example.
  • 24. Maste-Slave replication is easy ● SQLAlchemy unit of work pattern makes easy for frameworks to do the right thing 90% of the time ○ Read from slaves unless we are flushing the session ● Won't require changes to your code for most common cases ● Exceptions are as easy as @with_engine('master') ● As easy as sqlalchemy.master.url = mysql://masterhost/dbname sqlalchemy.slaves.slave1.url = mysql://slavehost/dbname sqlalchemy.slaves.slave2.url = mysql://slavehost/dbname
  • 25. Fast enough ● Speed should not be your primary focus, but it makes sense to care a lot about it, users tend to get frustrated by slow responses. ● New Relic App Speed Index reports an average of 5.0 seconds of response time for accepted experience. ● That is End-User time, not request time, to achieve 5 seconds you have to aim a lot lower ● Mean Opinion Score degrades quickly when surpassing 200ms. Less than 200ms is perceived as "right now". http://newrelic.com/ASI
  • 26. Development Tools ● It's easy to introduce changes with heavy impacts on performances without noticing. Development tools can help keeping under control impact of changes ● The DebugBar provides core utilities to track your application speed while developing: ○ Controller Profiling ○ Template & Partials Timing ○ Query Reporting ○ Query Logging for AJAX/JSON requests
  • 28. Keep an eye on your queries
  • 29. Check even after release ● Users use your application more widely than you might have expected ● Fast now, doesn't mean fast forever. Like test units avoid breaking things, rely on a speed feedback to keep acceptable speed. ● Keep your Apdex T index updated, user expectations evolve!
  • 30. There is no silver bullet ● Sorry, there is no silver bullet. ● Every application is a separate case, general and framework optimizations can usually provide little benefit when compared to domain specific optimizations ● Understanding how users interact with your application is the golden rule of optimization ● Don't understimate how its easy to do something really slow unconsciously: development tools can help catching those.