Skip to content

Commit

Permalink
Optimize listener callbacks.
Browse files Browse the repository at this point in the history
Use direct function calls as they can be up to 30% faster than
call_user_func_array.
  • Loading branch information
markstory committed Jul 5, 2013
1 parent c7432af commit 3040dbe
Showing 1 changed file with 32 additions and 7 deletions.
39 changes: 32 additions & 7 deletions lib/Cake/Event/EventManager.php
Expand Up @@ -235,13 +235,7 @@ public function dispatch($event) {
if ($event->isStopped()) {
break;
}
$data = $event->data();
if ($data !== null) {
array_unshift($data, $event);
$result = call_user_func_array($listener['callable'], $data);
} else {
$result = call_user_func($listener['callable'], $event);
}
$result = $this->_callListener($listener['callable'], $event);
if ($result === false) {
$event->stopPropagation();
}
Expand All @@ -252,6 +246,37 @@ public function dispatch($event) {
}
}

/**
* Calls a listener.
*
* Direct callback invocation is up to 30% faster than using call_user_func_array.
* Optimize the common cases to provide improved performance.
*
* @param callable $listener The listener to trigger.
* @param Event $event
* @return mixed The result of the $listener function.
*/
protected function _callListener(callable $listener, Event $event) {
$data = $event->data();
$length = count($data);
if ($length) {
$data = array_values($data);
}
switch ($length) {
case 0:
return $listener($event);
case 1:
return $listener($event, $data[0]);
case 2:
return $listener($event, $data[0], $data[1]);
case 3:
return $listener($event, $data[0], $data[1], $data[2]);
default:
array_unshift($data, $event);
return call_user_func_array($listener, $data);
}
}

/**
* Returns a list of all listeners for an eventKey in the order they should be called
*
Expand Down

0 comments on commit 3040dbe

Please sign in to comment.