szymanskilukasz
Łukasz Szymański
Development Team Lead at
@szymanskilukasz
https://www.linkedin.com/in/szymanskilukasz
https://twitter.com/szymanskilukasz
https://speakerdeck.com/szymanskilukasz
Slide 3
Slide 3 text
szymanskilukasz
About OLX
Slide 4
Slide 4 text
szymanskilukasz
40+
Countries
Slide 5
Slide 5 text
szymanskilukasz
+260 Milion
Monthly
Active Users
Slide 6
Slide 6 text
szymanskilukasz
25 Milion
Monthly Listings
Slide 7
Slide 7 text
szymanskilukasz
8,5 Milion
Monthly Transactions
Slide 8
Slide 8 text
szymanskilukasz
4 mld Page Views
Monthly
in Poland
Slide 9
Slide 9 text
szymanskilukasz
Migration
Slide 10
Slide 10 text
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) { ... }
szymanskilukasz
20 Physical Servers
32 CPU Cores
for Apache
OLX.PL
Slide 32
Slide 32 text
szymanskilukasz
CPU
Slide 33
Slide 33 text
szymanskilukasz
CPU
~ 50% -> 20%
Slide 34
Slide 34 text
szymanskilukasz
Load
Slide 35
Slide 35 text
szymanskilukasz
Load
~ 16 -> 5
Slide 36
Slide 36 text
szymanskilukasz
Now we can use
7 of them
for something else
OLX.PL
Slide 37
Slide 37 text
szymanskilukasz
Business
Slide 38
Slide 38 text
szymanskilukasz
Performance
deep dive
Slide 39
Slide 39 text
szymanskilukasz
Memory Optimization
Slide 40
Slide 40 text
szymanskilukasz
Reduce Number
Of Allocations
Slide 41
Slide 41 text
szymanskilukasz
Reduce Number
Of Allocations
PHP5 spends
20% of CPU time
in allocator
Slide 42
Slide 42 text
szymanskilukasz
Reduce Memory Usage
Slide 43
Slide 43 text
szymanskilukasz
CPU L1D L2 L3
RAM
32KB 256KB few MB
1ns 4ns 12ns
100ns
Slide 44
Slide 44 text
szymanskilukasz
Reduce Indirection
Slide 45
Slide 45 text
szymanskilukasz
Pointer points to pointer etc.
Slide 46
Slide 46 text
szymanskilukasz
Code
Slide 47
Slide 47 text
szymanskilukasz
Scalar type declarations
Slide 48
Slide 48 text
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
Slide 49
Slide 49 text
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
Slide 50
Slide 50 text
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';
}
}
Slide 51
Slide 51 text
szymanskilukasz
Slide 52
Slide 52 text
szymanskilukasz
Not Really
Slide 53
Slide 53 text
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';
}
}
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
Slide 90
Slide 90 text
szymanskilukasz
checked at compile-time
error is produced without
the function needing to
be called.
Slide 91
Slide 91 text
szymanskilukasz
Class Constant Visibility
Slide 92
Slide 92 text
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;
}
Slide 93
Slide 93 text
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;
}
Slide 94
Slide 94 text
szymanskilukasz
Nullable Types
Slide 95
Slide 95 text
szymanskilukasz
function answer(): ?int {
return null; //ok
}
function answer(): ?int {
return 42; // ok
}
function answer(): ?int {
return new stdclass(); // error
}
Slide 96
Slide 96 text
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
Slide 97
Slide 97 text
szymanskilukasz
// nullability can be removed by a subclass
interface Fooable {
function foo(): ?Fooable;
}
interface StrictFooable extends Fooable {
function foo(): Fooable; // valid
}
Slide 98
Slide 98 text
szymanskilukasz
// but it cannot be added
interface Fooable {
function foo(): Fooable;
}
interface LooseFooable extends Fooable {
function foo(): ?Fooable; // invalid
}
Slide 99
Slide 99 text
szymanskilukasz
// Valid use: loosening the nullable marker
// in a parameter:
interface Fooable {
function foo(Fooable $f);
}
interface LooseFoo extends Fooable {
function foo(?Fooable $f);
}
Slide 100
Slide 100 text
szymanskilukasz
// Invalid use: tightening
// the nullable marker in a parameter:
interface Fooable {
function foo(?Fooable $f);
}
interface StrictFoo extends Fooable {
function foo(Fooable $f);
}
Slide 101
Slide 101 text
szymanskilukasz
Iterable pseudo-type
Slide 102
Slide 102 text
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 = []) {
// ...
}
Slide 103
Slide 103 text
szymanskilukasz
Under Discussion
Slide 104
Slide 104 text
szymanskilukasz
Class Friendship
Created 2015/12/10
Slide 105
Slide 105 text
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);
}
}
Slide 106
Slide 106 text
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}";
}
}
Slide 107
Slide 107 text
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}";
}
}
szymanskilukasz
Named Parameters
Created 2013/09/06
Slide 110
Slide 110 text
szymanskilukasz
// Using positional arguments:
array_fill(0, 100, 42);
// Using named arguments:
array_fill(start_index => 0, num => 100, value => 42);
Slide 111
Slide 111 text
szymanskilukasz
htmlspecialchars($string, default, default, false);
// vs
htmlspecialchars($string, double_encode => false);
$str->contains("foo", true);
// vs
$str->contains("foo", caseInsensitive => true);
Slide 112
Slide 112 text
szymanskilukasz
Generic Types and Functions
Created 2015/04/28
Slide 113
Slide 113 text
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;
}
}
Slide 114
Slide 114 text
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;
}
}
Slide 115
Slide 115 text
szymanskilukasz
$entry = new Entry(1, 'test');
$entry = new Entry(1, 'test');
Slide 116
Slide 116 text
szymanskilukasz
In Draft
Slide 117
Slide 117 text
szymanskilukasz
Immutable classes and
properties
Slide 118
Slide 118 text
szymanskilukasz
class Email {
private $_email;
public function __construct ($email) {
// validation
$this->_email = $email;
}
public function getValue() {
return $this->_email;
}
}
Slide 119
Slide 119 text
szymanskilukasz
immutable class Email {
public $email;
public function __construct ($email) {
// validation
$this->email = $email;
}
}
Slide 120
Slide 120 text
szymanskilukasz
immutable class Email {
public $email;
public function __construct ($email) {
// validation
$this->email = $email;
}
}
Slide 121
Slide 121 text
szymanskilukasz
immutable class Email {
public $email;
public function __construct ($email) {
// validation
$this->email = $email;
}
}
Slide 122
Slide 122 text
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
Slide 123
Slide 123 text
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
Slide 124
Slide 124 text
szymanskilukasz
Property type-hints
Slide 125
Slide 125 text
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
Slide 126
Slide 126 text
szymanskilukasz
Slide 127
Slide 127 text
szymanskilukasz
Performance
Slide 128
Slide 128 text
szymanskilukasz
Code Quality
Slide 129
Slide 129 text
szymanskilukasz
Bright Future
Slide 130
Slide 130 text
szymanskilukasz
Łukasz Szymański
Development Team Lead at
@szymanskilukasz
https://www.linkedin.com/in/szymanskilukasz
https://twitter.com/szymanskilukasz
https://speakerdeck.com/szymanskilukasz