0
Generating
Power with Yield/Jason Myers @jasonamyers
Yield, a modern language love
story
Originally Proposed in 1995, the yield keyword became official via the
RFP on June 20t...
They are HEAVILY BASED off of Python, with a nod towards the
Mozilla JS implementation and the await C# concept.
Iterator
An object that lets us traverse a container
PHP Iterator Interface
Iterator extends Traversable {
/* Methods */
abstract public mixed current ( void )
abstract public...
ArrayIterator Example
$fruits = array(
"apple" => "yummy",
"orange" => "ah ya, nice",
"grape" => "wow, I love it!",
"plum"...
Generator
a special routine that can be used to control the iteration behavior of
a loop, and yields the values one at a t...
TL;DR
A generator looks like a function but behaves like an iterator
Performant?
range(0, 1000000)
Uses over 100MB of RAM
Generator Version
function xrange($start, $limit, $step = 1) {
if ($start < $limit) {
if ($step <= 0) {
throw new LogicExc...
TL; DR
function xrange($min, $max) {
for ($i = $min; $i < $max; $i++) {
yield $i;
}
}
Sequences
function collatz($val) {
yield $val;
while ($val != 1) {
if ($val%2 == 0) {
$val /= 2;
} else {
$val = 3*$val + ...
Y U Only LOOPin?
It will work for any function that takes an Iterator or a Traversable as
argument
$arr = iterator_to_arra...
Transformations
function multiply_sequence($a, $fac) {
foreach ($a as $val) {
yield $val*$fac;
}
}
function to_html_list($...
Chaining
foreach (to_html_list(multiply_sequence(collatz(5),2)) as $val) {
echo $val,"n";
}
<li>10</li>
<li>32</li>
<li>16...
Selections
function select_pattern($input, $pattern) {
foreach ($input as $val) {
if (preg_match($pattern, $val)) {
yield ...
Breath In
function getLines($file) {
$f = fopen($file, 'r');
if (!$f) {
throw new Exception();
}
while ($line = fgets($f))...
Breath Out
function createLog($file) {
$f = fopen($file, 'a');
while (true) {
$line = yield;
fwrite($f, $line);
}
}
$log =...
Bro Remote Me!
Fake the simultaneous processing of data
Green Threads
threads that are scheduled by a virtual machine (VM/interperter?)
instead of natively by the underlying oper...
function step1() {
$f = fopen("file.txt", 'r');
while ($line = fgets($f)) {
processLine($line);
yield true;
}
}
function step2() {
$f = fopen("file2.txt", 'r');
while ($line = fgets($f)) {
processLine($line);
yield true;
}
}
function step3() {
$f = fsockopen("www.example.com", 80);
stream_set_blocking($f, false);
$headers = "GET / HTTP/1.1rn";
$...
function runner(array $steps) {
while (true) {
foreach ($steps as $key => $step) {
$step->next();
if (!$step->valid()) {
u...
ZOMG... THERE BE DRAGONS!
This relies on making sure we have no blocking IO
overREACTPHP much?
event based, non-blocking IO - ReActPHP
One More Thing
So if I can flip control, I can haz an Async?
class Buffer {
protected $reads, $data;
public function __construct() {
$this->reads = new SplQueue();
$this->data = new S...
function printer(Buffer $buffer) {
while( true ) {
$value = ( yield Util::async($buffer->read()) );
echo "Printer: ", $val...
function nested_printer(Buffer $buffer) {
for( $i = 0; $i < 5; $i++ ) {
// Yield a promise task and wait for the result - ...
$buffer = new Buffer();
$scheduler = new AsyncScheduler();
$scheduler->add(new AsyncTaskGeneratorTask(printer($buffer)));
...
$loop = ReactEventLoopFactory::create();
$scheduler = new AsyncScheduler();
$scheduler->add(new AsyncTaskRecurringTask([$l...
Async
Created by Matt Pryor, on Bitbucket
Thanks
Huge thanks to Paul M. Jones and William Golden!
THE END
@jasonamyers
Generating Power with Yield
Generating Power with Yield
Generating Power with Yield
Generating Power with Yield
Generating Power with Yield
Generating Power with Yield
Generating Power with Yield
Generating Power with Yield
Upcoming SlideShare
Loading in...5
×

Generating Power with Yield

784

Published on

My talk for the Nashville PHP Users Group August 2013 meeting.

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

  • Be the first to like this

No Downloads
Views
Total Views
784
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
2
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Generating Power with Yield"

  1. 1. Generating Power with Yield/Jason Myers @jasonamyers
  2. 2. Yield, a modern language love story Originally Proposed in 1995, the yield keyword became official via the RFP on June 20th 2013 with PHP 5.5.Generators Facebook said a Hip, Hop and Don't Stop, and did their own yield generators in HipHop PHP
  3. 3. They are HEAVILY BASED off of Python, with a nod towards the Mozilla JS implementation and the await C# concept.
  4. 4. Iterator An object that lets us traverse a container
  5. 5. PHP Iterator Interface Iterator extends Traversable { /* Methods */ abstract public mixed current ( void ) abstract public scalar key ( void ) abstract public void next ( void ) abstract public void rewind ( void ) abstract public boolean valid ( void ) } For example checkout classArrayIterator
  6. 6. ArrayIterator Example $fruits = array( "apple" => "yummy", "orange" => "ah ya, nice", "grape" => "wow, I love it!", "plum" => "nah, not me" ); $obj = new ArrayObject( $fruits ); $it = $obj->getIterator(); echo "Iterating over: " . $obj->count() . " valuesn"; while( $it->valid() ) { echo $it->key() . "=" . $it->current() . "n"; $it->next(); } Iterating over: 4 values apple=yummy orange=ah ya, nice grape=wow, I love it! plum=nah, not me
  7. 7. Generator a special routine that can be used to control the iteration behavior of a loop, and yields the values one at a time
  8. 8. TL;DR A generator looks like a function but behaves like an iterator
  9. 9. Performant? range(0, 1000000) Uses over 100MB of RAM
  10. 10. Generator Version function xrange($start, $limit, $step = 1) { if ($start < $limit) { if ($step <= 0) { throw new LogicException('Step must be +ve'); } for ($i = $start; $i <= $limit; $i += $step) { yield $i; } } else { if ($step >= 0) { throw new LogicException('Step must be -ve'); } for ($i = $start; $i >= $limit; $i += $step) { yield $i; } } } uses less than 1KB!
  11. 11. TL; DR function xrange($min, $max) { for ($i = $min; $i < $max; $i++) { yield $i; } }
  12. 12. Sequences function collatz($val) { yield $val; while ($val != 1) { if ($val%2 == 0) { $val /= 2; } else { $val = 3*$val + 1; } yield $val; } } foreach (collatz(11) as $c) { echo $c," "; } 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
  13. 13. Y U Only LOOPin? It will work for any function that takes an Iterator or a Traversable as argument $arr = iterator_to_array(collatz(11));
  14. 14. Transformations function multiply_sequence($a, $fac) { foreach ($a as $val) { yield $val*$fac; } } function to_html_list($input) { foreach ($input as $val) { yield "<li>".$val."</li>"; } }
  15. 15. Chaining foreach (to_html_list(multiply_sequence(collatz(5),2)) as $val) { echo $val,"n"; } <li>10</li> <li>32</li> <li>16</li> <li>8</li> <li>4</li> <li>2</li>
  16. 16. Selections function select_pattern($input, $pattern) { foreach ($input as $val) { if (preg_match($pattern, $val)) { yield $val; } } }
  17. 17. Breath In function getLines($file) { $f = fopen($file, 'r'); if (!$f) { throw new Exception(); } while ($line = fgets($f)) { yield $line; } fclose($f); } foreach (getLines("someFile") as $line) { doSomethingWithLine($line); }
  18. 18. Breath Out function createLog($file) { $f = fopen($file, 'a'); while (true) { $line = yield; fwrite($f, $line); } } $log = createLog($file); $log->send("First"); $log->send("Second"); $log->send("Third");
  19. 19. Bro Remote Me! Fake the simultaneous processing of data
  20. 20. Green Threads threads that are scheduled by a virtual machine (VM/interperter?) instead of natively by the underlying operating system
  21. 21. function step1() { $f = fopen("file.txt", 'r'); while ($line = fgets($f)) { processLine($line); yield true; } }
  22. 22. function step2() { $f = fopen("file2.txt", 'r'); while ($line = fgets($f)) { processLine($line); yield true; } }
  23. 23. function step3() { $f = fsockopen("www.example.com", 80); stream_set_blocking($f, false); $headers = "GET / HTTP/1.1rn"; $headers .= "Host: www.example.comrn"; $headers .= "Connection: Closernrn"; fwrite($f, $headers); $body = ''; while (!feof($f)) { $body .= fread($f, 8192); yield true; } processBody($body); }
  24. 24. function runner(array $steps) { while (true) { foreach ($steps as $key => $step) { $step->next(); if (!$step->valid()) { unset($steps[$key]); } } if (empty($steps)) return; } } runner(array(step1(), step2(), step3()));
  25. 25. ZOMG... THERE BE DRAGONS! This relies on making sure we have no blocking IO
  26. 26. overREACTPHP much? event based, non-blocking IO - ReActPHP
  27. 27. One More Thing So if I can flip control, I can haz an Async?
  28. 28. class Buffer { protected $reads, $data; public function __construct() { $this->reads = new SplQueue(); $this->data = new SplQueue(); } public function read() { if( $this->data->isEmpty() ) { $deferred = new ReactPromiseDeferred(); $this->reads->enqueue($deferred->resolver()); return $deferred->promise(); } else { return ReactPromiseWhen::resolve($this->data->dequeue()); } } public function write($str) { if( $this->reads->isEmpty() ) { $this->data->enqueue($str); } else { $this->reads->dequeue()->resolve($str); } } }
  29. 29. function printer(Buffer $buffer) { while( true ) { $value = ( yield Util::async($buffer->read()) ); echo "Printer: ", $value, PHP_EOL; yield Util::async(nested_printer($buffer)); } }
  30. 30. function nested_printer(Buffer $buffer) { for( $i = 0; $i < 5; $i++ ) { // Yield a promise task and wait for the result - this is non-blocking $value = ( yield Util::async($buffer->read()) ); echo "Nested printer: ", $value, PHP_EOL; } }
  31. 31. $buffer = new Buffer(); $scheduler = new AsyncScheduler(); $scheduler->add(new AsyncTaskGeneratorTask(printer($buffer))); $i = 0; $scheduler->add(new AsyncTaskRecurringTask( function() use($buffer, &$i) { $buffer->write(++$i); } )); $scheduler->run(); Printer: 1 Nested printer: 2 Nested printer: 3 Nested printer: 4 Nested printer: 5 Nested printer: 6 Printer: 7 Nested printer: 8 Nested printer: 9 Nested printer: 10 Nested printer: 11 Nested printer: 12 ...
  32. 32. $loop = ReactEventLoopFactory::create(); $scheduler = new AsyncScheduler(); $scheduler->add(new AsyncTaskRecurringTask([$loop, 'tick'])); $scheduler->run();
  33. 33. Async Created by Matt Pryor, on Bitbucket
  34. 34. Thanks Huge thanks to Paul M. Jones and William Golden!
  35. 35. THE END @jasonamyers
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×