Last active
February 27, 2017 02:45
-
-
Save arturom/3820676f8ebae1c0f2d1ca8c89e144ba to your computer and use it in GitHub Desktop.
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 | |
ini_set('memory_limit','512M'); | |
class MessageStructure | |
{ | |
/** | |
* @var mixed | |
*/ | |
public $topic; | |
/** | |
* @var array | |
*/ | |
public $payload; | |
/** | |
* MessageStructure constructor. | |
* @param mixed $topic | |
* @param array $payload | |
*/ | |
public function __construct($topic, array $payload) | |
{ | |
$this->topic = $topic; | |
$this->payload = $payload; | |
} | |
} | |
interface MessageProtocolProcessor | |
{ | |
/** | |
* @param MessageStructure $messageStructure | |
* @return string | |
*/ | |
public function serializeMessageStructure(MessageStructure $messageStructure); | |
/** | |
* @param $serialized | |
* @return MessageStructure | |
*/ | |
public function deserializeMessageStructure($serialized); | |
/** | |
* @param MessageStructure $messageStructure | |
* @return bool | |
*/ | |
public function isMatchingTopic(MessageStructure $messageStructure); | |
} | |
class JsonProtocolProcessor implements MessageProtocolProcessor | |
{ | |
private $interestingTopics; | |
public function __construct(array $interestingTopics) | |
{ | |
$this->interestingTopics = $interestingTopics; | |
} | |
public function serializeMessageStructure(MessageStructure $messageStructure) | |
{ | |
return json_encode($messageStructure); | |
} | |
public function deserializeMessageStructure($serialized) | |
{ | |
$asObject = json_decode($serialized, true); | |
return new MessageStructure( | |
$asObject['topic'], | |
$asObject['payload'] | |
); | |
} | |
public function isMatchingTopic(MessageStructure $messageStructure) { | |
return isset($this->interestingTopics[$messageStructure->topic]); | |
} | |
} | |
class MsgPackProtocolProcessor implements MessageProtocolProcessor | |
{ | |
private $interestingTopics; | |
public function __construct(array $interestingTopics) | |
{ | |
$this->interestingTopics = $interestingTopics; | |
} | |
public function serializeMessageStructure(MessageStructure $messageStructure) | |
{ | |
return msgpack_pack($messageStructure); | |
} | |
public function deserializeMessageStructure($serialized) | |
{ | |
return msgpack_unpack($serialized); | |
} | |
public function isMatchingTopic(MessageStructure $messageStructure) { | |
return isset($this->interestingTopics[$messageStructure->topic]); | |
} | |
} | |
class BitmaskPrefixedProtocolProcessor implements MessageProtocolProcessor | |
{ | |
private $interestingBitmasks; | |
public function __construct(array $interestingBitmasks) | |
{ | |
$this->interestingBitmasks = $interestingBitmasks; | |
} | |
public function serializeMessageStructure(MessageStructure $messageStructure) | |
{ | |
return sprintf('%-32.d %s', $messageStructure->topic, json_encode($messageStructure->payload)); | |
} | |
public function deserializeMessageStructure($serialized) | |
{ | |
$parsedTopic = sscanf($serialized, '%d'); | |
return new MessageStructure( | |
$parsedTopic[0], | |
json_decode(substr($serialized, 32), true) | |
); | |
} | |
public function isMatchingTopic(MessageStructure $messageStructure) | |
{ | |
foreach($this->interestingBitmasks as $bitMask) { | |
if ($messageStructure->topic & $bitMask) { | |
return true; | |
} | |
} | |
return false; | |
} | |
} | |
class StringPrefixProtocolProcessor implements MessageProtocolProcessor | |
{ | |
private $interestingTopics; | |
public function __construct(array $interestingTopics) | |
{ | |
$this->interestingTopics = $interestingTopics; | |
} | |
public function serializeMessageStructure(MessageStructure $messageStructure) | |
{ | |
return sprintf('%-32.s %s', $messageStructure->topic, json_encode($messageStructure->payload)); | |
} | |
public function deserializeMessageStructure($serialized) | |
{ | |
$parsedTopic = sscanf($serialized, '%s'); | |
return new MessageStructure( | |
$parsedTopic[0], | |
json_decode(substr($serialized, 33), true) | |
); | |
} | |
public function isMatchingTopic(MessageStructure $messageStructure) | |
{ | |
return isset($this->interestingTopics[$messageStructure->topic]); | |
} | |
} | |
/** | |
* Generates a sequence of dummy payloads | |
*/ | |
class PayloadGenerator | |
{ | |
public static function generatePayloads($count) | |
{ | |
for($i = 0; $i < $count; $i++) { | |
yield ['foo' => $i]; | |
} | |
} | |
} | |
class ProcessorConfig | |
{ | |
public $processor; | |
public $topic; | |
public function __construct(MessageProtocolProcessor $processor, $topic) { | |
$this->processor = $processor; | |
$this->topic = $topic; | |
} | |
} | |
class StopWatch | |
{ | |
private $times = []; | |
private $latestLapStartTime; | |
public function __construct() | |
{ | |
$this->latestLapStartTime = microtime(true); | |
} | |
public function stopLap() | |
{ | |
return $this->times[] = microtime(true) - $this->latestLapStartTime; | |
} | |
public function getTimes() | |
{ | |
return $this->times; | |
} | |
} | |
function main() { | |
$interestingStringTopics = [ | |
'PAPI.PaymentMethodUpdated' => 1, | |
'SL.UserCreated' => 1 | |
]; | |
$bits = [ | |
'SL' => 1, | |
'PAPI' => 2, | |
'UserCreated' => 4, | |
'PaymentMethodUpdated' => 8 | |
]; | |
$interestingBitmapTopics = [ | |
$bits['PAPI'] | $bits['PaymentMethodUpdated'], | |
$bits['SL'] | $bits['UserCreated'] | |
]; | |
/** @var ProcessorConfig[] $configs */ | |
$configs = [ | |
new ProcessorConfig(new JsonProtocolProcessor($interestingStringTopics), 'SL.UserCreated'), | |
new ProcessorConfig(new MsgPackProtocolProcessor($interestingStringTopics), 'SL.UserCreated'), | |
new ProcessorConfig(new BitmaskPrefixedProtocolProcessor($interestingBitmapTopics), $bits['SL'] | $bits['UserCreated']), | |
new ProcessorConfig(new StringPrefixProtocolProcessor($interestingStringTopics), 'SL.UserCreated'), | |
]; | |
foreach ($configs as $config) { | |
$stopWatch = new StopWatch(); | |
$serializedMessages = []; | |
$messages = []; | |
$stopWatch->startLap(); | |
foreach (PayloadGenerator::generatePayloads(100000) as $payload) { | |
$serializedMessages[] = $config->processor->serializeMessageStructure(new MessageStructure($config->topic, $payload)); | |
} | |
$stopWatch->stopLap(); | |
$stopWatch->startLap(); | |
foreach ($serializedMessages as $serializedMessage) { | |
$messages[] = $config->processor->deserializeMessageStructure($serializedMessage); | |
} | |
$stopWatch->stopLap(); | |
$stopWatch->startLap(); | |
foreach ($messages as $message) { | |
$config->processor->isMatchingTopic($message); | |
} | |
$stopWatch->stopLap(); | |
echo PHP_EOL, get_class($config->processor), ' ', array_sum($stopWatch->getTimes()), PHP_EOL; | |
print_r(array_combine(['Serialization', 'Deserialization', 'Filtering'], $stopWatch->getTimes())); | |
} | |
} | |
main(); |
Author
arturom
commented
Feb 27, 2017
500 thousand iterations
JsonProtocolProcessor 7.6129372119904
Array
(
[Serialization] => 3.2253510951996
[Deserialization] => 3.4254701137543
[Filtering] => 0.9621160030365
)
MsgPackProtocolProcessor 6.9786627292633
Array
(
[Serialization] => 3.3377537727356
[Deserialization] => 2.3145089149475
[Filtering] => 1.3264000415802
)
BitmaskPrefixedProtocolProcessor 9.8353567123413
Array
(
[Serialization] => 3.8295338153839
[Deserialization] => 4.4926009178162
[Filtering] => 1.5132219791412
)
StringPrefixProtocolProcessor 9.1017689704895
Array
(
[Serialization] => 3.777095079422
[Deserialization] => 4.1574048995972
[Filtering] => 1.1672689914703
)
500 thousand iterations
JsonProtocolProcessor 7.6286671161652
Array
(
[Serialization] => 3.1558079719543
[Deserialization] => 3.406919002533
[Filtering] => 1.0659401416779
)
MsgPackProtocolProcessor 6.8090119361877
Array
(
[Serialization] => 3.2473049163818
[Deserialization] => 2.2534329891205
[Filtering] => 1.3082740306854
)
BitmaskPrefixedProtocolProcessor 9.4691841602325
Array
(
[Serialization] => 3.8497879505157
[Deserialization] => 4.1506111621857
[Filtering] => 1.4687850475311
)
StringPrefixProtocolProcessor 8.9867451190948
Array
(
[Serialization] => 3.6515710353851
[Deserialization] => 4.2066960334778
[Filtering] => 1.1284780502319
)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment