Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 446270e

Browse filesBrowse files
[EventDispatcher][VarDumper] optimize perf by leveraging Closure::fromCallable()
1 parent dbf053b commit 446270e
Copy full SHA for 446270e

File tree

6 files changed

+531
-464
lines changed
Filter options

6 files changed

+531
-464
lines changed

‎src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
class WrappedListener
2323
{
2424
private $listener;
25+
private $optimizedListener;
2526
private $name;
2627
private $called;
2728
private $stoppedPropagation;
@@ -31,9 +32,10 @@ class WrappedListener
3132
private $stub;
3233
private static $hasClassStub;
3334

34-
public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
35+
public function __construct(callable $listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
3536
{
3637
$this->listener = $listener;
38+
$this->optimizedListener = $listener instanceof \Closure ? $listener : \Closure::fromCallable($listener);
3739
$this->stopwatch = $stopwatch;
3840
$this->dispatcher = $dispatcher;
3941
$this->called = false;
@@ -108,7 +110,7 @@ public function __invoke(Event $event, $eventName, EventDispatcherInterface $dis
108110

109111
$e = $this->stopwatch->start($this->name, 'event_listener');
110112

111-
\call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher);
113+
\call_user_func($this->optimizedListener, $event, $eventName, $this->dispatcher ?: $dispatcher);
112114

113115
if ($e->isStarted()) {
114116
$e->stop();

‎src/Symfony/Component/EventDispatcher/EventDispatcher.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/EventDispatcher/EventDispatcher.php
+51-18Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ class EventDispatcher implements EventDispatcherInterface
3030
{
3131
private $listeners = array();
3232
private $sorted = array();
33+
private $optimized;
34+
35+
public function __construct()
36+
{
37+
if (__CLASS__ === \get_class($this)) {
38+
$this->optimized = array();
39+
}
40+
}
3341

3442
/**
3543
* {@inheritdoc}
@@ -40,7 +48,13 @@ public function dispatch($eventName, Event $event = null)
4048
$event = new Event();
4149
}
4250

43-
if ($listeners = $this->getListeners($eventName)) {
51+
if (null !== $this->optimized && null !== $eventName) {
52+
$listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? array() : $this->optimizeListeners($eventName));
53+
} else {
54+
$listeners = $this->getListeners($eventName);
55+
}
56+
57+
if ($listeners) {
4458
$this->doDispatch($listeners, $eventName, $event);
4559
}
4660

@@ -86,11 +100,10 @@ public function getListenerPriority($eventName, $listener)
86100
$listener[0] = $listener[0]();
87101
}
88102

89-
foreach ($this->listeners[$eventName] as $priority => $listeners) {
90-
foreach ($listeners as $k => $v) {
103+
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
104+
foreach ($listeners as &$v) {
91105
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
92106
$v[0] = $v[0]();
93-
$this->listeners[$eventName][$priority][$k] = $v;
94107
}
95108
if ($v === $listener) {
96109
return $priority;
@@ -123,7 +136,7 @@ public function hasListeners($eventName = null)
123136
public function addListener($eventName, $listener, $priority = 0)
124137
{
125138
$this->listeners[$eventName][$priority][] = $listener;
126-
unset($this->sorted[$eventName]);
139+
unset($this->sorted[$eventName], $this->optimized[$eventName]);
127140
}
128141

129142
/**
@@ -139,21 +152,17 @@ public function removeListener($eventName, $listener)
139152
$listener[0] = $listener[0]();
140153
}
141154

142-
foreach ($this->listeners[$eventName] as $priority => $listeners) {
143-
foreach ($listeners as $k => $v) {
155+
foreach ($this->listeners[$eventName] as $priority => &$listeners) {
156+
foreach ($listeners as $k => &$v) {
144157
if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
145158
$v[0] = $v[0]();
146159
}
147160
if ($v === $listener) {
148-
unset($listeners[$k], $this->sorted[$eventName]);
149-
} else {
150-
$listeners[$k] = $v;
161+
unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]);
151162
}
152163
}
153164

154-
if ($listeners) {
155-
$this->listeners[$eventName][$priority] = $listeners;
156-
} else {
165+
if (!$listeners) {
157166
unset($this->listeners[$eventName][$priority]);
158167
}
159168
}
@@ -215,22 +224,46 @@ protected function doDispatch($listeners, $eventName, Event $event)
215224

216225
/**
217226
* Sorts the internal list of listeners for the given event by priority.
218-
*
219-
* @param string $eventName The name of the event
220227
*/
221-
private function sortListeners($eventName)
228+
private function sortListeners(string $eventName)
222229
{
223230
krsort($this->listeners[$eventName]);
224231
$this->sorted[$eventName] = array();
225232

226-
foreach ($this->listeners[$eventName] as $priority => $listeners) {
233+
foreach ($this->listeners[$eventName] as &$listeners) {
227234
foreach ($listeners as $k => $listener) {
228235
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
229236
$listener[0] = $listener[0]();
230-
$this->listeners[$eventName][$priority][$k] = $listener;
231237
}
232238
$this->sorted[$eventName][] = $listener;
233239
}
234240
}
235241
}
242+
243+
/**
244+
* Optimizes the internal list of listeners for the given event by priority.
245+
*/
246+
private function optimizeListeners(string $eventName): array
247+
{
248+
krsort($this->listeners[$eventName]);
249+
$this->optimized[$eventName] = array();
250+
251+
foreach ($this->listeners[$eventName] as &$listeners) {
252+
foreach ($listeners as &$listener) {
253+
$closure = &$this->optimized[$eventName][];
254+
if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
255+
$closure = static function (...$args) use (&$listener, &$closure) {
256+
if ($listener[0] instanceof \Closure) {
257+
$listener[0] = $listener[0]();
258+
}
259+
($closure = \Closure::fromCallable($listener))(...$args);
260+
};
261+
} else {
262+
$closure = $listener instanceof \Closure ? $listener : \Closure::fromCallable($listener);
263+
}
264+
}
265+
}
266+
267+
return $this->optimized[$eventName];
268+
}
236269
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.