static optimization of php bytecode (phpsc 2017)

74
Static Optimization of PHP Bytecode Nikita Popov

Upload: nikita-popov

Post on 22-Jan-2018

5.070 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Static Optimization of PHP bytecode (PHPSC 2017)

Static Optimizationof

PHP BytecodeNikita Popov

Page 2: Static Optimization of PHP bytecode (PHPSC 2017)

2

154

192 196212

476 486501

0

100

200

300

400

500

PHP 5.3 PHP 5.4 PHP 5.5 PHP 5.6 PHP 7.0 PHP 7.1 PHP 7.2

Req

/ S

ec

Stolen from Rasmus

Wordpress 4.8-alpha @ 20c

Page 3: Static Optimization of PHP bytecode (PHPSC 2017)

3

154

192 196212

476 486501

0

100

200

300

400

500

PHP 5.3 PHP 5.4 PHP 5.5 PHP 5.6 PHP 7.0 PHP 7.1 PHP 7.2

Req

/ S

ec

Stolen from Rasmus

Wordpress 4.8-alpha @ 20c

Page 4: Static Optimization of PHP bytecode (PHPSC 2017)

4

$a = 42;$b = 24;echo $a + $b;

Code

Page 5: Static Optimization of PHP bytecode (PHPSC 2017)

5

ASSIGN $a, 42ASSIGN $b, 24

T0 = ADD $a, $bECHO T0

$a = 42;$b = 24;echo $a + $b;

Compile

CodeOpcodes

Page 6: Static Optimization of PHP bytecode (PHPSC 2017)

6

ASSIGN $a, 42ASSIGN $b, 24

T0 = ADD $a, $bECHO T0

$a = 42;$b = 24;echo $a + $b;

Compile VirtualMachine

Execute

CodeOpcodes

Page 7: Static Optimization of PHP bytecode (PHPSC 2017)

7

ASSIGN $a, 42ASSIGN $b, 24

T0 = ADD $a, $bECHO T0

$a = 42;$b = 24;echo $a + $b;

Compile VirtualMachine

Execute

CodeOpcodes

Optimize

Page 8: Static Optimization of PHP bytecode (PHPSC 2017)

8

ASSIGN $a, 42ASSIGN $b, 24

T0 = ADD $a, $bECHO T0

$a = 42;$b = 24;echo $a + $b;

Compile VirtualMachine

Execute

CodeOpcodes

Optimize

SSA

Page 9: Static Optimization of PHP bytecode (PHPSC 2017)

9

Optimizations

Page 10: Static Optimization of PHP bytecode (PHPSC 2017)

10

$c = $a + $b;

T0 = ADD $a, $bASSIGN $c, T0

Optimizations

Specialization

Page 11: Static Optimization of PHP bytecode (PHPSC 2017)

11

$c = $a + $b;

T0 = ADD $a, $bASSIGN $c, T0

$c = ADD $a, $b

Optimizations

Specialization

Page 12: Static Optimization of PHP bytecode (PHPSC 2017)

12

$c = $a + $b;

T0 = ADD $a, $bASSIGN $c, T0

$c = ADD $a, $b

$c = ADD_INT $a, $b

Optimizations

Specialization

Page 13: Static Optimization of PHP bytecode (PHPSC 2017)

13

$c = $a + $b;

T0 = ADD $a, $bASSIGN $c, T0

$c = ADD $a, $b

$c = ADD_INT $a, $b

$c = ADD_INT_NO_OVERFLOW $a, $b

Optimizations

Specialization

Page 14: Static Optimization of PHP bytecode (PHPSC 2017)

14

Optimizations

Constant Propagation

$a = 2;$b = $a + 1;echo $a * $b;

Page 15: Static Optimization of PHP bytecode (PHPSC 2017)

15

Optimizations

Constant Propagation

$a = 2;$b = 3;echo 6;

Page 16: Static Optimization of PHP bytecode (PHPSC 2017)

16

Optimizations

Constant Propagation & Dead Code Elimination

echo 6;

Page 17: Static Optimization of PHP bytecode (PHPSC 2017)

17

Optimizations

Inlining

Page 18: Static Optimization of PHP bytecode (PHPSC 2017)

18

Optimizations

Inlining

function test() {var_dump(div(4, 2));

}

function div($a, $b) {if ($b == 0) {

return -1;}return $a / $b;

}

Page 19: Static Optimization of PHP bytecode (PHPSC 2017)

19

Optimizations

Inlining

function test() {var_dump(div(4, 2));

}

function div($a, $b) {if ($b == 0) {

return -1;}return $a / $b;

}

function test() {$a = 4;$b = 2;if ($b == 0) {

$retval = -1;goto end;

}$retval = $a / $b;goto end;

end:unset($a, $b);var_dump($retval);

}

Page 20: Static Optimization of PHP bytecode (PHPSC 2017)

20

Optimizations

Inlining + CP

function test() {var_dump(div(4, 2));

}

function div($a, $b) {if ($b == 0) {

return -1;}return $a / $b;

}

function test() {$a = 4;$b = 2;

$retval = 2;goto end;

end:unset($a, $b);var_dump(2);

}

Page 21: Static Optimization of PHP bytecode (PHPSC 2017)

21

Optimizations

Inlining + CP + DCE

function test() {var_dump(div(4, 2));

}

function div($a, $b) {if ($b == 0) {

return -1;}return $a / $b;

}

function test() {

var_dump(2);}

Page 22: Static Optimization of PHP bytecode (PHPSC 2017)

22

SSA Formand

Type Inference

Page 23: Static Optimization of PHP bytecode (PHPSC 2017)

23

$x = 42;if (cond) {

$x = 42.0;var_dump($x);

} else {$x = "42";var_dump($x);

}

var_dump($x);

Static Single Assignment (SSA) Form

Page 24: Static Optimization of PHP bytecode (PHPSC 2017)

24

$x = 42;if (cond) {

$x = 42.0;var_dump($x);

} else {$x = "42";var_dump($x);

}

var_dump($x);

Static Single Assignment (SSA) Form

Type of $x:int|float|string

Page 25: Static Optimization of PHP bytecode (PHPSC 2017)

25

$x = 42;if (cond) {

$x = 42.0;var_dump($x);

} else {$x = "42";var_dump($x);

}

var_dump($x);

Static Single Assignment (SSA) Form

Type of $x here:int

Type of $x here:float

Type of $x here:string

Type of $x here:float|string

Page 26: Static Optimization of PHP bytecode (PHPSC 2017)

26

$x = 42;if (cond) {

$x = 42.0;var_dump($x);

} else {$x = "42";var_dump($x);

}

var_dump($x);

Static Single Assignment (SSA) Form

Page 27: Static Optimization of PHP bytecode (PHPSC 2017)

27

Static Single Assignment (SSA) Form

$x_1 = 42;if (cond) {

$x_2 = 42.0;var_dump($x_2);

} else {$x_3 = "42";var_dump($x_3);

}

var_dump($x_?);

Page 28: Static Optimization of PHP bytecode (PHPSC 2017)

28

Static Single Assignment (SSA) Form

$x_1 = 42;if (cond) {

$x_2 = 42.0;var_dump($x_2);

} else {$x_3 = "42";var_dump($x_3);

}$x_4 = phi($x_2, $x_3);var_dump($x_4);

Page 29: Static Optimization of PHP bytecode (PHPSC 2017)

29

Static Single Assignment (SSA) Form

$x_1 : int

$x_2 : float

$x_3 : string

$x_4 : float|string

$x_1 = 42;if (cond) {

$x_2 = 42.0;var_dump($x_2);

} else {$x_3 = "42";var_dump($x_3);

}$x_4 = phi($x_2, $x_3);var_dump($x_4);

Page 30: Static Optimization of PHP bytecode (PHPSC 2017)

30

Type Inference

$x = 42;do {

$y = $x;$x = $x + 3.14;

} while (cond);

var_dump($y);

Page 31: Static Optimization of PHP bytecode (PHPSC 2017)

31

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

Page 32: Static Optimization of PHP bytecode (PHPSC 2017)

32

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

Page 33: Static Optimization of PHP bytecode (PHPSC 2017)

33

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : ∅$y_1 : ∅$x_3 : ∅

Page 34: Static Optimization of PHP bytecode (PHPSC 2017)

34

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : ∅$y_1 : ∅$x_3 : ∅

Page 35: Static Optimization of PHP bytecode (PHPSC 2017)

35

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : int$y_1 : ∅$x_3 : ∅

Page 36: Static Optimization of PHP bytecode (PHPSC 2017)

36

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : int$y_1 : ∅$x_3 : ∅

Page 37: Static Optimization of PHP bytecode (PHPSC 2017)

37

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : int$y_1 : int$x_3 : float

Page 38: Static Optimization of PHP bytecode (PHPSC 2017)

38

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : int$y_1 : int$x_3 : float

Page 39: Static Optimization of PHP bytecode (PHPSC 2017)

39

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : int|float$y_1 : int$x_3 : float

Page 40: Static Optimization of PHP bytecode (PHPSC 2017)

40

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : int|float$y_1 : int$x_3 : float

Page 41: Static Optimization of PHP bytecode (PHPSC 2017)

41

Type Inference

$x_1 = 42;do {

$x_2 = phi($x_1, $x_3);$y_1 = $x_2;$x_3 = $x_2 + 3.14;

} while (cond);

var_dump($y_1);

$x_1 : int

$x_2 : int|float$y_1 : int|float$x_3 : float

Page 42: Static Optimization of PHP bytecode (PHPSC 2017)

42

Type Inference

$a = 2**62;$b = 2**62;var_dump($a + $b);// float(9.2233720368548E+18)

Page 43: Static Optimization of PHP bytecode (PHPSC 2017)

43

Type Inference

$a = 2**62;$b = 2**62;var_dump($a + $b);// float(9.2233720368548E+18)

Accurate type inference requires value range inference!

Page 44: Static Optimization of PHP bytecode (PHPSC 2017)

44

Type Inference

$a = 2**62;$b = 2**62;var_dump($a + $b);// float(9.2233720368548E+18)

Accurate type inference requires value range inference!

Same basic concept as type inference,but technically more involved…

Page 45: Static Optimization of PHP bytecode (PHPSC 2017)

45

Optimization obstacles

Page 46: Static Optimization of PHP bytecode (PHPSC 2017)

46

eval()?

variable variables?

Page 47: Static Optimization of PHP bytecode (PHPSC 2017)

47

eval()?

variable variables?

Don't optimize functions using those!

Page 48: Static Optimization of PHP bytecode (PHPSC 2017)

48

function test() {$foobar = 42;func($foobar);var_dump($foobar); // int(42)?

}

References

Page 49: Static Optimization of PHP bytecode (PHPSC 2017)

function func(&$ref) {$ref = 24;

}

function test() {$foobar = 42;func($foobar);var_dump($foobar); // int(42)? nope!

}

49

References

Page 50: Static Optimization of PHP bytecode (PHPSC 2017)

// file1.phpfunction func(&$ref) {

$ref = 24;}

// file2.phpfunction test() {

$foobar = 42;func($foobar);var_dump($foobar); // int(42)? nope!

}

50

References

Page 51: Static Optimization of PHP bytecode (PHPSC 2017)

51

References

Files compiledindependently

// file1.phpfunction func(&$ref) {

$ref = 24;}

// file2.phpfunction test() {

$foobar = 42;func($foobar);var_dump($foobar); // int(42)? nope!

}

Page 52: Static Optimization of PHP bytecode (PHPSC 2017)

52

The devil is in the details…

Page 53: Static Optimization of PHP bytecode (PHPSC 2017)

53

$a = 1;$b = 1;var_dump($a + $b); // ???

Page 54: Static Optimization of PHP bytecode (PHPSC 2017)

54

// file1.php$a = 1;$b = 1;var_dump($a + $b); // ???

// file2.php// EVIL CODE HERErequire 'file1.php';

Page 55: Static Optimization of PHP bytecode (PHPSC 2017)

55

// file1.php$a = 1;$b = 1;var_dump($a + $b); // ???

// file2.php$b = new class {

function __destruct() {$GLOBALS['b'] = 2;

}};require 'file1.php'; // int(3)

Page 56: Static Optimization of PHP bytecode (PHPSC 2017)

56

Pseudo-main scope is a lost cause!

Page 57: Static Optimization of PHP bytecode (PHPSC 2017)

57

function test() {$obj = new stdClass;$obj->prop = 42;// Code not using $obj in any wayvar_dump($obj->prop); // ???

}

Page 58: Static Optimization of PHP bytecode (PHPSC 2017)

58

function test() {$obj = new stdClass;$obj->prop = 42;// Code not using $obj in any wayvar_dump($obj->prop); // ???

}

set_error_handler(function($_1, $_2, $_3, $_4, $scope) {$scope['obj']->prop = "foobar";

});

Page 59: Static Optimization of PHP bytecode (PHPSC 2017)

59

function test() {$obj = new stdClass;$obj->prop = 42;// Code not using $obj in any wayvar_dump($obj->prop); // ???

}

set_error_handler(function($_1, $_2, $_3, $_4, $scope) {$scope['obj']->prop = "foobar";

});

Could generate warning

Page 60: Static Optimization of PHP bytecode (PHPSC 2017)

60

function test() {$obj = new stdClass;$obj->prop = 42;// Code not using $obj in any wayvar_dump($obj->prop); // ???

}

set_error_handler(function($_1, $_2, $_3, $_4, $scope) {$scope['obj']->prop = "foobar";

});

Could generate warning

95% of instructions havesome error condition

Page 61: Static Optimization of PHP bytecode (PHPSC 2017)

61

Object properties (and references)are a lost cause :(

Page 62: Static Optimization of PHP bytecode (PHPSC 2017)

• Constant Propagation, Dead Code Elimination, etc. only really effective with inlining

62

Inlining

Page 63: Static Optimization of PHP bytecode (PHPSC 2017)

• Constant Propagation, Dead Code Elimination, etc. only really effective with inlining

• Inlining only works if callee is known• Only within single file (thanks opcache)

• Non-private/final instance methods can be overridden

63

Inlining

Page 64: Static Optimization of PHP bytecode (PHPSC 2017)

• Constant Propagation, Dead Code Elimination, etc. only really effective with inlining

• Inlining only works if callee is known• Only within single file (thanks opcache)

• Non-private/final instance methods can be overridden

• Backtraces change

64

Inlining

Page 65: Static Optimization of PHP bytecode (PHPSC 2017)

65

Results

Page 66: Static Optimization of PHP bytecode (PHPSC 2017)

66

Results (microbenchmarks)

Page 67: Static Optimization of PHP bytecode (PHPSC 2017)

67

Results (libraries/applications)

• phpseclib RSA enc/dec: 18%

• Aerys Huffman coding: 8%

Page 68: Static Optimization of PHP bytecode (PHPSC 2017)

68

Results (libraries/applications)

• phpseclib RSA enc/dec: 18%

• Aerys Huffman coding: 8%

• WordPress: 3%

• MediaWiki: 1%

Page 69: Static Optimization of PHP bytecode (PHPSC 2017)

69

Type Inference Stats

Page 70: Static Optimization of PHP bytecode (PHPSC 2017)

70

State

• SSA + Type Inference in PHP 7.1

• Specialization in PHP 7.1

Page 71: Static Optimization of PHP bytecode (PHPSC 2017)

71

State

• SSA + Type Inference in PHP 7.1

• Specialization in PHP 7.1

• Inlining, Constant Propagation, DCE, etc. not in PHP 7.1

Page 72: Static Optimization of PHP bytecode (PHPSC 2017)

72

State

• SSA + Type Inference in PHP 7.1

• Specialization in PHP 7.1

• Inlining, Constant Propagation, DCE, etc. not in PHP 7.1

• Currently work underway on dynasm JIT using SSA + type inference framework

Page 73: Static Optimization of PHP bytecode (PHPSC 2017)

73

State

• SSA + Type Inference in PHP 7.1

• Specialization in PHP 7.1

• Inlining, Constant Propagation, DCE, etc. not in PHP 7.1

• Currently work underway on dynasm JIT using SSA + type inference framework

Nikita Popov, Biagio Cosenza, Ben Juurlink, and Dmitry Stogov.Static optimization in PHP 7. In CC'17, pages 65-75. ACM, 2017.http://nikic.github.io/pdf/cc17_static_optimization.pdf

Page 74: Static Optimization of PHP bytecode (PHPSC 2017)

74

@nikita_ppv

https://joind.in/talk/57be5

Questions?