Bumping our Stack to PHP 5.5

02cd14759ba3327f68f737131947781f?s=47 Glen Mailer
October 05, 2014

Bumping our Stack to PHP 5.5

A bit of a dev story, followed by a bit more of an ops story.

Here's what happened when we decided it was about time to get around to upgrading our PHP 5.3 app to something a bit more current.

02cd14759ba3327f68f737131947781f?s=128

Glen Mailer

October 05, 2014
Tweet

Transcript

  1. None
  2. Glen Mailer

  3. A short
 audience survey

  4. Set the Scene
 (as of September 2013)

  5. The Codebase

  6. First commit April 2010
 60k commits since According to git

  7. 9300 PHP files
 690k lines of code According to cloc

  8. 10 releases a week
 35 active committers
 10 concurrent streams


    1 deployable
  9. The Platform

  10. 8 Test Environments
 1 Staging Environment
 2 Live Environments

  11. 74 Live PHP boxes

  12. 1300 req/s peak
 500k uniques/week

  13. Why Upgrade?

  14. Using basically the same PHP version as the first commit

    with security patches
  15. PHP 5.3 is dead

  16. Bug fixes
 Performance

  17. New Features! short array syntax traits $this in closures yield

    finally
  18. None
  19. Bug #64827
 GC causes segfaults

  20. The Plan

  21. Upgrade a dev box Support 5.3 and 5.5 Pass all

    tests Upgrade 1 Test env Upgrade CI Upgrade Test & Staging Incrementally Upgrade Live
  22. Vagrant
 Chef
 Unit Tests
 Acceptance Tests

  23. Hack hack hack...

  24. 3 days later

  25. What changed?

  26. APC
 becomes
 OPcache and APCu

  27. Check for new function, fall back to old one if

    (function_exists('opcache_reset')) { opcache_reset(); } else { apc_clear_cache(); }
  28. “The PHP api will retain compatibility with APC, as will

    common configuration options, providing a drop in replacement.” APCu
  29. Not a drop in replacement

  30. APCu 4.0.1
 APCu 4.0.2
 master is closer still

  31. No more
 mysql_

  32. It will not be missed

  33. preg_replace /e
 becomes
 preg_replace_callback

  34. (string) array()
 Now raises a warning Still returns “Array”

  35. "Type-checked" function function inc($int) { if (!is_int($int)) { throw new

    InvalidArgumentException( 'Expected int, got: ' . $int ); } return $int + 1; }
  36. Unit test for type-checked function /** * @dataprovider provideIncInvalid */

    function testIncRejectsInvalid($a) { try { inc($a); $this->fail('Expected exception'); } catch (InvalidArgumentException $ex) {} } function provideIncInvalid() { return array( null, true, "string", array() ); }
  37. Simplest fix throw new InvalidArgumentException( 'Expected int, got: ' .

    json_encode($int) );
  38. $a = "string”;
 $a['index'];
 Now raises a warning

  39. // protected $a;
 ++$this->a
 Now raises a warning

  40. Progress

  41. Upgrade a dev box
 Support 5.3 and 5.5
 Pass all

    tests
 Upgrade 1 Test env
 Upgrade CI
 Upgrade Test & Staging
 Incrementally Upgrade Live
  42. Upgrade a dev box
 Support 5.3 and 5.5
 Pass all

    tests
 Upgrade 1 Test env
 Upgrade CI
 Upgrade Test & Staging
 Incrementally Upgrade Live
  43. PHPNW 2013

  44. The Rollout

  45. None
  46. None
  47. None
  48. None
  49. APCu Failures
 APCu #49: Segfaults
 APCu #19: deadlock

  50. Forwards
 or
 Backwards

  51. None
  52. Segfaults - 100 point Moving Average 7.2/s 6.0/s 4.8/s 3.6/s

    2.4/s 1.2/s Oct Nov Dec Jan
  53. None
  54. Shared Memory?
 I'm out.

  55. Can we
 leverage OPCache?

  56. The Barwell Cache

  57. function barwell_store($key, $value) { $path = BARWELL_BASE . '/' .

    md5($key); file_put_contents( $path, '<?php return ' . var_export($value, 1) ); opcache_invalidate($path); } function barwell_fetch($key) { return include(BARWELL_BASE . '/' . md5($key)); }
  58. function barwell_store_obj($key, $value) { $path = BARWELL_BASE . '/' .

    md5($key); file_put_contents( $path, '<?php return unserialize("' . serialize($value) . '")' ); opcache_invalidate($path); }
  59. Are you mad?

  60. None
  61. None
  62. Probably.

  63. Take a moment.
 Stop.
 Think.

  64. What is the problem we're trying to solve?

  65. Fast k/v access
 for hot paths

  66. How fast do we really need to be?

  67. Move almost everything over to memcached

  68. Autoload Map
 Environment Config
 Weird Zend Reflection

  69. function simple_store($key, $value) { file_put_contents( path($key), serialize($value)); } function simple_fetch($key)

    { return unserialize( file_get_contents(path($key))); }
  70. The
 Aftermath

  71. Performance

  72. Average Response Time in ms

  73. Average Memory Use in MB

  74. Average Response Time in ms
 on one API endpoint with

    minimal external calling
  75. New Features

  76. 17 Traits
 +
 4 in tests

  77. 2 uses of
 finally

  78. 37 uses of
 yield

  79. New array syntax?

  80. A few snowflake boxes are still on 5.3

  81. Have bumped minor version a couple of times since

  82. Began upgrading
 to 5.6 this week

  83. Takeaways

  84. Use configuration management tools

  85. Frequently upgrade things in small increments

  86. Shared memory is inherently complicated

  87. Monitor absolutely everything

  88. When you think you're doing something crazy
 
 You might

    be right
  89. Understand why you're doing something

  90. Fin.

  91. @glenathan https://joind.in/11801