PERFORMANCE AND NEW FEATURE OF PHP 7.4

Matteo Galacci

Software architect & Back-end Developer

Github:  https://github.com/matiux

Slack GRUSP:  matiux

Email:  m.galacci@gmail.com

Linkedin: Matteo Galacci

Grazie a...

Enrico Zimuel

https://www.zimuel.it

PHP

  • PHP: Hypertext Preprocessor
  • The most popular server-side language: PHP is used by 79.1% of all the websites (source: w3techs.com)
  • Used by Facebook, Wikipedia, Yahoo, Flickr, Badoo, Tumblr, Dailymotion, etc
  • 25 years of usage, since 1995
  • Full OOP support since PHP 5. Same programming paradigms as languages like java

PHP ECOSYSTEM

  • CMS: Wordpress and Symfony family
  • E-commerce: Magento, OpenCart, PrestaShop, etc
  • CRM: CiviCRM, SugarCRM, Vtiger etc
  • Wiki: DokuWiki, MedisWiki, PmWiki etc
  • Framework: Symfony, Laravel, Zend (?) etc
  • CQRS / ES

PHP 7

  • Released: 3 December 2015
  • Last major was PHP 5, 13 July 2004 (11 years)
  • Last release is 7.4.1 (18 December 2019)

PHP 6?

Native unicode support to PHP.
Never released. Project abandoned.

 

PHP 6 was supposed to add native unicode support to PHP. The community of developers working on it abandoned the project.
The main reason for not having a PHP 6 version is marketing. As time went on, it gave the PHP 6 release a bad name: a version that went in development for years (since 2005), but was never released.

 

Unicode is a computing industry standard for the consistent encoding, representation, and handling of text expressed in most of the world's writing systems.

SUPPORTED VERSIONS

PHP 7 IN A NUTSHELL

  • Great performance (thanks to PHPNG)
  • *Return/Scalar Type Declarations (But it is not mandatory like java). 
  • Anonymous classes (Useful in unit test to mock a class)
  • Nullable types (by prefixing the type name with a question mark)
  • Void return type (It was supported but now if esplicited, gives error)
  • New Error hierarchy (e.g. Fatal error, including file parser error, etc). Error and Exception implement both Throwable interface
  • Multiple catch

*Disabled by default. Use declare(strict_types=1); in each file

More info here

PERFORMANCE

PHPNG, PHP Next Generation

Developed by Dmitry Stogov and his team after more than a year's work.

He tried to make a JIT compiler like compiled or pseudo compiled languages (like Facebook with HHVM).

Better than PHP5, but not so much.

New data structure management (How variables, arrays, hash tables are managed. Everything, the basics) in the PHP engine.

Great performance improvement.

OTHER LANGUAGES

Mandelbrot fractal generator. Math functions with many iterations.

PHP 7 is also faster than Python 3.

May 2017

WORDPRESS

May 2017

Requests per second

MIGRATION CASE STUDIES

May 2017

  • Badoo saved one million dollars switching to PHP 7 (source). For the same reason Facebook has starts the JIT compiler project with HHVM.
  • Tumblr reduced the latency and CPU load by half moving to PHP 7 (source)
  • Dailymotion handles twice more traffic with same infrastructure switching to PHP 7 (source)

MIGRATION CASE STUDIES

May 2017

Resource Usage (CPU time):

MIGRATION CASE STUDIES

May 2017

Memory Usage:

BENCHMARK PHP5 vs php7

$a = [];

for ($i = 0; $i < 1000000; $i++) {
    $a[$i] = ["hello"];
}

echo memory_get_usage(true);
PHP 5.6 PHP 7
Memory usage 428 MB 33 MB
Execution time 0.49 sec 0.06 sec

BENCHMARK PHP 7.4

Some benchmarking of PHP 7.4 compared with the previous versions.

 

It has been used the Zend/bench.php script to run the experiment, getting the total execution times. This script is included with the PHP source code and it was created for testing the language using some math operators, nested loops, array, strings and recursive functions.

I executed the experiment using an Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz, with 32GB RAM, HD SSD running Linux Ubuntu 18.04.3 LTS.

BENCHMARK PHP 7.4

Here the results (in seconds) for each PHP versions:

BENCHMARK PHP 7.4

Here the results (in seconds) for each PHP versions:

BENCHMARK PHP 7.4

Here the results (in seconds) for each PHP versions:

BENCHMARK PHP 7.4

PHP 7.0 Nginx vs PHP 7.0 Swoole vs Node.js

http://grigorov.website/blog/performance-comparison-php-vs-node-js

PHP 7.4

NEW FEATURES

ARROW FUNCTIONS

array_map(function (User $user) { 
    return $user->id; 
}, $users)

Also called "short closures".


array_map(fn (User $user) => $user->id, $users)
  • Access to parent scope. No need for the use keyword.
  • $this works like a normal closures.
  • Contains only one expression; the return statement.

type variance

class ParentType {}

class ChildType extends ParentType {}

class A
{
    public function covariantReturnTypes(): ParentType
    {
    	/* … */ 
    }
}

class B extends A
{
    public function covariantReturnTypes(): ChildType
    { 
    	/* … */ 
    }
}

Covariance

type variance

class ParentType {}

class ChildType extends ParentType {}

class A
{
    public function contraVariantArguments(ChildType $type)
    { 
    	/* … */ 
    }
}

class B extends A
{
    public function contraVariantArguments(ParentType $type)
    { 
    	/* … */ 
    }
}

Contravariance

NULL COALESCING ASSIGNMENT OP.


$data['date'] = $data['date'] ?? new DateTime();

$data['date'] ??= new DateTime();

Array spread operator

$arrayA = [1, 2, 3];

$arrayB = [4, 5];

$result = [0, ...$arrayA, ...$arrayB, 6 ,7];

// [0, 1, 2, 3, 4, 5, 6, 7]

Only works with arrays with numerical keys.

Numeric Literal Separator

$unformattedNumber = 107925284.88;

$formattedNumber = 107_925_284.88;

PHP 7.4 allows for underscores to be used to visually separate numeric values.

Foreign function interface

A foreign function interface (FFI) is a mechanism by which a program written in one programming language can call routines or make use of services written in another.

 

Currently, accessing FFI data structures is significantly (about 2 times) slower than accessing native PHP arrays and objects. Therefore, it makes no sense to use the FFI extension for speed; however, it may make sense to use it to reduce memory consumption.

It was already possible to extend the PHP core. Phalcon framework is an example

Preloading

Another lower-level feature is preloading. It's is an amazing addition to PHP's core, which can result in some significant performance improvements.

In short: if you're using a framework, its files have to be loaded and linked on every request. Preloading allows the server to load PHP files in memory on startup, and have them permanently available to all subsequent requests.

The performance gain comes of course with a cost: if the source of preloaded files are changed, the server has to be restarted.

Custom object serialization

Two new magic methods have been added: __serialize and __unserialize.

 

The difference between these methods and __sleep and __wakeup is discussed in the RFC.

Reflection for references

$refs = [];

foreach ($array as $key => $value) {

    $ref = ReflectionReference::fromArrayElement(
    	$array, 
        $key
	);
    
    if (null !== $ref) {
        $refs[$ref->getId()][] = $key;
    }
}

This will partition the keys into groups that all point to the same reference:

$array = [
	'foo' => &$ref1, 
	'bar' => &$ref1, 
	'baz' => &$ref2, 
	'abc' => &$ref2,
] 

// this will result in:

$refs = [
	$ref1Id => [
		'foo', 'bar'
	], 
    $ref2Id => [
		'baz', 'abc'
    ]
]

Libraries like Symfony's var dumper rely heavily on the reflection API to reliably dump a variable. Previously it wasn't possible to properly reflect references, resulting in these libraries relying on hacks to detect them.

Reflection for references

Construction of ReflectionReference instances faces the following problem: A PHP function can either accept an argument by value or by reference. This needs to be declared in the function signature, making it impossible to distinguish whether the passed value was a reference originally or not. To determine whether or not something is a reference, access to the parent structure is necessary (which might be an array, object property table or symbol table).

 

To start with, only the fromArrayElement($array, $key) API is provided, which covers all known use-cases. Object properties can be handled by casting the object to array. The fromArrayElement($array, $key) method will either return a ReflectionReference instance if $array[$key] is a reference, or null.

 

If $array is not an array or $key is not an integer or string, a TypeError is thrown. If $array[$key] does not exist, a ReflectionException is thrown.

Weak references

Weak references allow the programmer to retain a reference to an object which does not prevent the object from being destroyed. They are useful for implementing cache like structures.

$obj = new stdClass;

$weakref = WeakReference::create($obj);

var_dump($weakref->get());

unset($obj);

var_dump($weakref->get());

/*
object(stdClass)#1 (0) {
}

NULL
*/
$a = new stdClass;
$b =&$a;
var_dump($a);
var_dump($b);

unset($a);
var_dump($a);
var_dump($b);

/*
object(stdClass)#1 (0) {
}

object(stdClass)#1 (0) {
}

Notice:  Undefined variable: a...

NULL
object(stdClass)#1 (0) {
}
*/

Backward incompatible

CREDITS

Thanks to Enrico Zimuel for the material and the help