6 tips to build
Fast Web Applications
-
Luciano Mammino (@loige)
PHP Dublin 22/03/2016
About me
Integrations Engineer at Smartbox
Php developer since *.php3
I Tweet as @loige
I Blog on loige.co
Preamble
- Only 6 tips (not exhaustive)
- Focused on backend
- Many generic advices (not just Php)
- ... Tools and examples (mostly) for Php :)
Tip 1.
Avoid premature optimisation!
"Premature optimisation is the root of all evil"
— Donald Knuth
(not an excuse to write 💩 code!)
Do you really have a problem?
How big the problem is?
Measure before questioning
Set (realistic) goals
Improve only where needed!
The right mindset
The performance lifecycle
Benchmarking
Profiling
Active or Passive?
Xdebug (Active)
- Gives a lot of data
- Slows down the execution
- Good in development
- Easy to integrate with IDEs
- Also a debugger
Libraries
Symfony stopwatch component
<?php
use Symfony\Component\Stopwatch\Stopwatch;
$stopwatch = new Stopwatch();
// Start event named 'eventName'
$stopwatch->start('eventName');
// ... some code goes here
$event = $stopwatch->stop('eventName');
echo $event->getDuration(); // xxx milliseconds
Cloud tools
Tip 2.
Do just what you need to
A.k.a.
"Don't do things that you don't need to"
E.g.
- Load classes that you are not using
- Open a connection to a database for every request
- Parse a huge XML config file for every request
<?php
require __DIR__ . '/vendor/autoload.php'; // generated by Composer
use Mario\Characters\Mario;
use Mario\Powerups\Mushroom;
// Mario & Mushroom classes not loaded yet...
$mario = new Mario();
// Mario class is loaded!
$mushroom = new Mushroom();
// Mushroom class is loaded!
$mario->eat($mushroom); // Tasty!
Other patterns
Dependency Injection
(& Dependency Injection Container)
Simplifies the loading of classes and the resolution of dependencies
Lazy loading & Proxy
Access resources only when you are about to use them
Tip 3.
If you really need to do it,
do it tomorrow!
Defer tasks when possible
E.g.
- Send an email to a user to confirm an order
- Resize an image after the upload
- Aggregate metrics
(Serve the response as soon as it's ready!)
Queues to the rescue
A PHP library (Redis as data store).
Laravel/Lumen built-in solution (multiple data storages).
Generic job server that supports many languages.
Work queue originally written to speed up Facebook
Tip 4.
Use cache to avoid repetitive computations and roundtrips
Different Caching layers:
- Byte code Cache (APC, OpCache)
- Application Cache (Redis, Memcache, Gibson)
- HTTP Cache (E-tag, Cache-control headers)
- Proxy Cache (Varnish, Squid, Nginx)
"There are only two hard things in Computer Science: cache invalidation and naming things"
— Phil Karlton
Tip 5.
Beware of the N+1 query problem!
<?php
function getUsers() {
//... retrieve the users from the database (1 query)
return $users;
}
function loadLastLoginsForUsers($users) {
foreach ($users as $user) {
$lastLogins = ... // load the last logins
// for the user (1 query, executed n times)
$user->setLastLogins($lastLogins);
}
return $users;
}
$users = getUsers();
loadLastLoginsForUsers($users);
SELECT id FROM Users; -- ids: 1, 2, 3, 4, 5, 6...
SELECT * FROM Logins WHERE user_id = 1;
SELECT * FROM Logins WHERE user_id = 2;
SELECT * FROM Logins WHERE user_id = 3;
SELECT * FROM Logins WHERE user_id = 4;
SELECT * FROM Logins WHERE user_id = 5;
SELECT * FROM Logins WHERE user_id = 6;
-- ...
N+1 Queries! 😓
Better solution
or use JOINS...
SELECT id FROM Users; -- ids: 1, 2, 3, 4, 5, 6...
SELECT * FROM Logins
WHERE user_id IN (1, 2, 3, 4, 5, 6, ...);
Don't trust the ORM
Check the queries generated by your code!
Tip 6.
Plan for horizontal scalability
Build your app to be replicated across many servers
Sessions:
- Don't use the default file based engine
- Be as much stateless as possible
User files:
- CDN, Cloud Storage (S3, Cloudfiles), Sync (NFS, Gluster)
Consider Microservices...
BONUS Tip.
Update to PHP7
(Rasmus approves)
Let's Recap
-
Avoid premature optimisation!
-
Do just what you need to
-
If you really need to do it, do it tomorrow!
-
Cache me if you can
-
Beware of the N+1 query problem!
-
Plan for horizontal scalability
-
Bonus: Update to Php 7
Thank you!
Let's keep in touch: