Skip to main content
PHP 5.5 is here
Go and get it
Hello
● Hello, I'm Julien PAULI
– Architect at Blablacar Paris (www.blablacar.com)
– PHP 5.5 Release Manager
– Working on PHP internals
@BlaBlaCar
● http://www.blablacar.com
– .es .it .pl .de and covoiturage.fr
● 75 people
● > 3 million members
● 180Gb MySQL, 2 web fronts, mobile apps
● PHP 5.3, planning 5.4 soon
– Symfony2/Doctrine2 based app
– Redis, Memcache, RabbitMQ, ElasticSearch
● Java, Perl, Python, {?}...
Inside BlaBlaCar
● We do all ourselves : self-hosted
● From network building to app deployment
● Basis is Unix , we mainly use Linux
We are hiring
● PHP dev (SF2)
● Database admin
● BI / Data
● System admin
● ?
PHP
PHP : When ?
● We've always released version whenever we
wanted to
– 5.0 (2004)
– 5.1 (2005)
– 5.2 (2006)
– 5.3 (2009)
– 5.4 (2011)
– 5.5 (2013)
● Starting with 5.4, we have a process
PHP release process
● https://wiki.php.net/rfc/releaseprocess
● Yearly new major/minor (5.4->5.5 or 6.0)
– New features
– Big changes. Majors may break BC
– 3 years of life (2 + 1)
● Monthly new revisions (5.4.3->5.4.4)
– Bug fixes, no new features, BC kept
● EOLed security releases
– After EOL, 1 year of security fixes
PHP contributors
● Not so many contributors worldwide
– About 10~20 regular ppl
– Hundreds total
● Lots of ways to contribute
– Code (sure)
– Report bugs, write more tests
– Documentation, translations
– Infrastructure : php.net
● But how many PHP users worldwide ?
PHP 5.5
PHP 5.5 menu
● Password hashing API
● Generators
● "Finally" keyword
● OPCode cache integration
● Syntax and engine improvements
● Class name to scalar
● Breaks & deprecations
New Password hashing API
● PHP users don't really understand/care
about the concept behing hashing, salting
and crypting
● PHP doesn't give any hints about that
● User are left on their own
– Until 5.5 version
– Welcome a new password hashing API !
New Password hashing API
● http://www.php.net/password
● See how easy that looks now :
– To generate a hash
$password = 'secret';
$hash = password_hash($password, PASSWORD_DEFAULT);
var_dump($hash);
// "$2y$10$Pa2cIqH5X3m6iqIYVDBdvOUcggnXnZzBy0dlie
4VRHLr3ncLcyB7a"
New Password hashing API
● http://www.php.net/password
● See how easy that looks now :
– To verify a hash
$provided_password = 'secret';
$hash = "$2y$10$Pa2cIqH5X3m6iqIYVDBdvOUcggnXnZzBy0
dlie4VRHLr3ncLcyB7a";
if (password_verify($provided_password, $hash)) {
echo "you are welcome" ;
}
New Password hashing API
● More options :
– choose your hashing algorithm
– choose a salt from yours
– choose a CPU cost
$password = "mysecret" ;
$hash =password_hash($password, PASSWORD_BCRYPT,
array("cost" => 5, "salt" => "my_secret_salt") ) ;
New Password hashing API
● Just one Database field is needed
● The hash encapsulates all the infos
– algorithm used
– salt used
– cost used
– hash itself
"$2y$10$Pa2cIqH5X3m6iqIYVDBdvOUcggnXnZzBy0dlie4VR...
Generators
● http://www.php.net/generators
● Implementation of "generators", like in
Python, Js or C#
– A sort of concise Iterator
– With less code to write :-)
– Introduction of the new "yield" keyword
Generators example
function myGenerator() {
echo "startn";
yield "call";
yield "mykey" => "myvalue";
echo "endn";
}
$gen = myGenerator();
foreach ($gen as $k=>$v) {
echo "key : $k - val : $vn";
}
start
key : 0 - val : call
key : mykey - val : myvalue
end
Generators as iterators
function myGenerator() {
echo "startn";
yield "call";
yield "mykey" => "myvalue";
echo "endn";
}
$gen = myGenerator();
var_dump($gen);
object(Generator)#1 (0) {
}
$gen->next(); // start
echo $gen->current(); // call
Generators internally
./bin/php55 --rc Generator
Class [ <internal:Core> <iterateable> final class Generator
implements Iterator, Traversable ] { (...)
var_dump(new Generator);
Catchable fatal error: The "Generator" class is reserved for
internal use and cannot be manually instantiated
Generators deeper
● Generators can throw exceptions
● Generators can send() values
final class Generator implements Iterator {
void rewind();
bool valid();
mixed current();
mixed key();
void next();
mixed send(mixed $value);
mixed throw(Exception $exception);
}
Finally
try - catch - finally
● http://www.php.net/exceptions
echo "beginn";
try {
echo "enteredn";
throw new Exception("Foo");
echo "gonna leave try";
}
catch (Exception $e) {
echo "caughtn";
}
finally {
echo "finallyn";
}
echo "endn";
begin
entered
caught
finally
end
finally example
PHP < 5.5
$db = mysqli_connect();
try {
call_some_function($db);
} catch (Exception $e) {
mysqli_close($db);
log($e);
throw $e;
}
mysqli_close($db);
stuff();
$db = mysqli_connect();
try {
call_some_function($db);
} catch (Exception $e) {
log($e);
throw $e;
} finally {
mysqli_close($db);
}
stuff();
PHP >= 5.5
"Other" changes
● ext/intl has been massively worked on / improved
● ext/curl up to date with new libcurl
● bison < 2.4 no longer supported (parser)
● libpcre and libgd updated
● array_column()
● cli_set_process_title()
● Lots of bug fixes
Engine changes
foreach() changes
● Foreach now supports list()
● Good to iterate over 2-dim arrays
$users = array(
array('Foo', 'Bar'),
array('Baz', 'Qux');
);
// Before
foreach ($users as $user) {
list($firstName, $lastName) = $user;
echo "First name: $firstName, last name: $lastName. ";
}
// After
foreach ($users as list($firstName, $lastName)) {
echo "First name: $firstName, last name: $lastName. ";
}
foreach() changes
● Foreach now accepts keys as non-scalars
● Iterators' key() may now return arrays
$it = new MultipleIterator();
$it->attachIterator(new ArrayIterator(array(1,2,3)));
$it->attachIterator(new ArrayIterator(array(4,5,6)));
foreach ($it as $k => $v) {
var_dump($k, $v); // $k is an array
}
Array dereferencing strings
● Dereference const expressions
– Cool shortcuts sometimes
var_dump( "php"[1] ); // 'h'
var_dump( [1, 2, 3][1] ); // 2
var_dump( [ ['foo, 'bar'], [1, 2] ] [0][1] ); // "bar"
boolval()
● We could cast to (bool), but there were no
function for that
– Those functions exist for other types
● intval(), strval(), floatval()
– A new function is to be used as a callback argument
var_dump( (boolval) "foo" ); // true
$data = [ 'foo', 42, false, new stdClass() ];
var_dump(array_map('boolval', $data));
Class name runtime resolution
● Resolve the FQN of an imported class
<?php
use vendorBBCBar;
class FooTest extends PHPUnit_Framework_TestCase
{
public function testExample()
{
$bar = $this->getMock(Bar::CLASS); // "vendorBBCBar"
/* … */
}
}
OPCache
● OPCache = "ZendOptimizerPlus" for PHP
– It's been freed by Zend recently
– It's then been renamed
● OPCache will be shipped with PHP 5.5 , as
a bundled extension you have to activate at
runtime
● http://www.php.net/opcache (wip)
● APC is now dead
OPCache roles
● OPCode caching + optimizing
OPCache vs APC
● APC
– Is (very) hard to maintain
– is maintained by few volunteers
● And it's been a PITA with 5.4
– Never do that again
– suffers from historical bad low-level designs
that make it very hard to evolve
– is less performant than OPCache, 5 to 20%
– provides a "user cache", OPCache doesn't
● ext/apcu is a possible candidate for that
OPCache vs APC
● OPCache
– Is PHP licenced (like APC)
– is maintained by volunteers
– is also maintained by pro guys, mainly hired by Zend
– will be maintained in the same time as PHP
● No more surprise like 5.4 and APC
– has been the first PHP OPcode cache
implementation (1998). Very mature
– Supports PHP from 5.2 to current (like APC)
– Integrates an optimizer
Breaks
PHP 5.5 compatibility breaks
● ext/mysql has been deprecated /!
● /e modifier for preg() has been deprecated
● Dropped support for Windows XP and 2k3
● No more php logo and zend logo functions
● pack()/unpack() minor changes
● No more curl-wrappers
Performances ?
● The biggest step was 5.3 to 5.4
– First time for such a boost
● 5.5 is faster than 5.4
– But don't expect the same effect than 5.3 to 5.4
Performances
● Testing blablacar.com
– PHPUnit 3.7.21
– 959 tests
– (Lots of external services and SQL)
Time: 14:32, Memory: 1202.50Mb
Time: 12:48, Memory: 995.50Mb
Time: 12:30, Memory: 996.50Mb
5.3.latest
5.4.latest
5.5.latest
Engine performance
● PHP 5.3.latest
empty_loop 0.161
func() 0.459 0.298
undef_func() 0.469 0.309
int_func() 0.446 0.285
$x = self::$x 0.444 0.284
self::$x = 0 0.441 0.281
isset(self::$x) 0.431 0.270
empty(self::$x) 0.443 0.283
$x = Foo::$x 0.586 0.425
Foo::$x = 0 0.808 0.647
isset(Foo::$x) 0.578 0.417
empty(Foo::$x) 0.590 0.429
self::f() 0.716 0.555
Foo::f() 0.752 0.591
$x = $this->x 0.426 0.265
$this->x = 0 0.497 0.337
$this->x += 2 0.439 0.279
++$this->x 0.381 0.220
--$this->x 0.404 0.244
$this->x++ 0.411 0.251
$this->x-- 0.415 0.254
isset($this->x) 0.423 0.263
empty($this->x) 0.433 0.272
$this->f() 0.610 0.449
$x = Foo::TEST 0.353 0.193
new Foo() 1.763 1.602
$x = TEST 0.371 0.211
$x = $_GET 0.361 0.200
$x = $GLOBALS['v'] 0.501 0.341
$x = $hash['v'] 0.355 0.194
$x = $str[0] 0.660 0.499
$x = $a ?: null 2.139 1.978
$x = $f ?: tmp 0.435 0.274
$x = $f ? $f : $a 2.141 1.980
$x = $f ? $f : tmp 0.418 0.258
Total 21.259
Engine performance
● PHP 5.4.latest
empty_loop 0.117
func() 0.380 0.263
undef_func() 0.377 0.260
int_func() 0.336 0.219
$x = self::$x 0.361 0.245
self::$x = 0 0.331 0.214
isset(self::$x) 0.232 0.116
empty(self::$x) 0.243 0.127
$x = Foo::$x 0.327 0.210
Foo::$x = 0 0.217 0.100
isset(Foo::$x) 0.279 0.162
empty(Foo::$x) 0.216 0.100
self::f() 0.398 0.281
Foo::f() 0.365 0.248
$x = $this->x 0.363 0.246
$this->x = 0 0.322 0.205
$this->x += 2 0.252 0.136
++$this->x 0.220 0.103
--$this->x 0.224 0.107
$this->x++ 0.248 0.132
$this->x-- 0.252 0.135
isset($this->x) 0.232 0.115
empty($this->x) 0.251 0.135
$this->f() 0.423 0.307
$x = Foo::TEST 0.220 0.103
new Foo() 0.821 0.705
$x = TEST 0.169 0.052
$x = $_GET 0.256 0.140
$x = $GLOBALS['v'] 0.450 0.334
$x = $hash['v'] 0.355 0.238
$x = $str[0] 0.369 0.252
$x = $a ?: null 0.235 0.118
$x = $f ?: tmp 0.330 0.213
$x = $f ? $f : $a 0.245 0.129
$x = $f ? $f : tmp 0.334 0.217
Total 10.749
Engine performance
● PHP 5.5.latest
empty_loop 0.117
func() 0.396 0.279
undef_func() 0.415 0.298
int_func() 0.325 0.208
$x = self::$x 0.286 0.169
self::$x = 0 0.399 0.282
isset(self::$x) 0.237 0.120
empty(self::$x) 0.282 0.165
$x = Foo::$x 0.246 0.129
Foo::$x = 0 0.320 0.203
isset(Foo::$x) 0.203 0.086
empty(Foo::$x) 0.248 0.131
self::f() 0.433 0.316
Foo::f() 0.395 0.278
$x = $this->x 0.249 0.132
$this->x = 0 0.320 0.203
$this->x += 2 0.251 0.134
++$this->x 0.309 0.192
--$this->x 0.223 0.106
$this->x++ 0.248 0.131
$this->x-- 0.258 0.141
isset($this->x) 0.236 0.119
empty($this->x) 0.262 0.145
$this->f() 0.438 0.321
$x = Foo::TEST 0.225 0.107
new Foo() 0.825 0.708
$x = TEST 0.177 0.060
$x = $_GET 0.262 0.145
$x = $GLOBALS['v'] 0.357 0.240
$x = $hash['v'] 0.267 0.150
$x = $str[0] 0.368 0.251
$x = $a ?: null 0.233 0.115
$x = $f ?: tmp 0.317 0.200
$x = $f ? $f : $a 0.254 0.137
$x = $f ? $f : tmp 0.318 0.201
Total 10.700
Thank you for listening !
We are hiring