Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP's Not Dead - PHP7 In Practice

PHP's Not Dead - PHP7 In Practice

Łukasz Szymański

August 20, 2016
Tweet

More Decks by Łukasz Szymański

Other Decks in Programming

Transcript

  1. szymanskilukasz
    PHP7
    in practice
    szymanskilukasz

    View full-size slide

  2. szymanskilukasz
    Łukasz Szymański
    Development Team Lead at
    @szymanskilukasz
    https://www.linkedin.com/in/szymanskilukasz
    https://twitter.com/szymanskilukasz
    https://speakerdeck.com/szymanskilukasz

    View full-size slide

  3. szymanskilukasz
    About OLX

    View full-size slide

  4. szymanskilukasz
    40+
    Countries

    View full-size slide

  5. szymanskilukasz
    +260 Milion
    Monthly
    Active Users

    View full-size slide

  6. szymanskilukasz
    25 Milion
    Monthly Listings

    View full-size slide

  7. szymanskilukasz
    8,5 Milion
    Monthly Transactions

    View full-size slide

  8. szymanskilukasz
    4 mld Page Views
    Monthly
    in Poland

    View full-size slide

  9. szymanskilukasz
    Migration

    View full-size slide

  10. szymanskilukasz
    // PHP 5 era code that will break.

    function handler(Exception $e) { ... }

    set_exception_handler('handler');


    // PHP 5 and 7 compatible.

    function handler($e) { ... }


    // PHP 7 only.

    function handler(Throwable $e) { ... }

    View full-size slide

  11. szymanskilukasz
    Memcached
    Memcache

    View full-size slide

  12. szymanskilukasz
    $factory = new CacheWrapperFactory();

    $factory->createServer(

    extension_loaded('memcache') 

    ? 'memcache' : 'memcached',

    $uri

    );

    View full-size slide

  13. szymanskilukasz
    Memcache Serializer
    !=
    Memcached Serializer

    View full-size slide

  14. szymanskilukasz
    memory
    object
    serialized by
    memcache
    serialization
    / deserialization
    application
    memcache
    memcached
    serialize
    deserialize
    x

    View full-size slide

  15. szymanskilukasz
    Question Time

    View full-size slide

  16. szymanskilukasz
    Restart

    View full-size slide

  17. szymanskilukasz
    APC

    View full-size slide

  18. szymanskilukasz
    APC is opcode cache and data store

    View full-size slide

  19. szymanskilukasz
    APC is opcode cache and data store
    APCu is only data store

    View full-size slide

  20. szymanskilukasz
    APC is opcode cache and data store
    APCu is only data store
    OPcache is only opcode cache

    View full-size slide

  21. szymanskilukasz
    APCu is APC stripped of opcode caching.
    APC is opcode cache and data store
    APCu is only data store
    OPcache is only opcode cache

    View full-size slide

  22. szymanskilukasz
    APCu
    Backward
    Compatible
    https://pecl.php.net/package/apcu_bc

    View full-size slide

  23. szymanskilukasz
    Issues with libs
    PHP7 support
    in general

    View full-size slide

  24. szymanskilukasz
    We were ready

    View full-size slide

  25. szymanskilukasz
    Promises

    View full-size slide

  26. szymanskilukasz
    source: http://www.zend.com/en/resources/php7_infographic

    View full-size slide

  27. szymanskilukasz
    source: http://www.zend.com/en/resources/php7_infographic

    View full-size slide

  28. szymanskilukasz
    source: http://www.zend.com/en/resources/php7_infographic

    View full-size slide

  29. szymanskilukasz
    source: http://www.zend.com/en/resources/php7_infographic

    View full-size slide

  30. szymanskilukasz
    Effects

    View full-size slide

  31. szymanskilukasz
    20 Physical Servers
    32 CPU Cores
    for Apache
    OLX.PL

    View full-size slide

  32. szymanskilukasz
    CPU

    View full-size slide

  33. szymanskilukasz
    CPU
    ~ 50% -> 20%

    View full-size slide

  34. szymanskilukasz
    Load

    View full-size slide

  35. szymanskilukasz
    Load
    ~ 16 -> 5

    View full-size slide

  36. szymanskilukasz
    Now we can use
    7 of them
    for something else
    OLX.PL

    View full-size slide

  37. szymanskilukasz
    Business

    View full-size slide

  38. szymanskilukasz
    Performance
    deep dive

    View full-size slide

  39. szymanskilukasz
    Memory Optimization

    View full-size slide

  40. szymanskilukasz
    Reduce Number
    Of Allocations

    View full-size slide

  41. szymanskilukasz
    Reduce Number
    Of Allocations
    PHP5 spends
    20% of CPU time
    in allocator

    View full-size slide

  42. szymanskilukasz
    Reduce Memory Usage

    View full-size slide

  43. szymanskilukasz
    CPU L1D L2 L3
    RAM
    32KB 256KB few MB
    1ns 4ns 12ns
    100ns

    View full-size slide

  44. szymanskilukasz
    Reduce Indirection

    View full-size slide

  45. szymanskilukasz
    Pointer points to pointer etc.

    View full-size slide

  46. szymanskilukasz
    Code

    View full-size slide

  47. szymanskilukasz
    Scalar type declarations

    View full-size slide

  48. szymanskilukasz
    class PHPisNotDead

    {

    public function addIntegers($a, $b) {

    return $a + $b;

    }


    public function addFloats($a, $b) {

    return $a + $b;

    }


    public function reverseString($a) {

    return strrev($a);

    }


    public function isItTrue($a) {

    return $a ? 'yes' : 'no';

    }

    }
    PHP5

    View full-size slide

  49. szymanskilukasz
    class PHPisNotDead

    {

    public function addIntegers(MyInteger $a, MyInteger $b) {

    return $a + $b;

    }


    public function addFloats(MyFloat $a, MyFloat $b) {

    return $a + $b;

    }


    public function reverseString(MyString $a) {

    return strrev($a);

    }


    public function isItTrue($a) {

    return $a ? 'yes' : 'no';

    }

    }
    PHP5 + Value Objects

    View full-size slide

  50. szymanskilukasz
    PHP7
    class PHPisNotDead

    {

    public function addIntegers(int $a, int $b) : int {

    return $a + $b;

    }


    public function addFloats(float $a, float $b) : float {

    return $a + $b;

    }


    public function reverseString(string $a) : string {

    return strrev($a);

    }


    public function isItTrue(bool $a) : string {

    return $a ? 'yes' : 'no';

    }

    }

    View full-size slide

  51. szymanskilukasz

    View full-size slide

  52. szymanskilukasz
    Not Really

    View full-size slide

  53. szymanskilukasz
    PHP7
    class PHPisNotDead

    {

    public function addIntegers(int $a, int $b) : int {

    return $a + $b;

    }


    public function addFloats(float $a, float $b) : float {

    return $a + $b;

    }


    public function reverseString(string $a) : string {

    return strrev($a);

    }


    public function isItTrue(bool $a) : string {

    return $a ? 'yes' : 'no';

    }

    }

    View full-size slide

  54. szymanskilukasz
    PHP7
    $php = new PHPisNotDead(); 

    var_dump($php->addIntegers(1.3, 5.7));
    // int(6)

    var_dump($php->addFloats(4, '3.4'));
    // double(7.4)

    var_dump($php->reverseString(12345));
    // string(5) "54321"

    var_dump($php->isItTrue(21.37));
    // string(3) "yes"

    View full-size slide

  55. szymanskilukasz
    PHP7
    $php = new PHPisNotDead(); 

    var_dump($php->addIntegers(1.3, 5.7));
    // int(6)

    var_dump($php->addFloats(4, '3.4'));
    // double(7.4)

    var_dump($php->reverseString(12345));
    // string(5) "54321"

    var_dump($php->isItTrue(21.37));
    // string(3) "yes"
    WTF?

    View full-size slide

  56. szymanskilukasz
    PHP7
    $php = new PHPisNotDead(); 

    var_dump($php->addIntegers(1.3, 5.7));
    // int(6)

    var_dump($php->addFloats(4, '3.4'));
    // double(7.4)

    var_dump($php->reverseString(12345));
    // string(5) "54321"

    var_dump($php->isItTrue(21.37));
    // string(3) "yes"
    Coercive
    Mode
    (default)

    View full-size slide

  57. szymanskilukasz
    public function addIntegers(int $a,int $b) : int {

    return $a + $b;

    }

    public function addIntegers($a, $b) {

    $a = (int) $a;

    $b = (int) $b;

    return (int) ($a + $b);

    }
    PHP7

    View full-size slide

  58. szymanskilukasz
    public function addIntegers(int $a,int $b) : int {

    return $a + $b;

    }

    public function addIntegers($a, $b) {

    $a = (int) $a;

    $b = (int) $b;

    return (int) ($a + $b);

    }
    PHP7

    View full-size slide

  59. szymanskilukasz
    declare (strict_types=1);

    View full-size slide

  60. szymanskilukasz
    declare (strict_types=1);
    class PHPisNotDead

    {

    public function addIntegers(int $a, int $b) : int {

    return $a + $b;

    }


    public function addFloats(float $a, float $b) : float {

    return $a + $b;

    }


    public function reverseString(string $a) : string {

    return strrev($a);

    }


    public function isItTrue(bool $a) : string {

    return $a ? 'yes' : 'no';

    }

    }
    PHPisNotDead.php

    View full-size slide

  61. szymanskilukasz

    View full-size slide

  62. szymanskilukasz
    Not Even
    Close

    View full-size slide

  63. szymanskilukasz
    index.php
    require "PHPisNotDead.php";


    $php = new PHPisNotDead();

    var_dump($php->addIntegers(1.3, 5.7));
    // int(6)

    var_dump($php->addFloats(4, '3.4'));
    // double(7.4)

    var_dump($php->reverseString(12345));
    // string(5) "54321"

    var_dump($php->isItTrue(21.37));
    // string(3) "yes"

    View full-size slide

  64. szymanskilukasz
    index.php
    require "PHPisNotDead.php";


    $php = new PHPisNotDead();

    var_dump($php->addIntegers(1.3, 5.7));
    // int(6)

    var_dump($php->addFloats(4, '3.4'));
    // double(7.4)

    var_dump($php->reverseString(12345));
    // string(5) "54321"

    var_dump($php->isItTrue(21.37));
    // string(3) "yes"
    WTF2?

    View full-size slide

  65. szymanskilukasz
    declare (strict_types=1);
    class PHPisNotDead

    {

    public function addIntegers(int $a, int $b) : int {

    return $a + $b;

    }


    public function addFloats(float $a, float $b) : float {

    return $a + $b;

    }


    public function reverseString(string $a) : string {

    return strrev($a);

    }


    public function isItTrue(bool $a) : string {

    return $a ? 'yes' : 'no';

    }

    }
    PHPisNotDead.php

    View full-size slide

  66. szymanskilukasz
    declare (strict_types=1);
    class PHPisNotDead

    {

    public function addIntegers(int $a, int $b) : int {

    return $a + $b;

    }


    public function addFloats(float $a, float $b) : float {

    return $a + $b;

    }


    public function reverseString(string $a) : string {

    return strrev($a);

    }


    public function isItTrue(bool $a) : string {

    return $a ? 'yes' : 'no';

    }

    }
    PHPisNotDead.php

    View full-size slide

  67. szymanskilukasz
    PHPisNotDead.php
    declare (strict_types = 1);


    class PHPisNotDead

    {

    public function addIntegers(int $a, int $b) : int {

    return (string) ($a + $b);

    }


    public function addFloats(float $a, float $b) : float {

    return $a + $b;

    }


    public function reverseString(string $a) : string {

    return strrev($a);

    }


    public function isItTrue(bool $a) : string {

    return $a ? 'yes' : 'no';

    }

    }

    View full-size slide

  68. szymanskilukasz
    Fatal error: Uncaught TypeError:
    Return value of PHPisNotDead::addIntegers()
    must be of the type integer, string returned

    View full-size slide

  69. szymanskilukasz
    declare (strict_types = 1);


    require "PHPisNotDead.php";


    $php = new PHPisNotDead();

    var_dump($php->addIntegers(1.3, 5.7));

    var_dump($php->addFloats(4, '3.4'));

    var_dump($php->reverseString(12345));

    var_dump($php->isItTrue(21.37));

    View full-size slide

  70. szymanskilukasz
    declare (strict_types = 1);


    require "PHPisNotDead.php";


    $php = new PHPisNotDead();

    var_dump($php->addIntegers(1.3, 5.7));

    var_dump($php->addFloats(4, '3.4'));

    var_dump($php->reverseString(12345));

    var_dump($php->isItTrue(21.37));

    View full-size slide

  71. szymanskilukasz
    TypeError: Argument 1 passed to
    PHPisNotDead::addIntegers()
    must be of the type integer, float given

    View full-size slide

  72. szymanskilukasz
    Errors & Exceptions

    View full-size slide

  73. szymanskilukasz
    $php = new PHPisNotDead();

    try {

    var_dump($php->addIntegers(1.3, 5.7));
    } catch (TypeError $error) {

    echo $error->getMessage();

    } catch (Error $error) {

    echo $error->getMessage();

    } catch (Exception $exception) {

    echo $exception->getMessage();

    } catch (Throwable $throwable) {

    echo $throwable->getMessage();

    }

    View full-size slide

  74. szymanskilukasz
    (float)

    View full-size slide

  75. szymanskilukasz
    var_dump((float) "php");

    View full-size slide

  76. szymanskilukasz
    PHP5.6 ?
    var_dump((float) "php");

    View full-size slide

  77. szymanskilukasz
    PHP5.6 float(0)
    var_dump((float) "php");

    View full-size slide

  78. szymanskilukasz
    PHP5.6 float(0)
    PHP7.0 ?
    var_dump((float) "php");

    View full-size slide

  79. szymanskilukasz
    PHP5.6 float(0)
    PHP7.0
    var_dump((float) "php");
    float(0)

    View full-size slide

  80. szymanskilukasz
    var_dump((float) "nananana");

    View full-size slide

  81. szymanskilukasz
    var_dump((float) "nananana");
    PHP5.6 ?

    View full-size slide

  82. szymanskilukasz
    var_dump((float) "nananana");
    PHP5.6 float(0)

    View full-size slide

  83. szymanskilukasz
    var_dump((float) "nananana");
    PHP5.6 float(0)
    PHP7.0 ?

    View full-size slide

  84. szymanskilukasz
    var_dump((float) "nananana");
    PHP5.6 float(0)
    PHP7.0 float(NAN)

    View full-size slide

  85. szymanskilukasz
    Future

    View full-size slide

  86. szymanskilukasz
    http://php.net/supported-versions.php

    View full-size slide

  87. szymanskilukasz
    PHP7.1

    View full-size slide

  88. szymanskilukasz
    Void Return Type

    View full-size slide

  89. szymanskilukasz
    function should_return_nothing(): void {

    return 1; // Fatal error: A void function must not return a value

    }


    function lacks_return(): void {

    // valid

    }


    function returns_nothing(): void {

    return; // valid

    }


    function returns_null(): void {

    return null; // Fatal error: A void function must not return a value

    }


    function foobar(void $foo) {}

    // Fatal error: void cannot be used as a parameter type

    View full-size slide

  90. szymanskilukasz
    checked at compile-time
    error is produced without
    the function needing to
    be called.

    View full-size slide

  91. szymanskilukasz
    Class Constant Visibility

    View full-size slide

  92. szymanskilukasz
    class Token {

    // Constants default to public

    const PUBLIC_CONST = 0;


    // Constants then also can have a defined visibility

    private const PRIVATE_CONST = 0;

    protected const PROTECTED_CONST = 0;

    public const PUBLIC_CONST_TWO = 0;


    //Constants can only have one visibility declaration list

    private const FOO = 1, BAR = 2;

    }

    View full-size slide

  93. szymanskilukasz
    //Interfaces only support public consts,
    // and a compile time error will be thrown
    // for anything else.
    // Mirroring the behavior of methods.

    interface ICache {

    public const PUBLIC = 0;

    const IMPLICIT_PUBLIC = 1;

    }

    View full-size slide

  94. szymanskilukasz
    Nullable Types

    View full-size slide

  95. szymanskilukasz
    function answer(): ?int {

    return null; //ok

    }


    function answer(): ?int {

    return 42; // ok

    }


    function answer(): ?int {

    return new stdclass(); // error

    }

    View full-size slide

  96. szymanskilukasz
    function say(?string $msg) {

    if ($msg) {

    echo $msg;

    }

    }


    say('hello'); // ok -- prints hello

    say(null); // ok -- does not print

    say(); // error -- missing parameter

    say(new stdclass); //error -- bad type

    View full-size slide

  97. szymanskilukasz
    // nullability can be removed by a subclass
    interface Fooable {

    function foo(): ?Fooable;

    }

    interface StrictFooable extends Fooable {

    function foo(): Fooable; // valid

    }

    View full-size slide

  98. szymanskilukasz
    // but it cannot be added
    interface Fooable {

    function foo(): Fooable;

    }

    interface LooseFooable extends Fooable {

    function foo(): ?Fooable; // invalid

    }

    View full-size slide

  99. szymanskilukasz
    // Valid use: loosening the nullable marker
    // in a parameter:

    interface Fooable {

    function foo(Fooable $f);

    }

    interface LooseFoo extends Fooable {

    function foo(?Fooable $f);

    }

    View full-size slide

  100. szymanskilukasz
    // Invalid use: tightening
    // the nullable marker in a parameter:

    interface Fooable {

    function foo(?Fooable $f);

    }

    interface StrictFoo extends Fooable {

    function foo(Fooable $f);

    }

    View full-size slide

  101. szymanskilukasz
    Iterable pseudo-type

    View full-size slide

  102. szymanskilukasz
    // If a value is not an array or instance of Traversable,

    // a TypeError will be thrown.

    function foo(iterable $iterable) {

    foreach ($iterable as $value) {

    // ...

    }

    }


    // If the returned value is not an array

    // or instance of Traversable, a TypeError will be thrown.

    function bar(): iterable {

    return [1, 2, 3];

    }


    // Parameters declared as iterable

    // may use null or an array as a default value

    function foo(iterable $iterable = []) {

    // ...

    }

    View full-size slide

  103. szymanskilukasz
    Under Discussion

    View full-size slide

  104. szymanskilukasz
    Class Friendship
    Created 2015/12/10

    View full-size slide

  105. szymanskilukasz
    class Person

    {

    friend HumanResourceReport;


    protected $id;

    protected $firstName;

    protected $lastName;


    public function __construct($id, $firstName, $lastName)

    {

    $this->id = $id;

    $this->firstName = $firstName;

    $this->lastName = $lastName;

    }


    public function makeReport()

    {

    return new HumanResourceReport($this);

    }

    }

    View full-size slide

  106. szymanskilukasz
    class HumanResourceReport

    {

    private $person;


    public function __construct(Person $person)

    {

    $this->person = $person;

    }


    public function getFullName()

    {

    // HumanResourceReport would not have access to protected 

    // members of Person if not explicitly listed as a friend.

    return $this->person->firstName . ' ' . $this->person->lastName;

    }


    public function getReportIdentifier()

    {

    return "HR_REPORT_ID_{$this->person->id}";

    }

    }

    View full-size slide

  107. szymanskilukasz
    class HumanResourceReport

    {

    private $person;


    public function __construct(Person $person)

    {

    $this->person = $person;

    }


    public function getFullName()

    {

    // HumanResourceReport would not have access to protected 

    // members of Person if not explicitly listed as a friend.

    return $this->person->firstName . ' ' . $this->person->lastName;

    }


    public function getReportIdentifier()

    {

    return "HR_REPORT_ID_{$this->person->id}";

    }

    }

    View full-size slide

  108. szymanskilukasz
    $person = new Person(Uuid::uuid4(), 'Alice', 'Wonderland');

    $report = $person->makeReport();


    var_dump($report->getFullName()); 

    // string(16) "Alice Wonderland"

    var_dump($report->getReportIdentifier()); 

    // string(49)
    "HR_REPORT_ID_3F2504E0-4F89-41D3-9A0C-0305E82C3301"

    View full-size slide

  109. szymanskilukasz
    Named Parameters
    Created 2013/09/06

    View full-size slide

  110. szymanskilukasz
    // Using positional arguments:

    array_fill(0, 100, 42);

    // Using named arguments:

    array_fill(start_index => 0, num => 100, value => 42);

    View full-size slide

  111. szymanskilukasz
    htmlspecialchars($string, default, default, false);

    // vs

    htmlspecialchars($string, double_encode => false);


    $str->contains("foo", true);

    // vs

    $str->contains("foo", caseInsensitive => true);

    View full-size slide

  112. szymanskilukasz
    Generic Types and Functions
    Created 2015/04/28

    View full-size slide

  113. szymanskilukasz
    class Entry

    {

    protected $key;

    protected $value;


    public function __construct(KeyType $key, ValueType $value)

    {

    $this->key = $key;

    $this->value = $value;

    }


    public function getKey(): KeyType

    {

    return $this->key;

    }


    public function getValue(): ValueType

    {

    return $this->value;

    }

    }

    View full-size slide

  114. szymanskilukasz
    class Entry

    {

    protected $key;

    protected $value;


    public function __construct(KeyType $key, ValueType $value)

    {

    $this->key = $key;

    $this->value = $value;

    }


    public function getKey(): KeyType

    {

    return $this->key;

    }


    public function getValue(): ValueType

    {

    return $this->value;

    }

    }

    View full-size slide

  115. szymanskilukasz
    $entry = new Entry(1, 'test');


    $entry = new Entry(1, 'test');

    View full-size slide

  116. szymanskilukasz
    In Draft

    View full-size slide

  117. szymanskilukasz
    Immutable classes and
    properties

    View full-size slide

  118. szymanskilukasz
    class Email {

    private $_email;


    public function __construct ($email) {

    // validation


    $this->_email = $email;

    }


    public function getValue() {

    return $this->_email;

    }

    }

    View full-size slide

  119. szymanskilukasz
    immutable class Email {

    public $email;


    public function __construct ($email) {

    // validation


    $this->email = $email;

    }

    }

    View full-size slide

  120. szymanskilukasz
    immutable class Email {

    public $email;


    public function __construct ($email) {

    // validation


    $this->email = $email;

    }

    }

    View full-size slide

  121. szymanskilukasz
    immutable class Email {

    public $email;


    public function __construct ($email) {

    // validation


    $this->email = $email;

    }

    }

    View full-size slide

  122. szymanskilukasz
    immutable class Email {

    public $email;


    public function __construct ($email) {

    // validation


    $this->email = $email;

    }

    }


    $email = new Email("[email protected]");

    $email->email = "[email protected]" // Call will
    result in Fatal Error

    View full-size slide

  123. szymanskilukasz
    class Email {

    public immutable $email;


    public function __construct ($email) {

    // validation


    $this->email = $email;

    }

    }


    $email = new Email("[email protected]");

    $email->email = "[email protected]" // Call will
    result in Fatal Error

    View full-size slide

  124. szymanskilukasz
    Property type-hints

    View full-size slide

  125. szymanskilukasz
    class BoxedInt {

    public int $value;

    }


    $i = new BoxedInt();

    $i->value = 'oops';

    // Catchable fatal error:

    // property BoxedInt::$value must be of

    // the type integer, string given

    View full-size slide

  126. szymanskilukasz

    View full-size slide

  127. szymanskilukasz
    Performance

    View full-size slide

  128. szymanskilukasz
    Code Quality

    View full-size slide

  129. szymanskilukasz
    Bright Future

    View full-size slide

  130. szymanskilukasz
    Łukasz Szymański
    Development Team Lead at
    @szymanskilukasz
    https://www.linkedin.com/in/szymanskilukasz
    https://twitter.com/szymanskilukasz
    https://speakerdeck.com/szymanskilukasz

    View full-size slide

  131. szymanskilukasz
    http://www.slideshare.net/nikita_ppv/php-7-what-changed-internally-php-barcelona-2015
    http://www.phpinternalsbook.com/
    resources
    http://php.net/manual/en/migration70.new-features.php
    https://wiki.php.net/
    http://www.zend.com/en/resources/php7_infographic

    View full-size slide