diff --git a/composer.json b/composer.json index 97d9541..82d1c2d 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,8 @@ "react/stream": "^1.0 || ^0.7 || ^0.6" }, "require-dev": { - "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3", - "phpunit/phpunit": "^7.0 || ^6.0 || ^5.7 || ^4.8.35" + "phpunit/phpunit": "^7.0 || ^6.0 || ^5.7 || ^4.8.35", + "react/child-process": "^0.6", + "react/event-loop": "^1.0 || ^0.5 || ^0.4 || ^0.3" } } diff --git a/examples/91-benchmark-count.php b/examples/91-benchmark-count.php new file mode 100644 index 0000000..45a17a4 --- /dev/null +++ b/examples/91-benchmark-count.php @@ -0,0 +1,43 @@ +on('data', function () use (&$count) { + ++$count; +}); + +$start = microtime(true); +$report = $loop->addPeriodicTimer(0.05, function () use (&$count, $start) { + printf("\r%d records in %0.3fs...", $count, microtime(true) - $start); +}); + +$decoder->on('close', function () use (&$count, $report, $loop, $start) { + $now = microtime(true); + $loop->cancelTimer($report); + + printf("\r%d records in %0.3fs => %d records/s\n", $count, $now - $start, $count / ($now - $start)); +}); + +$loop->run(); diff --git a/examples/92-benchmark-count-gzip.php b/examples/92-benchmark-count-gzip.php new file mode 100644 index 0000000..ae89625 --- /dev/null +++ b/examples/92-benchmark-count-gzip.php @@ -0,0 +1,55 @@ + IRAhandle_tweets_1.csv.gz +// +// 3) pipe compressed CSV into benchmark script: +// $ php examples/92-benchmark-count-gzip.php < IRAhandle_tweets_1.csv.gz + +use Clue\React\Csv\AssocDecoder; +use React\ChildProcess\Process; +use React\EventLoop\Factory; + +require __DIR__ . '/../vendor/autoload.php'; + +if (extension_loaded('xdebug')) { + echo 'NOTICE: The "xdebug" extension is loaded, this has a major impact on performance.' . PHP_EOL; +} + +$loop = Factory::create(); + +// This benchmark example spawns the decompressor in a child `gunzip` process +// because parsing CSV files is already mostly CPU-bound and multi-processing +// is preferred here. If the input source is slower (such as an HTTP download) +// or if `gunzip` is not available (Windows), using a built-in decompressor +// such as https://github.com/clue/reactphp-zlib would be preferable. +$process = new Process('exec gunzip', null, null, array( + 0 => STDIN, + 1 => array('pipe', 'w'), + STDERR +)); +$process->start($loop); +$decoder = new AssocDecoder($process->stdout); + +$count = 0; +$decoder->on('data', function () use (&$count) { + ++$count; +}); + +$start = microtime(true); +$report = $loop->addPeriodicTimer(0.05, function () use (&$count, $start) { + printf("\r%d records in %0.3fs...", $count, microtime(true) - $start); +}); + +$decoder->on('close', function () use (&$count, $report, $loop, $start) { + $now = microtime(true); + $loop->cancelTimer($report); + + printf("\r%d records in %0.3fs => %d records/s\n", $count, $now - $start, $count / ($now - $start)); +}); + +$loop->run();