This sample demonstrates how to measure performance of SBE encoding/decoding.
#include "CountingListener.h"
#include "../../Common/PrecisionTimer.h"
#include "../../Common/Helpers.h"
#include "../../Common/Settings.h"
using namespace Settings;
namespace {
#pragma pack(push, 1)
struct MessageHeaderComposite
{
};
struct PacketHeaderComposite
{
};
struct PreMessageHeaderComposite
{
};
#pragma pack(pop)
class SbeImprovePerformanceLibrary : public ISbeCustomCoderLibrary
{
public:
void queryCodingControl(
CoderOwnerId, SbeFieldMetaData, SbeFieldCodingSettings parameters) ONIXS_FIXENGINE_OVERRIDE {
parameters.useFormattedDateTime(false);
parameters.useValueNamesExternally(false);
}
};
MessageHeaderComposite decodeHeader(
ByteArray & sbeMessageBytes,
size_t & offset);
void decode();
void decodeEventBased();
};
int main(int argc, const char * argv[])
{
#ifndef NDEBUG
std::cerr << "Please use RELEASE build to measure performance." << std::endl;
return 1;
#endif
try {
EngineSettings engineSettings;
Engine::init(engineSettings);
if(argc > 1 && !strcmp(argv[1], "-c"))
decodeEventBased();
else
decode();
waitUntilEnterKey();
}
catch(const std::exception & ex) {
processSampleException(ex.what());
return 3;
}
}
namespace {
MessageHeaderComposite decodeHeader(
ByteArray & sbeMessageBytes,
size_t & offset)
{
PacketHeaderComposite packetHeader;
PreMessageHeaderComposite preMessageHeader;
MessageHeaderComposite messageHeader;
packetHeader = *reinterpret_cast<PacketHeaderComposite *>(reinterpret_cast<void *>(&sbeMessageBytes[0]));
offset += sizeof(packetHeader);
preMessageHeader = *reinterpret_cast<PreMessageHeaderComposite *>(reinterpret_cast<void *>(&sbeMessageBytes[offset]));
offset += sizeof(preMessageHeader);
messageHeader = *reinterpret_cast<MessageHeaderComposite *>(reinterpret_cast<void *>(&sbeMessageBytes[offset]));
offset += sizeof(messageHeader);
return messageHeader;
}
void decode()
{
SbeImprovePerformanceLibrary coderLib;
const std::string sbeTemplates = readTextFile("CmeSbeTemplate.xml");
Decoder decoder(sbeTemplates, &coderLib);
std::string sbeMessageBase64 = readTextFile("cmeSbeMessage.base64", true);
Base64Encoding::decode(sbeMessageBytes, sbeMessageBase64);
size_t offset = 0;
MessageHeaderComposite messageHeader = decodeHeader(sbeMessageBytes, offset);
const unsigned char * msg = &sbeMessageBytes[0] + offset;
PrecisionTimer timer;
const int numberOfMessages = 1000000;
for(int i = 0; i < numberOfMessages; ++i)
decoder.decode(messageHeader.templateId, messageHeader.version, messageHeader.blockLength, msg, sbeMessageBytes.size());
timer.stop();
long performance = timer.itemsPerSecond(numberOfMessages);
std::clog << std::endl << "\tSBE Decoding: " << performance << " msg/sec " << std::endl << std::endl;
const Message & decodedMessage = decoder.decode(messageHeader.templateId, messageHeader.version, messageHeader.blockLength, msg, sbeMessageBytes.size());
std::clog << "Decoded message: " << decodedMessage << std::endl;
}
void decodeEventBased()
{
std::string sbeTemplates = readTextFile("CmeSbeTemplate.xml");
EventBasedDecoder decoder(sbeTemplates);
std::string sbeMessageBase64 = readTextFile("cmeSbeMessage.base64", true);
Base64Encoding::decode(sbeMessageBytes, sbeMessageBase64);
size_t offset = 0;
MessageHeaderComposite messageHeader = decodeHeader(sbeMessageBytes, offset);
const unsigned char * msg = &sbeMessageBytes[0] + offset;
PrecisionTimer timer;
CountingListener listener;
size_t usedSize = 0;
const int numberOfMessages = 10000000;
for(int i = 0; i < numberOfMessages; ++i)
decoder.decodeSingleMessage(messageHeader.templateId, messageHeader.version, messageHeader.blockLength, msg, 0, sbeMessageBytes.size(), &listener, &usedSize);
timer.stop();
long performance = timer.itemsPerSecond(numberOfMessages);
std::clog << std::endl << "\tSBE event-based decoding: " << performance << " msg/sec " << std::endl << std::endl;
std::clog << "Messages: " << listener.completedMessageCount() << std::endl;
std::clog << "Fields: " << listener.fieldCount() << std::endl;
}
};