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

  3. szymanskilukasz
    About OLX

    View Slide

  4. szymanskilukasz
    40+
    Countries

    View Slide

  5. szymanskilukasz
    +260 Milion
    Monthly
    Active Users

    View Slide

  6. szymanskilukasz
    25 Milion
    Monthly Listings

    View Slide

  7. szymanskilukasz
    8,5 Milion
    Monthly Transactions

    View Slide

  8. szymanskilukasz
    4 mld Page Views
    Monthly
    in Poland

    View Slide

  9. szymanskilukasz
    Migration

    View 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 Slide

  11. szymanskilukasz
    Memcached
    Memcache

    View Slide

  12. szymanskilukasz
    $factory = new CacheWrapperFactory();

    $factory->createServer(

    extension_loaded('memcache') 

    ? 'memcache' : 'memcached',

    $uri

    );

    View Slide

  13. szymanskilukasz
    Memcache Serializer
    !=
    Memcached Serializer

    View Slide

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

    View Slide

  15. szymanskilukasz
    Question Time

    View Slide

  16. szymanskilukasz
    Restart

    View Slide

  17. szymanskilukasz
    APC

    View Slide

  18. szymanskilukasz
    APC is opcode cache and data store

    View Slide

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

    View Slide

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

    View 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 Slide

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

    View Slide

  23. szymanskilukasz
    Issues with libs
    PHP7 support
    in general

    View Slide

  24. szymanskilukasz
    We were ready

    View Slide

  25. szymanskilukasz
    Promises

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  30. szymanskilukasz
    Effects

    View Slide

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

    View Slide

  32. szymanskilukasz
    CPU

    View Slide

  33. szymanskilukasz
    CPU
    ~ 50% -> 20%

    View Slide

  34. szymanskilukasz
    Load

    View Slide

  35. szymanskilukasz
    Load
    ~ 16 -> 5

    View Slide

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

    View Slide

  37. szymanskilukasz
    Business

    View Slide

  38. szymanskilukasz
    Performance
    deep dive

    View Slide

  39. szymanskilukasz
    Memory Optimization

    View Slide

  40. szymanskilukasz
    Reduce Number
    Of Allocations

    View Slide

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

    View Slide

  42. szymanskilukasz
    Reduce Memory Usage

    View Slide

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

    View Slide

  44. szymanskilukasz
    Reduce Indirection

    View Slide

  45. szymanskilukasz
    Pointer points to pointer etc.

    View Slide

  46. szymanskilukasz
    Code

    View Slide

  47. szymanskilukasz
    Scalar type declarations

    View 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 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 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 Slide

  51. szymanskilukasz

    View Slide

  52. szymanskilukasz
    Not Really

    View 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 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 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 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 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 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 Slide

  59. szymanskilukasz
    declare (strict_types=1);

    View 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 Slide

  61. szymanskilukasz

    View Slide

  62. szymanskilukasz
    Not Even
    Close

    View 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 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 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 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 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 Slide

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

    View 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 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 Slide

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

    View Slide

  72. szymanskilukasz
    Errors & Exceptions

    View 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 Slide

  74. szymanskilukasz
    (float)

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  85. szymanskilukasz
    Future

    View Slide

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

    View Slide

  87. szymanskilukasz
    PHP7.1

    View Slide

  88. szymanskilukasz
    Void Return Type

    View 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 Slide

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

    View Slide

  91. szymanskilukasz
    Class Constant Visibility

    View 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 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 Slide

  94. szymanskilukasz
    Nullable Types

    View Slide

  95. szymanskilukasz
    function answer(): ?int {

    return null; //ok

    }


    function answer(): ?int {

    return 42; // ok

    }


    function answer(): ?int {

    return new stdclass(); // error

    }

    View 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 Slide

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

    function foo(): ?Fooable;

    }

    interface StrictFooable extends Fooable {

    function foo(): Fooable; // valid

    }

    View Slide

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

    function foo(): Fooable;

    }

    interface LooseFooable extends Fooable {

    function foo(): ?Fooable; // invalid

    }

    View 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 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 Slide

  101. szymanskilukasz
    Iterable pseudo-type

    View 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 Slide

  103. szymanskilukasz
    Under Discussion

    View Slide

  104. szymanskilukasz
    Class Friendship
    Created 2015/12/10

    View 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 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 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 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 Slide

  109. szymanskilukasz
    Named Parameters
    Created 2013/09/06

    View Slide

  110. szymanskilukasz
    // Using positional arguments:

    array_fill(0, 100, 42);

    // Using named arguments:

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

    View 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 Slide

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

    View 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 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 Slide

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


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

    View Slide

  116. szymanskilukasz
    In Draft

    View Slide

  117. szymanskilukasz
    Immutable classes and
    properties

    View Slide

  118. szymanskilukasz
    class Email {

    private $_email;


    public function __construct ($email) {

    // validation


    $this->_email = $email;

    }


    public function getValue() {

    return $this->_email;

    }

    }

    View Slide

  119. szymanskilukasz
    immutable class Email {

    public $email;


    public function __construct ($email) {

    // validation


    $this->email = $email;

    }

    }

    View Slide

  120. szymanskilukasz
    immutable class Email {

    public $email;


    public function __construct ($email) {

    // validation


    $this->email = $email;

    }

    }

    View Slide

  121. szymanskilukasz
    immutable class Email {

    public $email;


    public function __construct ($email) {

    // validation


    $this->email = $email;

    }

    }

    View 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 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 Slide

  124. szymanskilukasz
    Property type-hints

    View 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 Slide

  126. szymanskilukasz

    View Slide

  127. szymanskilukasz
    Performance

    View Slide

  128. szymanskilukasz
    Code Quality

    View Slide

  129. szymanskilukasz
    Bright Future

    View 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 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 Slide