Covers Performance improvements with the Symfony web framework for PHP.
- Google cares about user happiness, Google owns your search traffic ...so Google put page speed in PageRank (and crawl speed)
- Your site is more trustworthy and less frustrating
- Increase page views and ad impressions
- Increase conversions and revenue! It pays for itself!
- Bonus: run less app servers
1. SYMFONY
PERFORMANCE
Paul Thrasher
@thrashr888 | github.com/thrashr888
Sr. Software Engineer at Dogster
SF Symfony Meetup October
#sfsymfony
2. WHY WORRY ABOUT
PERFORMANCE?
yo u
an d
V
• Google cares about user happiness, Google owns your
search traffic
...so Google put page speed in PageRank (and crawl speed)
• Your site is more trustworthy and less frustrating
• Increase page views and ad impressions
• Increase conversions and revenue! It pays for itself!
• Bonus: run less app servers
3. DOGSTER, INC.
• Started in 2004
• Catster.com is the same codebase
• ~2MM monthly uniques
• ~12MM monthly page views
• Over 1 million dogs and cats on our sites
• Production servers: 5 app, 3 master DBs, 8 slave DBs
• Spent the summer redesigning and working on performance
4. Backend Performance
Benchmark, PHP, Database, Caching
Symfony 1.4.X Performance
You and your team, Caching
Frontend Performance
Benchmark, HTML, JS, CSS, Images, CDN
Questions at End
8. BACKEND - PHP 5.3
Migrate to PHP 5.3 http://github.com/smalyshev/migrate/
thrashr888@MacBook workspace$ php migrate.php SymSters
WARNING: Function 'spliti' is deprecated, please use 'preg_split' instead in file SymSters/lib/vendor/symfony/lib/
plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mssql.php line 173
WARNING: Function 'spliti' is deprecated, please use 'preg_split' instead in file SymSters/lib/vendor/symfony/lib/
plugins/sfDoctrinePlugin/lib/vendor/doctrine/Doctrine/Connection/Mssql.php line 192
WARNING: Function 'ereg' is deprecated, please use 'preg_match' instead in file SymSters/lib/vendor/symfony/lib/
plugins/sfPropelPlugin/lib/vendor/phing/lib/Zip.php line 1852
WARNING: Function 'ereg' is deprecated, please use 'preg_match' instead in file SymSters/lib/vendor/symfony/lib/
plugins/sfPropelPlugin/lib/vendor/phing/lib/Zip.php line 2735
WARNING: Function 'split' is deprecated, please use 'explode' or 'preg_split' instead in file SymSters/lib/vendor/
symfony/lib/plugins/sfPropelPlugin/lib/vendor/phing/tasks/ext/coverage/CoverageReportTask.php line 168
WARNING: Function 'set_magic_quotes_runtime' is deprecated, its use is no longer recommended in file SymSters/lib/
vendor/symfony/lib/vendor/swiftmailer/classes/Swift/ByteStream/FileByteStream.php line 82
WARNING: Function 'set_magic_quotes_runtime' is deprecated, its use is no longer recommended in file SymSters/lib/
vendor/symfony/lib/vendor/swiftmailer/classes/Swift/ByteStream/FileByteStream.php line 87
WARNING: Function 'set_magic_quotes_runtime' is deprecated, its use is no longer recommended in file SymSters/lib/
vendor/symfony/lib/vendor/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php line 174
WARNING: Function 'set_magic_quotes_runtime' is deprecated, its use is no longer recommended in file SymSters/lib/
vendor/symfony/lib/vendor/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php line 183
WARNING: Function 'set_magic_quotes_runtime' is deprecated, its use is no longer recommended in file SymSters/lib/
vendor/symfony/lib/vendor/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php line 202
WARNING: Function 'set_magic_quotes_runtime' is deprecated, its use is no longer recommended in file SymSters/lib/
vendor/symfony/lib/vendor/swiftmailer/classes/Swift/KeyCache/DiskKeyCache.php line 210
WARNING: Function 'ereg' is deprecated, please use 'preg_match' instead in file SymSters/plugins/sfPropel15Plugin/
lib/vendor/phing/lib/Zip.php line 1852
WARNING: Function 'ereg' is deprecated, please use 'preg_match' instead in file SymSters/plugins/sfPropel15Plugin/
lib/vendor/phing/lib/Zip.php line 2735
9. BACKEND - MYSQL SLOW QUERY LOG
Count : 55 (5.46%)
Time : 204.477485 s total, 3.717772 s avg, 1.007915 s to 20.940426 s max (9.81%)
95% of Time : 160.326234 s total, 3.083197 s avg, 1.007915 s to 9.951604 s max
Lock Time (s) : 2.507 ms total, 46 avg, 34 to 65 max (1.86%)
95% of Lock : 2.318 ms total, 45 avg, 34 to 61 max
Rows sent : 3 avg, 3 to 3 max (0.00%)
Rows examined : 14.69k avg, 311 to 112.50k max (0.12%)
Database : starster
EXPLAIN : 14369 produced, 2278976448465661 read
id: 1
select_type: SIMPLE
table: p
type: ref
possible_keys: pub_index,user_id_idx,NI_PET_CODE
key: user_id_idx
key_len: 3
ref: const
rows: 1732
Extra: Using where; Using filesort
Query abstract:
SET timestamp=N; SELECT p.post_id, p.body, p.pet_id, p.thread_id, p.main_topic_id FROM forums_post_new p
WHERE p.pub_status != 'S' AND p.user_id = 'S' AND p.pet_code = 'S' ORDER BY p.post_id DESC LIMIT N;
Query sample:
SET timestamp=1286803854;
SELECT p.post_id, p.body, p.pet_id, p.thread_id, p.main_topic_id FROM forums_post_new p WHERE p.pub_status !=
'n' AND p.user_id = '243549' AND p.pet_code = 'd' ORDER BY p.post_id DESC LIMIT 3;
10. BACKEND - OTHER METHODS
• Setup timers, refactor and cache slow code
• Memcache, APC cache, etc.
• Add app and DB servers
• Use Twig for layouts, it uses file-based caching
11. Don’t get too caught up here
unless there are major issues.
15. Symfony already does a few other things for you:
• caches settings and config
• keeps junk off production servers
• provides caching framework to make your caching easier
• Core Compilation (turns 30 files into 1 file)
• BUT Symfony is for apps, not speedy scripts
• Symfony performance mostly means caching…
18. SYMFONY - ACTION CACHE
Just cache the action, not the views:
# apps/frontend/modules/homepage/config/cache.yml
all:
with_layout: false
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/21
19. SYMFONY - PARTIAL CACHE
Just give it the name of the partial file:
# apps/frontend/modules/homepage/config/cache.yml
index:
enabled: true
_sidebar:
enabled: true
all:
with_layout: true
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/21
20. SYMFONY - FUNCTION CACHE
You can cache many function calls:
<?php
$dog = new Dog();
$cache = new sfMemcacheCache();
$func = new sfFunctionCache($cache);
$func->call(array($dog, 'getFriends'), array('25'));
29. FRONTEND - HOW DO WE FIX THIS?
Less HTML, JS, CSS Faster JS
Less images Faster CSS
Less photoshop Faster images
(more HTML)
30. FRONTEND - LESS IS MORE
Less HTML, JS, CSS
• Remove code you’re not using
• Concat files together for lower HTTP requests
Less images
• Make design decisions to remove images
• Use sprites for less HTTP requests
Less Photoshop, more HTML
• Don’t go crazy with Photoshop when you’re designing
31. FRONTEND - FASTER DOWNLOADS
Faster JavaScript
• Be careful about where and how you place your JS
Faster CSS
• Minify and gzip your files
Faster images
• Compress your images before uploading
37. THE CSS IS EASY AS PIE
• CSScalls and positions the sprite with
background-image and background-position properties
.image {
background-image:
url(http://www.website.com/images/sprite-image.png);
background-position: 0px 100px;
width: 100px;
height: 50px;
}
• See? Easy as pie!
38. WHY USE CSS SPRITES?
• Reduce the number of HTTP Requests to server
• Improves load time of your website
• Faster
load time on your pages means better search engine
page ranking
39. EXAMPLE
• Dogster global elements used 32 images that were
“sprite-able”. We tiled all 32 images onto one image
• Combined 32 images = 170 KB
Single sprite image = 70 KB
40. HOW TO CREATE CSS SPRITES
• Option 1: Create them manually
• Option 2: Use a Sprite generator
• SpriteMe – http://spriteme.org/
• Project Fondue CSS Sprite generator -
http://spritegen.website-performance.org/
• SmartSprites - http://csssprites.org/
41. IMAGE OPTIMIZATION
Using image compression tools to make sure your files are as
small as they can be
• OptiPNG - http://optipng.sourceforge.net/
• Image Optimizer - http://www.imageoptimizer.net/Pages/Home.aspx
• PNG Crusher - http://www.amake.us/software/pngcrusher/
42. IMAGE OPTIMIZATION (CONT’D.)
Avoid using text images, i.e., images that just contain text.
Try to use a font service instead:
• Typekit - http://typekit.com/
• Font-Squirrel (free!) - http://www.fontsquirrel.com/
• FontFont - http://www.fontfont.com/
• Google Fonts - http://code.google.com/webfonts
43. POWER OF CSS3
Use cool CSS3 style effects - enables you to style WITHOUT
images
• Rounded corners, drop shadows, gradients
#findAVetMain {
-moz-border-radius:10px 10px 10px 10px;
-moz-box-shadow:0 0 8px #666666;
background-color:#FFFFFF;
border:1px solid #999999;
height:180px;
margin:10px 0 20px;
}
44. LESS PHOTOSHOP, MORE HTML
When designing mockups for your site, think of how it will get
built with html and css
• E.g. Does your nav bar really need an image for each item?
style it with css using a UL
• Think of how you can build each element without an image
• Build
it with clean HTML - don’t stick everything in a div.
Use your H1s, your Ps, ULs, etc...and it will perform better
47. FRONTEND - IMPLEMENTATIONS
LABjs
• Download your JS files in parallel
CDN: Amazon S3 and CloudFront
• Give your assets a proper home
Quarantine Your Ads
• They can be a pain, put them in a box
52. FRONTEND - CDN ADVANTAGES
Use a CDN, or giving your assets the home they deserve. There are
several advantages to using Amazon’s CDN.
• Geographical edge caching brings files closer to your users
• Purposefully set HTTP headers
• Cookie-less domain
• No need to use Apache/PHP to serve assets
• Overall quicker downloads
• Easy to round-robin domains
53. FRONTEND - STATIC FILES
Two classes of assets you’ll be serving:
Static
http://a1.cdnsters.com/static/images/slideshow/220x220rainydaydog.jpg
• Files that rarely change
• Typically libraries and images
• User generated content
• We mirror our images FTP server every 15 minutes
54. FRONTEND - RELEASE FILES
Two classes of assets you’ll be serving:
Release
http://a2.cdnsters.com/releases/20101014-1128/topic/css/
main.min.css.gz
• Files that might change each release
• Typically related to the apps
55. FRONTEND - CDN IMPLEMENTATION
So, how do you implement S3 and CloudFront?
1. Concat files by hand or using scripts
2. Compress images with ImageOptim
3. Create Minified versions of your JS and CSS
4. Create gzipped versions of all files
5. “rsync” white-listed folders to S3, with proper headers
6. CloudFront automatically gets files from S3
Bonus: https://gist.github.com/b82e5671e1f46760f0d9
Also try: http://tinycdn.com/
59. FRONTEND - ADS
Ads typically load external scripts that block page rendering. You’ll
probably want to quarantine your ads in some manner.
• Ads really really suck
• Place them in iframes
• Insert placeholders in HTML that populate at end of page via
Javascript
• Async loading probably doesn’t work because of
document.write() in ad scripts
* Google likely does count ads in overall page speed time
60. WRAP UP
Backend Performance
Benchmark, PHP, Database, Caching
Symfony 1.4.X Performance
You and your team, Caching
Frontend Performance
Benchmark, HTML, JS, CSS, Images, CDN
62. SF Symfony Meetup
http://www.dogster.com/
#sfsymfony
http://www.joedog.org/index/siege-home
http://github.com/smalyshev/migrate/
http://dev.mysql.com/doc/refman/5.5/en/slow-query-log.html
http://www.symfony-project.org/jobeet/1_4/Doctrine/en/21
http://www.yotta.com/
http://www.webpagetest.org/
http://labjs.com/
More JS loading tips: http://jquerysbestfriends.com/
Rules for Faster-Loading Web Sites: http://stevesouders.com/hpws/rules.php
http://aws.amazon.com/s3/
http://aws.amazon.com/cloudfront/
http://tinycdn.com/
http://code.google.com/p/minify/
http://www.io.com/~maus/HttpKeepAlive.html
Bonus S3 Symfony Task: https://gist.github.com/b82e5671e1f46760f0d9
Yuko Takahashi Paul Thrasher
@yukodesigns @thrashr888 | github.com/thrashr888
UI/Interactive Designer at Dogster Sr. Software Engineer at Dogster
Notas del editor
Question: Who's already worrying about performance and doing something about it?
1. Cut out code you&#x2019;re not using
2. Make design decisions to cut out more images, use sprites
3. Don&#x2019;t go crazy with Photoshop when you&#x2019;re designing
4. Be careful about where you place your JS
5. Minify and gzip your files
6. Compress your images
Use correct headers for your assets, we&#x2019;ll go over that later.
Use correct headers for your assets, we&#x2019;ll go over that later.
intro
role at dogster
excited to be here...wooo
origins of css sprite
Started off in video gaming: sprites were used to build visual effects in games
Has evolved to being used on all kinds of websites, like Yahoo, Facebook and Google.
Sprites are often confused as being a series of images, but it&#x2019;s actually one large image
Small images like buttons, roll-over or hover state, icons, logos, any small graphics
Examples
And they can be absurdly huge: Yahoo has one that is 380 pixels by 4314 pixels. It&#x2019;s only 12KB
Examples of button states used in a sprite
Simple example of how css looks - mainly using background image style that calls the image and X and Y coordinates for background-position styles
-think of all the information that goes into the image file...there&#x2019;s meta data, there&#x2019;s a color table associated with each file, and so if you think of all that information in each image file, you can see how that can slow down your site
- having a sprite reduces those number HTTP requests - and also makes the experience with images more seamless
- classic example are rollover buttons. with a sprite having a static state and rollover state as one image - with CSS styling the hover class is seamless...
- we may enjoy lightning fast download times in either our office or at home, but many of your users may not have that kind of speed, so we need to always keep in mind the user experience - if it doesn&#x2019;t load, they&#x2019;ll hit the back button
-&#x201C;sprite-able&#x201D; - not all images should be used in sprites. ideal is buttons, icons, little graphics as you saw in the previous slide. no large images and no images that require a repeating background
- dogster example: as a proof of concept, i took all the little images from the chrome, used a sprite generator that laid out all 32 images onto one large image and you can see the results
global elements = chrome = ubernav, nav, footer
Option 1 - take the widest image you have - that would be your width, then place all the images below. you can add as many as you want. the pain is figuring out all the coordinates
Option 2 - Sprite generators make sprites super fast and super easy. the only problem is maintaining it - if you need to add images, you&#x2019;d have to run it through again.
- SpriteMe - bookmarklet service
- Project Fondue - one i used. zip images, customiz how the images are laid out
basic example that illustrates what you can do with css3
Use correct headers for your assets, we&#x2019;ll go over that later.