Multi-tasking in PHP

11,509 views

Published on

Presentation to the Atlanta PHP user group's December 2012 meetup

Published in: Technology
0 Comments
4 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
11,509
On SlideShare
0
From Embeds
0
Number of Embeds
2,759
Actions
Shares
0
Downloads
0
Comments
0
Likes
4
Embeds 0
No embeds

No notes for slide

Multi-tasking in PHP

  1. 1. Multi-tasking in PHPWednesday, December 5, 12
  2. 2. About Me • Formerly CTO for Company52 • Currently work at Brandmovers on Northside Drive • Self-taught • Full-time geek since 2007Wednesday, December 5, 12
  3. 3. Wednesday, December 5, 12
  4. 4. Use Cases • System resources are not the bottleneck • Batch processing involving an API: • E-Mail • Geocoding • Electronic billing • DaemonsWednesday, December 5, 12
  5. 5. Alternatives • Gearman • curl_multi_* • Other scripting languagesWednesday, December 5, 12
  6. 6. TheoryWednesday, December 5, 12
  7. 7. Two ways to multi-task Multi-processing Multi-threading Separate memory Shared memory Errors are isolated Errors are not isolated Separate permissions Same permissions Linux/UNIX WindowsWednesday, December 5, 12
  8. 8. Multiprocessing Multithreading Process 1 program Process 1 program Thread 1 state: virtual memory PC, stack processor state: virtual PC, stack processor Process 2 program Thread 2 state: virtual PC, stack processor memory state: virtual memory PC, stack processor Thread m state: virtual Process n program PC, stack processor state: virtual memory PC, stack processor Process n Courtesy www.fmc-modeling.orgWednesday, December 5, 12
  9. 9. Multiprocessing • “The simultaneous execution of two or more programs by separate CPUs under integrated control.” • Clones the entire process, except resources • Copy-on-write memoryWednesday, December 5, 12
  10. 10. Forking Diagram courtesy cnx.orgWednesday, December 5, 12
  11. 11. Child Process • A cloned copy of a parent process • Receives a new process ID and a parent process ID • Does some work • DiesWednesday, December 5, 12
  12. 12. ...sort of. Photo Credit: Christopher Brian (2011 Toronto Zombie Walk)Wednesday, December 5, 12
  13. 13. Parent Responsibilities • Reproduction • Monitors child process status • “Reap” zombie processesWednesday, December 5, 12
  14. 14. Process Signals Signal Description SIGCHLD Child process died SIGINT User Interrupt SIGTERM Terminate SIGKILL Forcibly terminateWednesday, December 5, 12
  15. 15. PHP ImplementationWednesday, December 5, 12
  16. 16. Requirements • Unix-like operating system • PHP 4.1+ • PHP PCNTL extension (compile with --enable-pcntl) • PHP Semaphore extension, optional (--enable-sysvsem, --enable-sysvshm, --enable-sysvmsg) • Plenty of memory • Multiple CPU coresWednesday, December 5, 12
  17. 17. Overview 1. Define signal handlers 2. Fetch a dataset 3. Fork off one child process for each item 4. Stop forking when a threshold is reached, and sleep 5. Reap a child process whenever SIGCHLD is received 6. If there’s more work to do, fork more processes 7. When all child processes have been reaped, terminateWednesday, December 5, 12
  18. 18. declare(ticks = 1); // Setup our signal handlers pcntl_signal(SIGTERM, "signal_handler"); pcntl_signal(SIGINT,  "signal_handler"); pcntl_signal(SIGCHLD, "signal_handler");Wednesday, December 5, 12
  19. 19. function signal_handler($signal) { switch ($signal) { case SIGINT: case SIGTERM: // kill all child processes exit(0); case SIGCHLD: // reap a child process reap_child(); break; } }Wednesday, December 5, 12
  20. 20. $pid = pcntl_fork(); switch($pid) { case 0: // Child process call_user_func($callback, $data); posix_kill(posix_getppid(), SIGCHLD); exit; case -1: // Parent process, fork failed throw new Exception("Out of memory!"); default: // Parent process, fork succeeded $processes[$pid] = TRUE; }Wednesday, December 5, 12
  21. 21. Repeat for each unit of workWednesday, December 5, 12
  22. 22. function reap_child() { // Check if any child process has terminated, // and if so remove it from memory $pid = pcntl_wait($status, WNOHANG); if ($pid < 0) { throw new Exception("Out of memory"); } elseif ($pid > 0) { unset($processes[$pid]); } }Wednesday, December 5, 12
  23. 23. Demo Time! http://gist.github.com/4212160Wednesday, December 5, 12
  24. 24. Wednesday, December 5, 12
  25. 25. DON’T: • DON’T fork a web process (CLI only!) • DON’T overload your system • DON’T open resources before forking • DO respect common POSIX signals • DO remove zombie processes • DO force new database connections in children mysql_reconnect($s, $u, $p, TRUE);Wednesday, December 5, 12
  26. 26. ChallengesWednesday, December 5, 12
  27. 27. Race Conditions • A logic bug where the result is affected by the sequence or timing of uncontrollable events • Adding debug logic can change timing • Dirty reads • Lost data • Unpredictable behavior • Deadlocks, hanging, crashingWednesday, December 5, 12
  28. 28. Wednesday, December 5, 12
  29. 29. Wednesday, December 5, 12
  30. 30. Solutions • Handle I/O in the parent process exclusively • Manage resources with semaphores and/or mutexesWednesday, December 5, 12
  31. 31. Semaphores • Semaphore = atomically updated counter • Mutex = binary semaphore with ownership • PHP: sem_get(), sem_release() • Transactional databases use semaphoresWednesday, December 5, 12
  32. 32. Deadlocks Image credit: csunplugged.orgWednesday, December 5, 12
  33. 33. Bonus SlidesWednesday, December 5, 12
  34. 34. Shared Memory • Advanced inter-process communication • Pass data back to the parent process • PHP Shared Memory extension (--enable-shmop) • PHP System V Shared Memory extension (--enable-sysvshm) • More robust • Compatible with other languagesWednesday, December 5, 12
  35. 35. Daemonization • Fork, kill parent • Orphaned child process continues running • Signal and error handling are critical • Server daemons usually fork child processes to handle requestsWednesday, December 5, 12
  36. 36. Wednesday, December 5, 12
  37. 37. Thank You! @compwright http://bit.ly/atlphpmWednesday, December 5, 12

×