Slide 1

Slide 1 text

SCALING PHP Dustin Whittle

Slide 2

Slide 2 text

PHP IS USED BY THE LIKES OF FACEBOOK, YAHOO, ZYNGA, TUMBLR, ETSY, AND WIKIPEDIA. HOW DO THE LARGEST INTERNET COMPANIES SCALE PHP TO MEET THEIR DEMAND? JOIN THIS SESSION AND FIND OUT HOW TO USE THE LATEST TOOLS IN PHP FOR DEVELOPING HIGH PERFORMANCE APPLICATIONS. WE’LL TAKE A LOOK AT COMMON TECHNIQUES FOR SCALING PHP APPLICATIONS AND BEST PRACTICES FOR PROFILING AND OPTIMIZING PERFORMANCE. AFTER THIS SESSION, YOU’LL LEAVE PREPARED TO TACKLE YOUR NEXT ENTERPRISE PHP PROJECT.

Slide 3

Slide 3 text

AGENDA • Why performance matters? • The problems with PHP • Best practice designs • Distributed data caches with Redis and Memcached • Doing work in the background with queues • Http caching and a reverse proxy with Varnish • Using the right tool for the job • Tools of the trade • Xdebug + WebGrind • XHProf + XHProf GUI • AppDynamics • Google PageSpeed • Architecture not applications

Slide 4

Slide 4 text

%645*/8)*55-& EVTUJOXIJUUMFDPN !EVTUJOXIJUUMF 4BO'SBODJTDP $BMJGPSOJB 64" 6CFS "QQ%ZOBNJDT ,XBSUFS 4FOTJP-BCT :BIPP l 5FDIOPMPHJTU 5SBWFMFS 1JMPU 4LJFS %JWFS 4BJMPS (PMGFS

Slide 5

Slide 5 text

WHAT I HAVE WORKED ON • Developer Advocate @
 • Developer Evangelist @
 • Consultant & Trainer @
 • Developer Evangelist @

Slide 6

Slide 6 text

DID YOU KNOW FACEBOOK, YAHOO, ZYNGA, TUMBLR, ETSY, AND WIKIPEDIA WERE ALL STARTED ON PHP?

Slide 7

Slide 7 text

WHY DOES PERFORMANCE MATTER?

Slide 8

Slide 8 text

WHEN MOZILLA SHAVED 2.2 SECONDS OFF THEIR LANDING PAGE, FIREFOX DOWNLOADS INCREASED 15.4% (60 million more downloads)

Slide 9

Slide 9 text

AMAZON AND WALMART INCREASED REVENUE 1% FOR EVERY 100MS OF IMPROVEMENT

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

PERFORMANCE DIRECTLY IMPACTS THE BOTTOM LINE

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

•Performance is key to a great user experience •Under 100ms is perceived as reac$ng instantaneously •A 100ms to 300ms delay is percep$ble •1 second is about the limit for the user's flow of thought to stay uninterrupted •Users expect a site to load in 2 seconds •AXer 3 seconds, 40% will abandon your site. •10 seconds is about the limit for keeping the user's a*en$on •Modern applicaDons spend more Dme in the browser than on the server-side

Slide 14

Slide 14 text

Login Flight Status Search Flight Purchase Mobile Big data SOA NOSQL Cloud Agile Web Application complexity is exploding

Slide 15

Slide 15 text

TREAT PERFORMANCE AS A FEATURE!

Slide 16

Slide 16 text

PHP IS SLOWER THAN JAVA, C+ +, ERLANG, SCALA, AND GO!

Slide 17

Slide 17 text

HTTP://PHPSADNESS.COM/

Slide 18

Slide 18 text

...AND PHP HAS SOME SERIOUS DESIGN ISSUES AND INCONSISTENCIES!

Slide 19

Slide 19 text

...BUT THERE ARE WAYS TO SCALE TO HANDLE HIGH TRAFFIC APPLICATIONS

Slide 20

Slide 20 text

PHP IS NOT YOUR PROBLEM!

Slide 21

Slide 21 text

SCALABILITY = ARCHITECTURE != CODE OPTIMIZATIONS

Slide 22

Slide 22 text

WHAT VERSION OF PHP DO YOU RUN?

Slide 23

Slide 23 text

UPGRADE YOUR PHP ENVIRONMENT TO 2016! PHP7 is twice as fast as PHP5

Slide 24

Slide 24 text

USE COMPOSER TO STAY UP TO DATE

Slide 25

Slide 25 text

NGINX + PHP-FPM

Slide 26

Slide 26 text

USE AN OPCODE CACHE!

Slide 27

Slide 27 text

PHP 5.5+ HAS OPCACHE

Slide 28

Slide 28 text

USE AUTOLOADING AND PSR-0

Slide 29

Slide 29 text

SYMFONY CLASSLOADER COMPONENT WITH CACHING

Slide 30

Slide 30 text

SCALING BEYOND A SINGLE SERVER IN PHP

Slide 31

Slide 31 text

OPTIMIZE YOUR SESSIONS!

Slide 32

Slide 32 text

THE DEFAULT IN PHP IS TO PERSIST SESSIONS TO DISK

Slide 33

Slide 33 text

IT IS BETTER TO STORE SESSIONS IN A DATABASE

Slide 34

Slide 34 text

EVEN BETTER IS TO STORE IN A DATABASE WITH A SHARED CACHE IN FRONT

Slide 35

Slide 35 text

PECL INSTALL MEMCACHED

Slide 36

Slide 36 text

session.save_handler = memcached session.save_path = "10.0.0.10:11211,10.0.0.11:11211,10.0.0.12:11211" memcached.sess_prefix = “session.” memcached.sess_consistent_hash = On memcached.sess_remove_failed = 1 memcached.sess_number_of_replicas = 2 memcached.sess_binary = On memcached.sess_randomize_replica_read = On memcached.sess_locking = On memcached.sess_connect_$meout = 200 memcached.serializer = “igbinary”

Slide 37

Slide 37 text

THE BEST SOLUTION IS TO LIMIT SESSION SIZE AND STORE ALL DATA IN A SIGNED OR ENCRYPTED COOKIE

Slide 38

Slide 38 text

Scaling server-side applications • Caching - Cache as much on the client-side and server side as possible (javascript, css, images, fonts, content). • Leverage a CDN + browser caching • Use a reverse proxy cache on the server side • Queuing - Do not delay the user experience for tasks that can be executed in the background • Async - Optimize work to execute concurrently / asynchronously

Slide 39

Slide 39 text

LEVERAGE AN IN-MEMORY DATA CACHE

Slide 40

Slide 40 text

MEMCACHED.ORG

Slide 41

Slide 41 text

REDIS.IO

Slide 42

Slide 42 text

•Any data that is expensive to generate/query and long lived should be cached •Web Service Responses •HTTP Responses •Database Result Sets •ConfiguraDon Data

Slide 43

Slide 43 text

GUZZLE HTTP CLIENT HAS BUILT- IN SUPPORT FOR CACHING WEB SERVICE REQUESTS AND PSR-7

Slide 44

Slide 44 text

$memcache = new Memcache(); $memcache->connect('localhost', 11211); $memcacheDriver = new Doctrine\Common\Cache\MemcacheCache(); $memcacheDriver->setMemcache($memcache); $client = new Guzzle\H:pClient(‘h:p://www.test.com/’); $cachePlugin = new Guzzle\Plugin\Cache\CachePlugin(array( ‘storage’ => new Guzzle\Plugin\Cache\DefaultCacheStorage( new Guzzle\Plugin\Cache\DoctrineCacheAdapter($memcacheDriver) ) )); $client->addSubscriber($cachePlugin); $response = $client->get(‘h:p://www.wikipedia.org/’)->send(); $response = $client->get(‘h:p://www.wikipedia.org/’)->send();

Slide 45

Slide 45 text

DOCTRINE ORM FOR PHP HAS BUILT-IN CACHING SUPPORT FOR MEMCACHED AND REDIS

Slide 46

Slide 46 text

$memcache = new Memcache(); $memcache->connect('localhost', 11211); $memcacheDriver = new Doctrine\Common\Cache\MemcacheCache(); $memcacheDriver->setMemcache($memcache); $config = new Doctrine\ORM\ConfiguraDon(); $config->setQueryCacheImpl($memcacheDriver); $config->setMetadataCacheImpl($memcacheDriver); $config->setResultCacheImpl($memcacheDriver); $enDtyManager = Doctrine\ORM\EnDtyManager::create(array(‘driver’ => ‘pdo_sqlite’, ‘path’ => __DIR__ . ‘/db.sqlite’), $config); $query = $em->createQuery(‘select u from EnDDesUser u’); $query->useResultCache(true, 60); $users = $query->getResult();

Slide 47

Slide 47 text

DO BLOCKING WORK IN BACKGROUND TASKS VIA QUEUES

Slide 48

Slide 48 text

•Resque •Gearman •RabbitMQ •Kawa •Beanstalkd •ZeroMQ •AcDveMQ

Slide 49

Slide 49 text

RESQUE

Slide 50

Slide 50 text

•Any process that is slow and not important for the h:p response should be queued •Sending noDficaDons + posDng to social accounts •AnalyDcs + InstrumentaDon •UpdaDng profiles and discovering friends from social accounts •Consuming web services like Twi:er Streaming API

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

No content

Slide 53

Slide 53 text

No content

Slide 54

Slide 54 text

No content

Slide 55

Slide 55 text

LEVERAGE HTTP CACHING

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

No content

Slide 58

Slide 58 text

EXPIRES OR INVALIDATION

Slide 59

Slide 59 text

EXPIRATION

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

No content

Slide 62

Slide 62 text

VALIDATION

Slide 63

Slide 63 text

No content

Slide 64

Slide 64 text

No content

Slide 65

Slide 65 text

EXPIRATION AND INVALIDATION

Slide 66

Slide 66 text

No content

Slide 67

Slide 67 text

No content

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

No content

Slide 70

Slide 70 text

SYMFONY HTTPFOUNDATION COMPONENT WITH HTTP CACHING

Slide 71

Slide 71 text

use Symfony\Component\H:pFoundaDon\Response; $response = new Response(‘Hello World!’, 200, array(‘content-type’ => ‘text/html’)); $response->setCache(array( ‘etag’ => ‘a_unique_id_for_this_resource’, ‘last_modified’ => new DateTime(), ‘max_age’ => 600, ‘s_maxage’ => 600, ‘private’ => false, ‘public’ => true, ));

Slide 72

Slide 72 text

use Symfony\Component\H:pFoundaDon\Request; use Symfony\Component\H:pFoundaDon\Response; $request = Request::createFromGlobals(); $response = new Response(‘Hello World!’, 200, array(‘content-type’ => ‘text/html’)); if ($response->isNotModified($request)) { $response->send(); }

Slide 73

Slide 73 text

•Varnish •Squid •Nginx Proxy Cache •Apache Proxy Cache

Slide 74

Slide 74 text

USE VARNISH AS A REVERSE PROXY CACHE TO ALLEVIATE LOAD ON YOUR APP SERVERS

Slide 75

Slide 75 text

Caching Best Practices • Use consistent URLs: if you serve the same content on different URLs, then that content will be fetched and stored multiple times. Tip: note that URLs are case sensitive! • Ensure the server provides a validation token (ETag): validation tokens eliminate the need to transfer the same bytes when a resource has not changed on the server. • Identify which resources can be cached by intermediaries: those with responses that are identical for all users are great candidates to be cached by a CDN and other intermediaries. • Determine the optimal cache lifetime for each resource: different resources may have different freshness requirements. Audit and determine the appropriate max-age for each one. • Determine the best cache hierarchy for your site: the combination of resource URLs with content fingerprints, and short or no-cache lifetimes for HTML documents allows you to control how quickly updates are picked up by the client.

Slide 76

Slide 76 text

OPTIMIZE YOUR FRAMEWORK!

Slide 77

Slide 77 text

No content

Slide 78

Slide 78 text

•Stay up-to-date with the latest stable version of your favorite framework •Disable features you are not using (I18N, Security, etc) •Always use a data cache like Memcached/Redis •Enable caching features for views and database result sets •Always use a HTTP cache like Varnish

Slide 79

Slide 79 text

Monitor performance on the server-side and client-side

Slide 80

Slide 80 text

XDEBUG + WEBGRIND

Slide 81

Slide 81 text

No content

Slide 82

Slide 82 text

UPROFILER + XHPROF + GUI

Slide 83

Slide 83 text

No content

Slide 84

Slide 84 text

No content

Slide 85

Slide 85 text

No content

Slide 86

Slide 86 text

No content

Slide 87

Slide 87 text

No content

Slide 88

Slide 88 text

No content

Slide 89

Slide 89 text

No content

Slide 90

Slide 90 text

No content

Slide 91

Slide 91 text

PHP AS GLUE

Slide 92

Slide 92 text

BACKEND = JAVA/SCALA/ ERLANG/GO/NODE FRONTEND = PHP OR JAVASCRIPT

Slide 93

Slide 93 text

YAHOO! & YPHP Move slow code to PHP extensions

Slide 94

Slide 94 text

FACEBOOK & HHVM A drop-in replacement for PHP (mostly)

Slide 95

Slide 95 text

•Upgrade to PHP 7 with Zend OpCache using PHP-FPM + Nginx •Stay up to date with your framework + dependencies (using Composer) •OpDmize your session store to use signed cookies or database with caching •Cache your database and web service access with Memcache or Redis •Do blocking work in the background with queues and tasks using Resque •Use HTTP caching and a reverse proxy cache like Varnish •Profile code with Xdebug + Webgrind and monitor producDon performance with AppDynamics!

Slide 96

Slide 96 text

DON’T FORGET TO OPTIMIZE THE CLIENT SIDE

Slide 97

Slide 97 text

IN MODERN WEB APPLICATIONS MOST OF THE LATENCY COMES FROM THE CLIENT SIDE

Slide 98

Slide 98 text

USE ASSETIC TO OPTIMIZE CLIENT-SIDE ASSETS

Slide 99

Slide 99 text

Common Performance Best Practices • Reduce size of HTTP requests • Optimize stylesheets + javascripts + images + fonts • Leverage gzip compression • Reduce cookie size + use cookie less domains for static assets

Slide 100

Slide 100 text

Common Performance Best Practices • Optimize content • Move stylesheet to head • Move javascript to body close (and eliminate blocking javascript) • Preload components when idle

Slide 101

Slide 101 text

Common Performance Best Practices • Reduce DNS lookups • Reduce network latency with Content Delivery Networks • Use service workers

Slide 102

Slide 102 text

Understanding the impact of HTTP2 • Todays best practices are tomorrows anti-patterns • The limitations of HTTP/1.X forced us to develop various application workarounds (sharding, concatenation, spriting, inlining, etc.) to optimize performance. However, in the process we’ve also introduced numerous regressions: poor caching, unnecessary downloads, delayed execution, and more. • HTTP/2 eliminates the need for these hacks and allows us to both simplify our applications and deliver improved performance. • You should unshard (domains), unconcat (css/javascript), and unsprite your assets (images) • You should switch from inlining to server push • Read Ilya Grigorik awesome book on browser performance - http://hpbn.co/http2

Slide 103

Slide 103 text

GOOGLE PAGESPEED INSIGHTS

Slide 104

Slide 104 text

No content

Slide 105

Slide 105 text

No content

Slide 106

Slide 106 text

No content

Slide 107

Slide 107 text

No content

Slide 108

Slide 108 text

No content

Slide 109

Slide 109 text

No content

Slide 110

Slide 110 text

No content

Slide 111

Slide 111 text

No content

Slide 112

Slide 112 text

SCALABILITY IS ABOUT THE ENTIRE ARCHITECTURE, NOT MINOR CODE OPTIMIZATIONS.

Slide 113

Slide 113 text

QUESTIONS?

Slide 114

Slide 114 text

This talk is heavily inspired from: Google PageSpeed Rules Google Web Fundamentals Ryan Tomayko’s “Things Caches Do” Addy Osmani’s “Automating Workflow” Ilya Grigorik “High Performance Browser Networking”

Slide 115

Slide 115 text

FIND THESE SLIDES ON SPEAKERDECK: SPEAKERDECK.COM/DUSTINWHITTLE