Skip to content

Instantly share code, notes, and snippets.

@arturom
Last active February 27, 2017 02:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arturom/3820676f8ebae1c0f2d1ca8c89e144ba to your computer and use it in GitHub Desktop.
Save arturom/3820676f8ebae1c0f2d1ca8c89e144ba to your computer and use it in GitHub Desktop.
<?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();
@arturom
Copy link
Author

arturom commented Feb 27, 2017

JsonProtocolProcessor 1.6236619949341
Array
(
    [Serialization] => 0.66471004486084
    [Deserialization] => 0.73484396934509
    [Filtering] => 0.22410798072815
)

MsgPackProtocolProcessor 1.3595271110535
Array
(
    [Serialization] => 0.62837409973145
    [Deserialization] => 0.45459008216858
    [Filtering] => 0.27656292915344
)

BitmaskPrefixedProtocolProcessor 1.9099369049072
Array
(
    [Serialization] => 0.72616600990295
    [Deserialization] => 0.85963892936707
    [Filtering] => 0.32413196563721
)

StringPrefixProtocolProcessor 1.7858688831329
Array
(
    [Serialization] => 0.70727586746216
    [Deserialization] => 0.83357715606689
    [Filtering] => 0.24501585960388
)

@arturom
Copy link
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
)

@arturom
Copy link
Author

arturom commented Feb 27, 2017

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