Skip to content

Commit

Permalink
Merge pull request #11 from alexpts/improve-speed
Browse files Browse the repository at this point in the history
Improve speed
  • Loading branch information
alexpts authored Apr 11, 2022
2 parents bdafc54 + e6e6714 commit 1124169
Show file tree
Hide file tree
Showing 24 changed files with 625 additions and 65 deletions.
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ It is very fast event emitter and filters.

### Creating an Emitter
```php
$emitter = new PTS\Events\EventEmitter;
$emitter = new \PTS\Events\EventEmitter;
```

### Adding Listeners
Expand All @@ -31,13 +31,18 @@ With priority
$emitter->on('user.created', $handler, 100);
```

With extra arguments
With extra arguments for EventEmitterExtraArgs instance (EventEmitter instance skip extra args)
```php
$emitter = new \PTS\Events\EventEmitterExtraArgs;

$extra1 = 1;
$extra2 = 'some';
$emitter->on('log', function(string $log, int $extra1, string $extra2) {

$handler = function(string $log, int $extra1, string $extra2) {
// ...
}, 50, [$extra1, $extra2]);
};

$emitter->on('log', $handler, 50, [$extra1, $extra2]);
$emitter->emit('log', ['some log']);
```

Expand Down Expand Up @@ -97,8 +102,7 @@ eventNames(): array;
EventHandler must be `callable`

```php
use PTS\Events\Events;
$eventsBus = new EventEmitter;
$eventsBus = new \PTS\Events\EventEmitter;

$eventsBus->on('some:event', function(){ ... });
$eventsBus->on('some:event', 'trim');
Expand All @@ -108,7 +112,7 @@ $eventsBus->once('some', $instanceWithInvokeMethod);
```

#### Order handlers
Listeners has priority. All listeners invoke by priority
Listeners have priority. All listeners invoke by priority

```php
$events->on('post:title', 'trim', 10); // second
Expand All @@ -133,9 +137,9 @@ $events->off('post:title');
#### StopPropagation

```php
$events->on('eventName', function(){ ... });
$events->on('eventName', function(){ throw new StopPropagation; });
$events->on('eventName', function(){ ... }); // it does not call
$events->on('eventName', function() { ... });
$events->on('eventName', function() { throw new StopPropagation; });
$events->on('eventName', function() { ... }); // it does not call
```

## Filters
Expand All @@ -155,20 +159,19 @@ eventNames(): array;

Example
```php
use PTS\Events\Filters;
$filters = new Filters;
$filters = new \PTS\Events\Filters;

$filters->on('post:title', 'trim');
$title = $filters->filter('post:title', ' Raw title '); // `Raw title`
```



### Inject EventEmitter / FilterEmitter

1. Event/Filter Bus.

```php
use PTS\Events\EventBusTrait;
use PTS\Events\Bus\EventBusTrait;

class Service {
use EventBusTrait;
Expand Down
80 changes: 71 additions & 9 deletions benchmark/bechmark.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
use Blackfire\Client;
use Blackfire\Profile\Configuration;
use PTS\Events\EventEmitter;
use PTS\Events\EventEmitterExtraArgs;
use PTS\Events\Filter\FilterEmitter;
use PTS\Events\Filter\FilterExtraArgsEmitter;

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

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

Expand All @@ -17,24 +19,84 @@
}

$startTime = microtime(true);

$events = new EventEmitter;
$events2 = new EventEmitterExtraArgs();

$filters = new FilterEmitter;
$filters2 = new FilterExtraArgsEmitter;

$events
->on('event-a', fn(int $a) => $a, 50, [1, 2])
->on('event-a', fn(int $b) => $b);
->on('event-a', fn(int|null $b = null) => $b)
->on('event-a', fn(int|null $b = null) => $b);

$events2
->on('event-a', fn(int|null $a = null) => $a, 50, [1, 2])
->on('event-a', fn(int|null $b = null) => $b);

$filters
->on('filter-a', fn(int $a, int $b) => $a, 50, [1, 2])
->on('filter-a', fn(int $a, int $b) => $a);
->on('filter-a', fn(int $a = 1, int $b = 2) => $a, 50, [1, 2])
->on('filter-a', fn(int $a = 1, int $b = 2) => $a);

$filters2
->on('filter-a', fn(int $a = 1, int $b = 2) => $a, 50, [1, 2])
->on('filter-a', fn(int $a = 1, int $b = 2) => $a);


function test(string $title, callable $func, int $iterations) {
$startTime = microtime(true);

while ($iterations--) {
$func();
}

while ($iterations--) {
$diff = (microtime(true) - $startTime) * 1000;
$duration = sprintf('%2.3f ms', $diff);
echo $title . ': ' . $duration . PHP_EOL;
}

echo 'Events:' . PHP_EOL;

test('with args in emit', function() use ($events){
$events->emit('event-a', [1]);
}, $iterations);

test('EA with args in emit', function() use ($events2){
$events2->emit('event-a', [1]);
}, $iterations);


test('without args in emit', function() use ($events){
$events->emit('event-a');
}, $iterations);

test('EA without args in emit', function() use ($events2){
$events2->emit('event-a');
}, $iterations);



echo PHP_EOL . 'Filter:' . PHP_EOL;

test('with args in emit', function() use ($filters){
$filters->emit('filter-a', 1, [3]);
}
}, $iterations);

test('EA with args in emit', function() use ($filters2){
$filters2->emit('filter-a', 1, [3]);
}, $iterations);


test('without args in emit', function() use ($filters){
$filters->emit('filter-a', 1);
}, $iterations);

test('EA without args in emit', function() use ($filters2){
$filters2->emit('filter-a', 1);
}, $iterations);



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

if ($blackfire) {
Expand Down
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
"PTS\\Events\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"PTS\\Events\\Test\\": "test/unit"
}
},
"scripts": {
"bench": "vendor/bin/phpbench run --config=test/phpbench.json --report=aggregate",
"test": "vendor/bin/phpunit --config=test/phpunit.xml"
Expand Down
3 changes: 2 additions & 1 deletion src/EventBusTrait.php → src/Bus/EventBusTrait.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?php
declare(strict_types=1);

namespace PTS\Events;
namespace PTS\Events\Bus;

use PTS\Events\EventEmitterInterface;
use PTS\Events\Filter\FilterEmitterInterface;

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

namespace PTS\Events;

class EventEmitterExtraArgs implements EventEmitterInterface
{
use EventEmitterExtraArgsTrait;
}
52 changes: 52 additions & 0 deletions src/EventEmitterExtraArgsTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

trait EventEmitterExtraArgsTrait
{
use EventEmitterTrait;

public function emit(string $name, array $args = []): void
{
$countArgs = count($args);

try {
foreach ($this->listeners[$name] ?? [] as $i => $listener) {
match ($countArgs) {
0 => ($listener->handler)(...$listener->extraArgs),
1 => ($listener->handler)($args[0], ...$listener->extraArgs),
2 => ($listener->handler)($args[0], $args[1], ...$listener->extraArgs),
default => ($listener->handler)(...$args, ...$listener->extraArgs),
};

if ($listener->once) {
unset($this->listeners[$name][$i]);
if (count($this->listeners[$name]) === 0) {
unset($this->listeners[$name]);
}
}
}
} catch (StopPropagation) {
return;
}
}

public function emitNoArgs(string $name): void
{
try {
foreach ($this->listeners[$name] ?? [] as $i => $listener) {
($listener->handler)(...$listener->extraArgs);

if ($listener->once) {
unset($this->listeners[$name][$i]);
if (count($this->listeners[$name]) === 0) {
unset($this->listeners[$name]);
}
}
}
} catch (StopPropagation) {
return;
}
}
}
2 changes: 2 additions & 0 deletions src/EventEmitterInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
interface EventEmitterInterface
{
public function emit(string $name, array $args = []): void;
public function emitNoArgs(string $name): void;

public function on(string $name, callable $handler, int $priority = 50, array $extraArgs = []): static;
public function once(string $name, callable $handler, int $priority = 50, array $extraArgs = []): static;
public function off(string $event, callable $handler = null, int $priority = null): static;
Expand Down
28 changes: 26 additions & 2 deletions src/EventEmitterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,35 @@ trait EventEmitterTrait
protected array $listeners = [];

public function emit(string $name, array $args = []): void
{
$countArgs = count($args);

try {
foreach ($this->listeners[$name] ?? [] as $i => $listener) {
match ($countArgs) {
0 => ($listener->handler)(),
1 => ($listener->handler)($args[0]),
2 => ($listener->handler)($args[0], $args[1]),
default => ($listener->handler)(...$args),
};

if ($listener->once) {
unset($this->listeners[$name][$i]);
if (count($this->listeners[$name]) === 0) {
unset($this->listeners[$name]);
}
}
}
} catch (StopPropagation) {
return;
}
}

public function emitNoArgs(string $name): void
{
try {
foreach ($this->listeners[$name] ?? [] as $i => $listener) {
$handler = $listener->handler;
$handler(...$args, ...$listener->extraArgs);
($listener->handler)();

if ($listener->once) {
unset($this->listeners[$name][$i]);
Expand Down
9 changes: 9 additions & 0 deletions src/EventExtraArgsEmitter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);

namespace PTS\Events;

class EventExtraArgsEmitter implements EventEmitterInterface
{
use EventEmitterExtraArgsTrait;
}
6 changes: 3 additions & 3 deletions src/EventHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@

class EventHandler
{
public string $id;
public readonly string $id;
/** @var callable */
public $handler;
public bool $once = false;

public function __construct(
callable $handler,
public int $priority = 0,
public array $extraArgs = []
public readonly int $priority = 0,
public readonly array $extraArgs = []
) {
$this->id = $this->getHandlerId($handler);
$this->handler = $handler;
Expand Down
Loading

0 comments on commit 1124169

Please sign in to comment.