php next generation

Matteo Galacci

Software architect & Back-end Developer

Github:  https://github.com/matiux

Slack GRUSP:  matiux

Email:  m.galacci@gmail.com

Linkedin: Matteo Galacci

  • Developer since 2000
  • Consultant since 2008  
  • Software architect
  • Back-end developer
  • Domain Driven Design & Clean Code evangelist 
  • Member of PUG Romagna admins

Grazie a...

Grazie a...

Manuel Baldassarri

 

Linkedin

 

Introduzione a Swoole

PHP

  • PHP: Hypertext Preprocessor
  • The most popular server-side language: PHP is used by 78.9% 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.5 (16 April 2020)

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

7.0| Scalar type declaration

<?php

// Coercive mode

function sumOfInts(int ...$ints)
{
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));

//int(9)
<?php

// strict mode

declare(strict_types=1);

function sumOfInts(int ...$ints)
{
    return array_sum($ints);
}

var_dump(sumOfInts(2, '3', 4.1));

Fatal errors: Uncaught TypeError: Argument 2 passed to sumOfInts() must be of the type integer, string given

 

Next TypeError: Argument 3 passed to sumOfInts() must be of the type integer, float given, called in

7.0| return type declaration

<?php

function arraysSum(array ...$arrays): array
{
    return array_map(function(array $array): int {
        return array_sum($array);
    }, $arrays);
}

print_r(arraysSum([1,2,3], [4,5,6], [7,8,9]));


Array
(
    [0] => 6
    [1] => 15
    [2] => 24
)

7.0| Anonymous classes

<?php

interface Logger {

    public function log(string $msg);
}

class Application {

    private $logger;

    public function getLogger(): Logger {
         return $this->logger;
    }

    public function setLogger(Logger $logger) {
         $this->logger = $logger;
    }
}

$app = new Application();

$app->setLogger(new class implements Logger {

    public function log(string $msg) {
    
        echo $msg;
    }
});

var_dump($app->getLogger());

7.1| Nullable types

<?php

function testReturn(?string $string): ?string
{
    return $string;
}

echo testReturn(null); // null
echo testReturn('foo'); // foo

7.1| Void functions

<?php

function testReturn(string $string): void
{
    echo $string;
}

echo testReturn('foo'); // foo

7.1| Class constant visibility

<?php

class ConstDemo
{
    const PUBLIC_CONST_A = 1;
    public const PUBLIC_CONST_B = 2;
    protected const PROTECTED_CONST = 3;
    private const PRIVATE_CONST = 4;
}

7.2| New object type

<?php

function test(object $obj) : object
{
    return new SplQueue();
}

test(new StdClass());

7.0| Null coalescing operator

<?php

// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';

// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';

// Coalescing can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';

7.1| Multi catch exception handling

<?php

try {

    // some code
    
} catch (FirstException | SecondException $e) {

    // handle first and second exceptions
}

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

Swoole

Compared with other async programming frameworks or softwares such as Nginx, Tornado, Node.js, Swoole has the built-in PHP coroutine and async support, multiple threads I/O modules.

  • Event driven / Async programming
  • One million contemporary clients
  • Game servers
  • Chat / Webchat / Bot

Swoole

Swoole

Swoole

PHP 7.4

PHP 7.4 NEW FEATURES

November 2019

7.4| 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.

7.4| type variance

class ParentType {}

class ChildType extends ParentType {}

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

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

Covariance

7.4| 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

7.4| 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

7.4| 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.

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) {
}
*/

7.4| NULL COALESCING ASSIGNMENT OP.


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

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

7.4| 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.

php 8

PHP 8, the new major PHP version, is expected to be released on December 3, 2020. That means there will be no PHP 7.5 version.

  • JIT compiler (RFC)
  • Union types (RFC)
  • Static return type (RFC)
  • Weak maps (RFC)
  • ::class on object (RFC)
  • Stringable interface (RFC)

PHP 8

PHP 8 NEW FEATURES

8.0| JIT

What's JIT?

A Just-In-Time (JIT) compiler is a feature of the run-time interpreter, that instead of interpreting bytecode every time a method is invoked, will compile the bytecode into machine code, and then invoke this object code instead

8.0| JIT

Ciclo di vita

8.0| JIT

<?php
for ($i=0; $i<100; $i++) {
    echo $i;
}	

Example

Opcode

L0 (2):     ASSIGN CV0($i) int(0)
L1 (2):     JMP L4
L2 (3):     ECHO CV0($i)
L3 (2):     PRE_INC CV0($i)
L4 (2):     T1 = IS_SMALLER CV0($i) int(100)
L5 (2):     JMPNZ T1 L2
L6 (5):     RETURN int(1)

Linguaggio semplice simile ad assembly

8.0| JIT

Opcache

8.0| JIT

JIT

8.0| JIT

JIT

Previously we said that JIT can decide which portions to translate into machine code and which to leave in Opcode. How do you decide? Through a CRTO configuration, a number of 4 decimal places where each number represents a specific configuration.

CRTO = 1235

 

  • 1 = use AVX instructions (CPU optimization)
  • 2 = Register Allocation
  • 3 = profile on the fly and compile hot functions (Trigger)
  • 5 = type inference & procedure analysis (Optimization level)

8.0| JIT

JIT TRIGGER

  • 0 = JIT all functions on first script load
  • 1 = JIT functions on first execution
  • 2 = Profile on first request and compile hot functions on second request
  • 3 = Profile on the fly and compile hot functions
  • 4 = Compile functions with @jit tag in doc-comments*

* Useful for developing libraries and frameworks

8.0| JIT

8.0| JIT on Wordpress

  • PHP 8 no JIT: 190 req/sec
  • PHP 8 + JIT (CTRO 1235): 160 req/sec
  • PHP 8 + JIT (CTRO 1225): 189 req/sec
  • JIT is useful for CPU intensive applications (machine learning - PHP ML, image manipulation, pdf creations etc).
  • JIT does not offer improvement for IO Bound applications

8.0| Union typeS (RFC)

<?php

class Number {

    private int|float $number;
	
    public function setNumber(int|float $number): void {
        $this->number = $number;
    }
	
    public function getNumber(): int|float {
        return $this->number;
    }
}

8.0| Static return type (RFC)

<?php

class A {

    public function __construct($params = []) {
        $this->params = $params;
    }

    public function create($params): static {
        return new static($params);
    }
}

class B extends A {
}

$b = new B();

$result = $b->create(['x' => 'y']);

var_dump($result); // object(B) {["params"]=> ["x" => "y"]}

Useful in fluent interfaces

8.0| Weak maps (RFC)

<?php

$map = new WeakMap;
$obj = new stdClass;
$map[$obj] = 42;
var_dump($map);

// object(WeakMap)#1 (1) {
//   [0]=> [ 
//     "key" => object(stdClass)#2,
//     "value" => int(42)
//   ]
// }
	
// The object is destroyed here, key automatically removed
unset($obj);

var_dump($map);
// object(WeakMap)#1 (0) { }	

To provide "weakly referenced" map objects

Useful in the implementation of cache systems

8.0| Weak maps

<?php

class Foo {

    private WeakMap $cache;
	
    public function getSomethingWithCaching(object $obj) {
    
        return $this->cache[$obj] ??= $this->somethingExpensive($obj);
    }
}

To provide "weakly referenced" map objects

??= Null Coalescing Assignment (PHP 7.4+)

When the $obj variable is cleared somewhere, I don't have to invalidate the cache because the WeakMaps clears the reference in the cache

8.0| Stringable interface (RFC)

<?php

interface Stringable
{
    public function __toString(): string;
}

Stringable interface is automatically added to classes that implement the __toString() method

PHP 8 Release date

Feature freeze: July 28th 2020

Release date: December 2020

php 8 references

PHP RFC official page
PHP RFC Watch
Brent Roose, New in PHP 8
Eli White, What’s in PHP Eight?, php[architect], Vol.19 - Issue 5, May 2020
Arkadiusz Kondas, Compiling PHP 8 from source with JIT support
Níckolas Da Silva, Understanding PHP 8's JIT
Benoit Jacquemont, PHP 8 et Just In Time Compilation, PHPForum 2019
Nikita Popov, PHP 7 Virtual Machine
Anthony Ferrara, A PHP Compiler, aka The FFI Rabbit Hole
James Titcumb, Climbing the Abstract Syntax Tree, PHP UK 2018

CREDITS