@ 2014-03-28T16:37:08Z <?php
function extract_docblocks($data) {
$inBlock = false;
$forceNewItem = true;
$currentBlock = array();
$blocks = array();
foreach (preg_split('/[\r\n]+/', $data) as $line) {
$line = trim($line);
if (!$inBlock) {
if ($line === '/**') {
$inBlock = true;
}
continue;
}
if ($line[0] !== '*') {
$inBlock = false;
$forceNewItem = true;
$currentBlock = array();
continue;
}
if ($line === '*/') {
$inBlock = false;
$forceNewItem = true;
$blocks[] = $currentBlock;
$currentBlock = array();
continue;
}
$line = trim(substr($line, 1));
if ($line[0] === '@' || $forceNewItem) {
$forceNewItem = false;
$currentBlock[] = $line;
} else if ($line === '') {
$forceNewItem = true;
} else {
$currentBlock[count($currentBlock) - 1] .= "\n" . $line;
}
}
return $blocks;
}
$str = <<<CLASS
<?php
/**
* Class EventLoop
*
* This is not the fastest event loop implementation in the world, at least
* partially because it's been stupidified for PHP4. It's not really for high
* performance asyncSaucezOMG though, so it shouldn't matter.
*/
class EventLoop
{
/**
* @var EventLoopConfig
*/
var $config;
/**
* @var EventLoopLogger
* @access private
*/
var $_logger;
/**
* @var WorkerPoolFactory
*/
var $_workerPoolFactory;
/**
* @var array
* @access private
*/
var $_streamWatchers = array(
'read' => array(
'streams' => array(),
'callbacks' => array(),
),
'write' => array(
'streams' => array(),
'callbacks' => array(),
),
'except' => array(
'streams' => array(),
'callbacks' => array(),
),
);
/**
* @var int
* @access private
*/
var $_streamWatcherCount = 0;
/**
* @var Scheduler
* @access private
*/
var $_scheduler;
/**
* @var WorkerPool
* @access private
*/
var $_dynamicWorkerPool;
/**
* @var WorkerPool
* @access private
*/
var $_dnsWorkerPool;
/**
* @var StreamHandler[]
* @access private
*/
var $_streamHandlers = array();
/**
* @var bool
* @access private
*/
var $_running = false;
/**
* Constructor
*
* @param WorkerPoolFactory $workerPoolFactory
* @param EventLoopConfig $config
* @param EventLoopLogger $logger
* @param SchedulerFactory $schedulerFactory
* @param StreamHandler $socketStreamHandler
*/
function EventLoop(&$workerPoolFactory, &$config, &$logger, &$schedulerFactory, &$socketStreamHandler)
{
$this->config = &$config;
$this->_logger = &$logger;
$this->_workerPoolFactory = &$workerPoolFactory;
$this->_scheduler = &$schedulerFactory->create($this->_logger);
$this->registerStreamHandler($socketStreamHandler, array('tcp', 'udp', 'unix'));
$this->_dynamicWorkerPool = &$workerPoolFactory->create($this, $this->config->workers, $this->_logger, 'Dynamic');
$config->dns->normalizeInheritableProperties($this->config->workers);
$this->_dnsWorkerPool = &$workerPoolFactory->create($this, $this->config->dns, $this->_logger, 'DNS');
}
/**
* Get the current time as a float
*
* @return float
* @access private
*/
function _now()
{
list($usec, $sec) = explode(' ', microtime());
return ((float)$usec + (float)$sec);
}
/**
* Check whether at least one client socket or scheduled item is active
*
* @return bool
* @access private
*/
function _isActive()
{
return $this->_streamWatcherCount || $this->_scheduler->isActive();
}
/**
* Get the time until there is something to do
*
* @return float|null
* @access private
*/
function _getNextActivityTime()
{
$candidates = array();
if (null !== $time = $this->_scheduler->getNextActivityTime()) {
$candidates[] = $time;
}
if (null !== $time = $this->_dynamicWorkerPool->getNextActivityTime()) {
$candidates[] = $time;
}
if (null !== $time = $this->_dnsWorkerPool->getNextActivityTime()) {
$candidates[] = $time;
}
return $candidates ? max(min($candidates), 0) : null;
}
/**
* Sleep until the next scheduled item is due to be executed
*
* @access private
*/
function _awaitNextActivity($timeout)
{
if ($timeout) {
$this->_logger->debug(null, 'Waiting until next scheduled activity, timeout: %f', $timeout);
usleep(floor($timeout * 1000000));
}
}
/**
* Process I/O on all active streams
*
* @access private
*/
function _processStreams($timeout)
{
$streams = array(
'read' => $this->_streamWatchers['read']['streams'],
'write' => $this->_streamWatchers['write']['streams'],
'except' => $this->_streamWatchers['except']['streams'],
);
if ($timeout !== null) {
$secs = floor($timeout);
$usecs = floor(($timeout - $secs) * 1000000);
} else {
$secs = $usecs = null;
}
$this->_logger->debug(
null, 'select() watching %d streams for activity (read: %d, write: %d, except: %d), timeout: %s',
count($streams['read']) + count($streams['write']) + count($streams['except']),
count($streams['read']), count($streams['write']), count($streams['except']),
$secs === null ? 'NULL' : "{$secs}s {$usecs}u"
);
$count = stream_select($streams['read'], $streams['write'], $streams['except'], $secs, $usecs);
if ($count === false) {
$this->_logger->error(null, 'select() operation failed!');
exit(1);
} else if ($count === 0) {
$this->_logger->debug(null, 'select() returned 0 streams with activity');
return;
}
$this->_logger->debug(
null, 'select() returned %d streams with activity (read: %d, write: %d, except: %d)',
$count, count($streams['read']), count($streams['write']), count($streams['except'])
);
foreach (array('read', 'write', 'except') as $op) {
foreach ($streams[$op] as $stream) {
$id = (int) $stream;
if (isset($this->_streamWatchers[$op]['callbacks'][$id])) {
call_user_func($this->_streamWatchers[$op]['callbacks'][$id], $stream);
}
}
}
}
/**
* Add a watcher for a stream
*
* @param string $op
* @param resource $stream
* @param callable $callback
* @return bool
* @access module
*/
function _addStreamWatcher($op, $stream, $callback)
{
$id = (int) $stream;
$op = strtolower($op);
if (!isset($this->_streamWatchers[$op])) {
$this->_logger->debug(null, 'Failed to add %s watcher on stream #%d: unknown op', $op, $id);
return false;
} else if (!is_resource($stream)) {
$this->_logger->debug(null, 'Failed to add %s watcher on stream #%d: not a valid stream resource', $op, $id);
return false;
} else if (!is_callable($callback)) {
$this->_logger->debug(null, 'Failed to add %s watcher on stream #%d: invalid callback', $op, $id);
return false;
}
if (!isset($this->_streamWatchers[$op]['streams'][$id])) {
$this->_streamWatchers[$op]['streams'][$id] = $stream;
$this->_streamWatcherCount++;
} else {
$this->_logger->debug(null, 'Overwrote %s watcher on stream #%d', $op, $id);
}
$this->_streamWatchers[$op]['callbacks'][$id] = $callback;
$this->_logger->debug(null, 'Added %s watcher on stream #%d, watchers: %d', $op, $id, $this->_streamWatcherCount);
return true;
}
/**
* Remove a watcher for a stream or stream ID
*
* @param string $op
* @param resource|int $stream
* @access module
*/
function _removeStreamWatcher($op, $stream)
{
$id = (int) $stream;
$op = strtolower($op);
if (isset($this->_streamWatchers[$op]['streams'][$id])) {
unset($this->_streamWatchers[$op]['streams'][$id], $this->_streamWatchers[$op]['callbacks'][$id]);
$this->_streamWatcherCount--;
$this->_logger->debug(null, 'Removed %s watcher on stream #%d, watchers: %d', $op, $id, $this->_streamWatcherCount);
} else {
$this->_logger->debug(null, 'Could not remove %s watcher on stream #%d: not registered', $op, $id);
}
}
/**
* Clean up and shut down the event loop
*/
function _shutdown()
{
$this->_logger->info(null, 'Shutting down event loop');
// Remove all stream watchers apart from workers
foreach (array('read', 'write', 'except') as $op) {
foreach ($this->_streamWatchers[$op]['callbacks'] as $id => $callback) {
if (!is_array($callback) || !is_a($callback[0], 'WorkerParentEndpoint')) {
$this->_removeStreamWatcher($op, $id);
}
}
}
// Empty the schedule
$this->_scheduler->shutdown();
// Send all workers a terminate signal
$this->_dynamicWorkerPool->shutdown();
$this->_dnsWorkerPool->shutdown();
// Let workers terminate gracefully
while ($this->_streamWatcherCount > 0) {
$this->_processStreams($this->_getNextActivityTime());
$this->_scheduler->processActivity();
}
}
/**
* Register a handler for a stream wrapper or set of wrappers
*
* @param StreamHandler $handler
* @param array $schemes
* @return bool
*/
function registerStreamHandler(&$handler, $schemes)
{
if (!is_a($handler, 'StreamHandler')) {
return false;
}
foreach ($schemes as $scheme) {
$this->_streamHandlers[strtolower($scheme)] = &$handler;
}
return true;
}
/**
* Create a new stream
*
* @param string $address
* @return SocketStream
*/
function &openStream($address)
{
if (!$url = parse_url($address)) {
$this->_logger->warn(null, 'Unable to parse stream URL %s: Parse failed', $address);
return null;
} else if (!isset($url['scheme'])) {
$this->_logger->warn(null, 'Unable to parse stream URL %s: Missing scheme', $address);
return null;
}
$scheme = strtolower($url['scheme']);
if (!isset($this->_streamHandlers[$scheme])) {
$this->_logger->warn(null, 'No stream handler registered for URI scheme: %s', $scheme);
return null;
}
$stream = &$this->_streamHandlers[$scheme]->createStream($this, $url);
return $stream;
}
/**
* Schedule a job to be run asynchronously in a worker
*
* @param string $method
* @param mixed ...$args
* @return AsyncJob
*/
function &async($method)
{
$args = func_get_args();
$job = &new AsyncJob($method, array_slice($args, 1));
$this->_dynamicWorkerPool->pushJob($job);
$this->_logger->info(null, 'Queued async job, method: %s', $method);
return $job;
}
/**
* Resolve a host name to an IP address asynchronously
*
* @param string $host
* @param callable $callback
* @param bool $returnHost
*/
function resolveHost($host, $callback, $returnHost = false)
{
if ($host === '255.255.255.255' || ip2long($host) !== -1) {
$this->in(0, $callback, $returnHost ? array($host, $host) : array($host));
} else {
$job = &new AsyncJob('DNSWorker::resolve', array($host));
$this->_dnsWorkerPool->pushJob($job);
$job->on('complete', $callback, $returnHost ? array($host) : array());
$job->on('error', $callback, $returnHost ? array($host, null) : array(null));
}
}
/**
* Schedule a callback to be execute after a specified number of microseconds
*
* @param int $usecs
* @param callable $callback
* @param array $args
* @return int
*/
function in($usecs, $callback, $args = array())
{
return $this->_scheduler->createItem($this->_now() + ($usecs / 1000000), $callback, $args);
}
/**
* Schedule a callback to execute at a specified timestamp
*
* @param float $timestamp
* @param callable $callback
* @param array $args
* @return int
*/
function at($timestamp, $callback, $args = array())
{
return $this->_scheduler->createItem($timestamp, $callback, $args);
}
/**
* Schedule a recurring callback to execute after a specified number of microseconds
*
* @param int $usecs
* @param callable $callback
* @param array $args
* @return int
*/
function every($usecs, $callback, $args = array())
{
$secs = $usecs / 1000000;
return $this->_scheduler->createItem($this->_now() + $secs, $callback, $args, $secs);
}
/**
* Cancel a scheduled callback
*
* @param int $id
* @return bool
*/
function cancel($id)
{
return $this->_scheduler->removeItem($id);
}
/**
* Execute the event loop
*/
function run()
{
$this->_logger->info(null, 'Starting event loop');
$this->_running = true;
// Main loop
while ($this->_running && $this->_isActive()) {
$timeout = $this->_getNextActivityTime();
if ($this->_streamWatcherCount > 0) {
$this->_processStreams($timeout);
} else {
$this->_awaitNextActivity($timeout);
}
$this->_dynamicWorkerPool->processActivity();
$this->_dnsWorkerPool->processActivity();
$this->_scheduler->processActivity();
}
$this->_running = false;
$this->_shutdown();
$this->_logger->info(null, 'Event loop terminated');
}
/**
* Check whether the event loop is running
*
* @return bool
*/
function isRunning()
{
return $this->_running;
}
/**
* Stop the event loop after the current iteration
*/
function stop()
{
$this->_logger->debug(null, 'Stopping event loop');
$this->_running = false;
}
}
CLASS;
print_r(extract_docblocks($str));
Enable javascript to submit You have javascript disabled. You will not be able to edit any code.
Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).
Version System time (s) User time (s) Memory (MiB) 5.4.26 0.003 0.060 19.09 5.4.25 0.017 0.073 18.99 5.4.24 0.010 0.057 18.99 5.4.23 0.017 0.063 18.94 5.4.22 0.017 0.050 19.09 5.4.21 0.007 0.063 18.97 5.4.20 0.007 0.053 19.02 5.4.19 0.013 0.053 18.64 5.4.18 0.020 0.047 18.94 5.4.17 0.013 0.050 18.77 5.4.16 0.020 0.043 18.77 5.4.15 0.013 0.050 18.95 5.4.14 0.003 0.063 16.31 5.4.13 0.007 0.047 16.30 5.4.12 0.007 0.073 16.30 5.4.11 0.010 0.047 16.47 5.4.10 0.007 0.050 16.34 5.4.9 0.010 0.053 16.36 5.4.8 0.013 0.060 16.40 5.4.7 0.007 0.073 16.38 5.4.6 0.010 0.050 16.53 5.4.5 0.000 0.077 16.37 5.4.4 0.007 0.070 16.60 5.4.3 0.003 0.050 16.34 5.4.2 0.010 0.073 16.48 5.4.1 0.017 0.063 16.36 5.4.0 0.020 0.043 15.67 5.3.28 0.003 0.057 14.63 5.3.27 0.013 0.050 14.72 5.3.26 0.020 0.050 14.72 5.3.25 0.003 0.053 14.74 5.3.24 0.003 0.057 14.81 5.3.23 0.000 0.080 14.70 5.3.22 0.007 0.050 14.51 5.3.21 0.013 0.047 14.65 5.3.20 0.013 0.050 14.76 5.3.19 0.007 0.057 14.68 5.3.18 0.010 0.067 14.77 5.3.17 0.010 0.063 14.68 5.3.16 0.013 0.070 14.57 5.3.15 0.010 0.060 14.59 5.3.14 0.007 0.073 14.57 5.3.13 0.007 0.070 14.64 5.3.12 0.007 0.073 14.57 5.3.11 0.010 0.053 14.64 5.3.10 0.007 0.057 13.91 5.3.9 0.010 0.060 14.13 5.3.8 0.007 0.050 14.14 5.3.7 0.030 0.047 14.04 5.3.6 0.007 0.070 14.19 5.3.5 0.017 0.043 13.80 5.3.4 0.010 0.067 13.98 5.3.3 0.007 0.073 14.04 5.3.2 0.007 0.057 13.80 5.3.1 0.010 0.063 13.76 5.3.0 0.013 0.053 13.75 5.2.17 0.010 0.057 11.26 5.2.16 0.010 0.050 11.34 5.2.15 0.007 0.050 11.25 5.2.14 0.007 0.043 11.16 5.2.13 0.010 0.053 11.23 5.2.12 0.013 0.050 11.22 5.2.11 0.010 0.050 11.31 5.2.10 0.003 0.043 11.12 5.2.9 0.007 0.040 11.09 5.2.8 0.010 0.060 11.21 5.2.7 0.007 0.040 11.31 5.2.6 0.010 0.053 11.32 5.2.5 0.013 0.040 11.06 5.2.4 0.013 0.040 11.21 5.2.3 0.003 0.063 10.98 5.2.2 0.010 0.050 11.01 5.2.1 0.007 0.037 10.85 5.2.0 0.007 0.040 10.89 5.1.6 0.000 0.040 10.17 5.1.5 0.007 0.030 10.30 5.1.4 0.017 0.037 10.05 5.1.3 0.017 0.030 10.39 5.1.2 0.000 0.040 10.68 5.1.1 0.007 0.040 10.27 5.1.0 0.003 0.037 10.12 5.0.5 0.010 0.023 8.75 5.0.4 0.007 0.027 8.56 5.0.3 0.013 0.037 8.38 5.0.2 0.007 0.023 8.37 5.0.1 0.003 0.043 8.33 5.0.0 0.003 0.043 8.10 4.4.9 0.010 0.027 7.04 4.4.8 0.003 0.023 7.04 4.4.7 0.000 0.027 7.04 4.4.6 0.000 0.023 7.04 4.4.5 0.007 0.020 7.04 4.4.4 0.007 0.030 7.04 4.4.3 0.007 0.020 7.04 4.4.2 0.003 0.023 7.04 4.4.1 0.007 0.017 7.04 4.4.0 0.000 0.033 7.04 4.3.11 0.007 0.023 7.04 4.3.10 0.000 0.023 7.04 4.3.9 0.000 0.027 7.03 4.3.8 0.010 0.040 7.03 4.3.7 0.003 0.023 7.03 4.3.6 0.000 0.023 7.03 4.3.5 0.007 0.020 7.02 4.3.4 0.003 0.033 7.02 4.3.3 0.000 0.027 7.02 4.3.2 0.010 0.023 7.02 4.3.1 0.000 0.027 7.02 4.3.0 0.017 0.013 14.49
preferences:dark mode live preview
155.45 ms | 1394 KiB | 7 Q