Skip to content

Commit

Permalink
optimize performance, smart lazy sort
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpts committed Jan 27, 2019
1 parent b8521c1 commit 215e47b
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 23 deletions.
50 changes: 50 additions & 0 deletions benchmark/bechmark.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

use Blackfire\Client;
use Blackfire\Profile\Configuration;
use PTS\Events\Events;
use PTS\Events\Filters;
use PTS\Events\ResolveHandler;

require_once __DIR__ .'/../vendor/autoload.php';

$iterations = $argv[1] ?? 1000;
$blackfire = $argv[2] ?? false;
$iterations++;

if ($blackfire) {
$client = new Client;
$probe = $client->createProbe(new Configuration);
}

$startTime = microtime(true);
$resolver = new ResolveHandler;
$events = new Events($resolver);
$filters = new Filters($resolver);


$events->on('event-a', function (int $a) {
return $a;
}, 50, [1, 2])->on('event-a', function (int $b) {
return $b;
});

$filters->on('filter-a', function(int $a, int $b) {
return $a;
}, 50, [1, 2])->on('filter-a', function (int $a, int $b) {
return $a;
});


while ($iterations--) {
$events->emit('event-a', [1]);
$filters->filter('filter-a', 1, [3]);
}

$diff = (microtime(true) - $startTime) * 1000;
echo sprintf('%2.3f ms', $diff);
echo "\n" . memory_get_peak_usage()/1024;

if ($blackfire) {
$client->endProbe($probe);
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"php": ">=7.2"
},
"require-dev": {
"phpunit/phpunit": "^7.5"
"phpunit/phpunit": "^7.5",
"blackfire/php-sdk": "^1.18"
},
"autoload": {
"psr-4": {
Expand Down
113 changes: 112 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 27 additions & 14 deletions src/BaseEvents.php
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

abstract class BaseEvents
{
/** @var array[][] */
protected $listeners = [];
/** @var Handler */
/** @var ResolveHandler */
protected $handler;
/** @var bool */
protected $sorted = false;

public function __construct()
public function __construct(ResolveHandler $handler = null)
{
$this->handler = new Handler;
$this->handler = $handler ?? new ResolveHandler;
}

public function getListeners(): array
Expand All @@ -21,8 +24,10 @@ public function getListeners(): array

protected function sortListeners(string $name): void
{
if (array_key_exists($name, $this->listeners)) {
$isSorted = $this->sorted[$name] ?? false;
if (!$isSorted) {
krsort($this->listeners[$name], SORT_NUMERIC);
$this->sorted[$name] = true;
}
}

Expand All @@ -43,6 +48,8 @@ public function on(string $name, callable $handler, int $priority = 50, array $e
'priority' => $priority,
];

$this->sorted[$name] = false;

return $this;
}

Expand Down Expand Up @@ -70,8 +77,9 @@ public function once(string $name, callable $handler, int $priority = 50, array
*/
protected function offAll(string $eventName): self
{
if (array_key_exists($eventName, $this->listeners)) {
unset($this->listeners[$eventName]);
$hasEvent = $this->listeners[$eventName] ?? false;
if ($hasEvent) {
unset($this->listeners[$eventName], $this->sorted[$eventName]);
}

return $this;
Expand All @@ -95,7 +103,7 @@ public function off(string $eventName, callable $handler = null, int $priority =
: $this->offHandlerWithPriority($eventName, $handler, $priority);

if (empty($this->listeners[$eventName])) {
unset($this->listeners[$eventName]);
unset($this->listeners[$eventName], $this->sorted[$eventName]);
}

return $this;
Expand All @@ -114,7 +122,6 @@ protected function offHandlerWithPriority(string $eventName, callable $handler,

if (isset($this->listeners[$eventName][$priority][$handlerId])) {
unset($this->listeners[$eventName][$priority][$handlerId]);

$this->cleanEmptyEvent($eventName, $priority);
}

Expand All @@ -131,8 +138,8 @@ protected function offHandlerWithoutPriority(string $eventName, callable $handle
{
$handlerId = $this->handler->getKey($handler);

foreach ($this->listeners[$eventName] as $currentPriority => $nandlers) {
foreach ($nandlers as $currentHandlerId => $paramsHandler) {
foreach ($this->listeners[$eventName] as $currentPriority => $handlers) {
foreach ($handlers as $currentHandlerId => $paramsHandler) {
if ($handlerId === $currentHandlerId) {
unset($this->listeners[$eventName][$currentPriority][$handlerId]);
$this->cleanEmptyEvent($eventName, $currentPriority);
Expand All @@ -148,6 +155,10 @@ protected function cleanEmptyEvent(string $eventName, int $currentPriority): voi
if (empty($this->listeners[$eventName][$currentPriority])) {
unset($this->listeners[$eventName][$currentPriority]);
}

if (empty($this->sorted[$eventName])) {
unset($this->sorted[$eventName]);
}
}

/**
Expand All @@ -159,7 +170,8 @@ protected function cleanEmptyEvent(string $eventName, int $currentPriority): voi
*/
protected function trigger(string $name, array $arguments = [], $value = null)
{
if (array_key_exists($name, $this->listeners)) {
$event = $this->listeners[$name] ?? false;
if ($event) {
$this->sortListeners($name);
foreach ($this->listeners[$name] as $handlers) {
foreach ($handlers as $paramsHandler) {
Expand All @@ -179,7 +191,7 @@ protected function trigger(string $name, array $arguments = [], $value = null)
*/
protected function offOnce(array $paramsHandler, string $name): void
{
if (array_key_exists('once', $paramsHandler) && $paramsHandler['once']) {
if ($paramsHandler['once'] ?? false) {
$this->off($name, $paramsHandler['handler'], $paramsHandler['priority']);
}
}
Expand All @@ -193,8 +205,9 @@ protected function offOnce(array $paramsHandler, string $name): void
*/
protected function getCallArgs(array $arguments, array $extraArguments, $value = null): array
{
$arguments = array_merge($arguments, $extraArguments);
array_unshift($arguments, $value);
foreach ($extraArguments as $name => $val) {
$arguments[] = $val;
}

return $arguments;
}
Expand Down
1 change: 1 addition & 0 deletions src/EmitterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function setFilters(FiltersInterface $filters): void
* @param string $name
* @param mixed $value
* @param mixed $arguments
*
* @return mixed
*/
public function filter(string $name, $value, array $arguments = [])
Expand Down
6 changes: 1 addition & 5 deletions src/Events.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

Expand All @@ -20,9 +21,4 @@ public function emit(string $name, array $arguments = [])

return $this;
}

protected function getCallArgs(array $arguments, array $extraArguments, $value = null): array
{
return array_merge($arguments, $extraArguments);
}
}
1 change: 1 addition & 0 deletions src/EventsInterface.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

Expand Down
9 changes: 9 additions & 0 deletions src/Filters.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

Expand All @@ -19,4 +20,12 @@ public function filter(string $name, $value, array $arguments = [])
return $e->getValue();
}
}

protected function getCallArgs(array $arguments, array $extraArguments, $value = null): array
{
$arguments = parent::getCallArgs($arguments, $extraArguments, $value);
array_unshift($arguments, $value);

return $arguments;
}
}
1 change: 1 addition & 0 deletions src/FiltersInterface.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

Expand Down
5 changes: 3 additions & 2 deletions src/Handler.php → src/ResolveHandler.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

class Handler
class ResolveHandler
{

public function getKey(callable $handler): string
{
if (is_array($handler)) {
list($className, $method) = $handler;
[$className, $method] = $handler;

if (is_object($className)) {
$className = get_class($className);
Expand Down
1 change: 1 addition & 0 deletions src/StopPropagation.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

Expand Down
1 change: 1 addition & 0 deletions test/unit/FiltersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ protected function setUp()
/**
* @param string $value
* @param int $length
*
* @return string
*/
public function customFilterHandler(string $value, $length = 4): string
Expand Down

0 comments on commit 215e47b

Please sign in to comment.