Created
          March 7, 2011 19:32 
        
      - 
      
- 
        Save beberlei/859052 to your computer and use it in GitHub Desktop. 
    Performance of bschussek/doctrine-common EventManager changes
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | <?php | |
| require_once "Doctrine/Common/ClassLoader.php"; | |
| use Doctrine\Common\ClassLoader; | |
| use Doctrine\Common\EventArgs; | |
| use Doctrine\Common\EventManager; | |
| $loader = new ClassLoader(); | |
| $loader->register(); | |
| $evm = new EventManager(); | |
| $nevm = new EventManagerNew(); | |
| $benchmarks = array(); | |
| class PropagationEventArgs extends EventArgs | |
| { | |
| private $propagation = false; | |
| public function isPropagationStopped() | |
| { | |
| return $this->propagation; | |
| } | |
| } | |
| for ($i = 0; $i < 25; $i++) { | |
| $evm->addEventListener(array("onEvent"), new SomeEventListener); | |
| $nevm->addEventListener(array("onEvent"), new SomeEventListener); | |
| for ($j = 0; $j < 100; $j++) { | |
| $benchmarks['evm'][$i][$j] = microtime(true); | |
| for ($k = 0; $k < 100; $k++) { | |
| $evm->dispatchEvent('onEvent', new EventArgs()); | |
| } | |
| $benchmarks['evm'][$i][$j] = microtime(true) - $benchmarks['evm'][$i][$j]; | |
| usleep(500); | |
| $benchmarks['nevm'][$i][$j] = microtime(true); | |
| for ($k = 0; $k < 100; $k++) { | |
| $nevm->dispatchEvent('onEvent', new PropagationEventArgs()); | |
| } | |
| $benchmarks['nevm'][$i][$j] = microtime(true) - $benchmarks['nevm'][$i][$j]; | |
| usleep(500); | |
| } | |
| } | |
| foreach ($benchmarks AS $name => $data) { | |
| foreach ($data AS $listenerCount => $repetitionData) { | |
| echo $name . "\t" . sprintf("%4d", $listenerCount) . "\t" . (array_sum($repetitionData)/count($repetitionData)) . "\n"; | |
| } | |
| } | |
| class SomeEventListener | |
| { | |
| public function onEvent(EventArgs $args) | |
| { | |
| } | |
| } | |
| class EventManagerNew | |
| { | |
| /** | |
| * Map of registered listeners. | |
| * <event> => (<objecthash> => <listener>) | |
| * | |
| * @var array | |
| */ | |
| private $_listeners = array(); | |
| /** | |
| * Map of priorities by the object hashes of their listeners. | |
| * <event> => (<objecthash> => <priority>) | |
| * | |
| * This property is used for listener sorting. | |
| * | |
| * @var array | |
| */ | |
| private $_priorities = array(); | |
| /** | |
| * Stores which event listener lists are currently sorted. | |
| * <event> => <sorted> | |
| * | |
| * @var array | |
| */ | |
| private $_sorted = array(); | |
| /** | |
| * Dispatches an event to all registered listeners. | |
| * | |
| * @param string $eventName The name of the event to dispatch. The name of the event is | |
| * the name of the method that is invoked on listeners. | |
| * @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners. | |
| * If not supplied, the single empty EventArgs instance is used. | |
| */ | |
| public function dispatchEvent($eventName, EventArgs $eventArgs = null) | |
| { | |
| if (isset($this->_listeners[$eventName])) { | |
| $eventArgs = $eventArgs === null ? new EventArgs() : $eventArgs; | |
| $this->sortListeners($eventName); | |
| foreach ($this->_listeners[$eventName] as $listener) { | |
| $this->triggerListener($listener, $eventName, $eventArgs); | |
| if ($eventArgs->isPropagationStopped()) { | |
| break; | |
| } | |
| } | |
| } | |
| } | |
| /** | |
| * Triggers the listener method for an event. | |
| * | |
| * This method can be overridden to add functionality that is executed | |
| * for each listener. | |
| * | |
| * @param object $listener The event listener on which to invoke the listener method. | |
| * @param string $eventName The name of the event to dispatch. The name of the event is | |
| * the name of the method that is invoked on listeners. | |
| * @param EventArgs $eventArgs The event arguments to pass to the event handlers/listeners. | |
| */ | |
| protected function triggerListener($listener, $eventName, EventArgs $eventArgs) | |
| { | |
| if ($listener instanceof \Closure) { | |
| $listener->__invoke($eventArgs); | |
| } else { | |
| $listener->$eventName($eventArgs); | |
| } | |
| } | |
| /** | |
| * Sorts the internal list of listeners for the given event by priority. | |
| * | |
| * Calling this method multiple times will not cause overhead unless you | |
| * add new listeners. As long as no listener is added, the list for an | |
| * event name won't be sorted twice. | |
| * | |
| * @param string $event The name of the event. | |
| */ | |
| private function sortListeners($eventName) | |
| { | |
| if (!$this->_sorted[$eventName]) { | |
| $p = $this->_priorities[$eventName]; | |
| uasort($this->_listeners[$eventName], function ($a, $b) use ($p) { | |
| return $p[spl_object_hash($b)] - $p[spl_object_hash($a)]; | |
| }); | |
| $this->_sorted[$eventName] = true; | |
| } | |
| } | |
| /** | |
| * Gets the listeners of a specific event or all listeners. | |
| * | |
| * @param string $event The name of the event. | |
| * @return array The event listeners for the specified event, or all event listeners. | |
| */ | |
| public function getListeners($event = null) | |
| { | |
| if ($event) { | |
| $this->sortListeners($event); | |
| return $this->_listeners[$event]; | |
| } | |
| foreach ($this->_listeners as $event => $listeners) { | |
| $this->sortListeners($event); | |
| } | |
| return $this->_listeners; | |
| } | |
| /** | |
| * Checks whether an event has any registered listeners. | |
| * | |
| * @param string $event | |
| * @return boolean TRUE if the specified event has any listeners, FALSE otherwise. | |
| */ | |
| public function hasListeners($event) | |
| { | |
| return isset($this->_listeners[$event]) && $this->_listeners[$event]; | |
| } | |
| /** | |
| * Adds an event listener that listens on the specified events. | |
| * | |
| * @param string|array $events The event(s) to listen on. | |
| * @param object $listener The listener object. | |
| * @param integer $priority The higher this value, the earlier an event listener | |
| * will be triggered in the chain. Defaults to 0. | |
| */ | |
| public function addEventListener($events, $listener, $priority = 0) | |
| { | |
| // Picks the hash code related to that listener | |
| $hash = spl_object_hash($listener); | |
| foreach ((array) $events as $event) { | |
| if (!isset($this->_listeners[$event])) { | |
| $this->_listeners[$event] = array(); | |
| $this->_priorities[$event] = array(); | |
| } | |
| // Prevents duplicate listeners on same event (same instance only) | |
| $this->_listeners[$event][$hash] = $listener; | |
| $this->_priorities[$event][$hash] = $priority; | |
| $this->_sorted[$event] = false; | |
| } | |
| } | |
| /** | |
| * Removes an event listener from the specified events. | |
| * | |
| * @param string|array $events | |
| * @param object $listener | |
| */ | |
| public function removeEventListener($events, $listener) | |
| { | |
| // Picks the hash code related to that listener | |
| $hash = spl_object_hash($listener); | |
| foreach ((array) $events as $event) { | |
| // Check if actually have this listener associated | |
| if (isset($this->_listeners[$event][$hash])) { | |
| unset($this->_listeners[$event][$hash]); | |
| unset($this->_priorities[$event][$hash]); | |
| } | |
| } | |
| } | |
| /** | |
| * Adds an EventSubscriber. The subscriber is asked for all the events he is | |
| * interested in and added as a listener for these events. | |
| * | |
| * @param Doctrine\Common\EventSubscriber $subscriber The subscriber. | |
| * @param integer $priority The higher this value, the earlier an event listener | |
| * will be triggered in the chain. Defaults to 0. | |
| */ | |
| public function addEventSubscriber(EventSubscriber $subscriber, $priority = 0) | |
| { | |
| $this->addEventListener($subscriber->getSubscribedEvents(), $subscriber, $priority); | |
| } | |
| } | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | evm 0 0.00048770189285278 | |
| evm 1 0.00059050321578979 | |
| evm 2 0.00068733215332031 | |
| evm 3 0.00078628063201904 | |
| evm 4 0.00084335088729858 | |
| evm 5 0.00095219135284424 | |
| evm 6 0.0010335898399353 | |
| evm 7 0.0011562895774841 | |
| evm 8 0.0012545847892761 | |
| evm 9 0.001274037361145 | |
| evm 10 0.0014402270317078 | |
| evm 11 0.0014760065078735 | |
| evm 12 0.0012823748588562 | |
| evm 13 0.0012816596031189 | |
| evm 14 0.0015170240402222 | |
| evm 15 0.0014918971061707 | |
| evm 16 0.0016846013069153 | |
| evm 17 0.0019244766235352 | |
| evm 18 0.0020828008651733 | |
| evm 19 0.0019659638404846 | |
| evm 20 0.0020429754257202 | |
| evm 21 0.0021235156059265 | |
| evm 22 0.0019197344779968 | |
| evm 23 0.0022525453567505 | |
| evm 24 0.0020547080039978 | |
| nevm 0 0.0008044958114624 | |
| nevm 1 0.001168360710144 | |
| nevm 2 0.0015089774131775 | |
| nevm 3 0.0018552470207214 | |
| nevm 4 0.0020939707756042 | |
| nevm 5 0.002463595867157 | |
| nevm 6 0.0027560544013977 | |
| nevm 7 0.0031801915168762 | |
| nevm 8 0.003525767326355 | |
| nevm 9 0.003646252155304 | |
| nevm 10 0.0041954660415649 | |
| nevm 11 0.0043569731712341 | |
| nevm 12 0.0038117527961731 | |
| nevm 13 0.0038837623596191 | |
| nevm 14 0.0046020936965942 | |
| nevm 15 0.0045461463928223 | |
| nevm 16 0.0051713013648987 | |
| nevm 17 0.0059885501861572 | |
| nevm 18 0.0065212893486023 | |
| nevm 19 0.0061679720878601 | |
| nevm 20 0.0064382171630859 | |
| nevm 21 0.006737904548645 | |
| nevm 22 0.0060815143585205 | |
| nevm 23 0.0072019243240356 | |
| nevm 24 0.0067453527450562 | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment