OnixS C++ ICE Binary Order Entry Handler 1.2.3
API Documentation
Loading...
Searching...
No Matches
Benchmark Sample

This sample demonstrates how to measure latency and use the warm-up feature.

Using OpenOnload® Network Stack

OpenOnload is part of Solarflare’s suite of network acceleration technologies.

To achieve better results, use the latency profile. For example:

$ ./run-under-onload.sh --host 192.168.28.1 --port 20054 --mainThreadCpu 1 --receivingThreadCpu 2

TCP Loopback Acceleration

The TCP loopback acceleration is turned off by default. It is configured via the environment variables EF_TCP_CLIENT_LOOPBACK and EF_TCP_SERVER_LOOPBACK.

Activate

$ export EF_TCP_CLIENT_LOOPBACK=1 $ export EF_TCP_SERVER_LOOPBACK=1

Verify

$ echo $EF_TCP_CLIENT_LOOPBACK
$ echo $EF_TCP_SERVER_LOOPBACK

Source code

1/*
2 * Copyright Onix Solutions Limited [OnixS]. All rights reserved.
3 *
4 * This software owned by Onix Solutions Limited [OnixS] and is protected by copyright law
5 * and international copyright treaties.
6 *
7 * Access to and use of the software is governed by the terms of the applicable ONIXS Software
8 * Services Agreement (the Agreement) and Customer end user license agreements granting
9 * a non-assignable, non-transferable and non-exclusive license to use the software
10 * for it's own data processing purposes under the terms defined in the Agreement.
11 *
12 * Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
13 * of this source code or associated reference material to any other location for further reproduction
14 * or redistribution, and any amendments to this copyright notice, are expressly prohibited.
15 *
16 * Any reproduction or redistribution for sale or hiring of the Software not in accordance with
17 * the terms of the Agreement is a violation of copyright law.
18 */
19// Uncomment to disable using of huge pages.
20//#define ONIXS_USE_HUGE_PAGE 0
21
22// Uncomment to enable debug mode.
23//#define ONIXS_DEBUGGING
24
25#include <iostream>
26
28
29using namespace ONIXS_ICEBOE_NAMESPACE;
31
32#include <Settings/Defaults.h>
33#include <Common/Helpers.h>
34#include <Common/Listener.h>
35#include <Common/Settings.h>
36#include <Common/Signal.h>
37#include <Common/Tools.h>
38#include <Common/Emulator.h>
40
41using namespace Samples;
42
43int main(int argc, char* argv[])
44{
45 // `--help` to show options.
46 const AppConfiguration<
54 > cfg{"Benchmark", argc, argv};
55
56 try
57 {
58 const auto numberOfMessages = cfg.numberOfMessages();
59 const auto warmupInterval = cfg.warmupInterval();
60 const auto intervalBetweenSending = (std::max)(cfg.intervalBetweenSending(), warmupInterval);
61 const auto storageType = cfg.storage();
62 const auto receivingThreadAffinity = cfg.receivingThreadCpu();
63
64 ThisThread::affinity(cfg.mainThreadCpu());
66
67 auto settings = fillSettings(cfg);
68 const auto emulator = createEmulator(settings, cfg);
69
70 // Request Binary Order Gateway credentials from Binary Utility Service Gateway
71 const auto bgwCredentials = receiveBgwCredentials(settings, cfg.host(), cfg.port());
72
73 settings
74 .receiveSpinningTimeout(1000 * 1000)
75 .useSpinLock(true)
76 .logBeforeSending(false);
77
78 class BenchmarkListener final : public BenchmarkSessionListener
79 {
80 public:
81 explicit BenchmarkListener(size_t numberOfMessages)
82 : BenchmarkSessionListener(numberOfMessages)
83 {}
84
85 using SessionListener::onError;
86
87 void onError(
88 SessionErrorReason::Enum reason, const std::string & description, Session * session, Messaging::SbeMessage msg) override
89 {
90 BenchmarkSessionListener::onError(reason, description, session, msg);
91 receivedAllMessages_.set_exception(std::make_exception_ptr(std::runtime_error(description)));
92 }
93
95 void collectSessionTimeMarks(Session & session, MessageHolder<NewOrderRequest> & order,
96 size_t numberOfMessages, size_t sendPeriodUsec, size_t warmupPeriodUsec)
97 {
98 receivedAllMessages_ = std::promise<void>{};
99
100 resetBenchmark();
101
102 auto sendingTime = UtcWatch::now();
103
104 for(uint64_t messageCounter = 0; messageCounter < numberOfMessages; ++messageCounter)
105 {
106 order->orderQty(messageCounter + 1);
107 order->clOrdId(messageCounter);
108
109 beforeSending();
110 session.send(order, sendingTime);
111 afterSending();
112
113 sendingTime = UtcWatch::now();
114
115 if(warmupPeriodUsec)
116 {
117 const auto start = PerformanceCounter::current();
118
119 do
120 {
121 ThisThread::spinWait(warmupPeriodUsec);
122 session.warmUp(order, sendingTime);
123 }
124 while(PerformanceCounter::elapsedMicroseconds(start) < static_cast<PerformanceCounter::Span>(sendPeriodUsec));
125 }
126 else if(sendPeriodUsec)
127 {
128 ThisThread::spinWait(sendPeriodUsec);
129 }
130 }
131
132 waitUntilReceivedAllMessages();
133 }
134
135 private:
136 void onReceivedAllMessages() override
137 {
139 receivedAllMessages_.set_value();
140 }
141
142 void waitUntilReceivedAllMessages()
143 {
144 auto future = receivedAllMessages_.get_future();
145
146 if(future.wait_for(std::chrono::seconds{120}) != std::future_status::ready)
147 receivedAllMessages_.set_exception(std::make_exception_ptr(std::runtime_error("Operation timed out.")));
148
149 future.get();
150 }
151
152 std::promise<void> receivedAllMessages_;
153 }
154 listener{numberOfMessages};
155
156 printBenchmarkSettings(std::clog, numberOfMessages, intervalBetweenSending, warmupInterval, storageType);
157
158 const auto bgwSession= makeUnique<BgwSession>(settings, &listener, cfg.storage());
159
160 const auto guard = setPriorityAndPolicy(bgwSession.get());
161
162 listener.measureOverhead();
163
164 bgwSession->
165 receivingThreadAffinity(receivingThreadAffinity)
166 .sendingThreadAffinity(Default::AuxiliarySendingThreadAffinity)
167 .connect(bgwCredentials.host(), bgwCredentials.port(), bgwCredentials.ipSessionToken());
168
169 auto order = Helper::createOrder(cfg.traderId());
170
171 std::clog << "\nWarm-up phase to make first calls faster..." << std::endl;
172 listener.collectSessionTimeMarks(*bgwSession, order, numberOfMessages, intervalBetweenSending, warmupInterval);
173
174 std::clog << "\nMeasurement phase..." << std::endl;
175 listener.collectSessionTimeMarks(*bgwSession, order, numberOfMessages, intervalBetweenSending, warmupInterval);
176
177 TcpInfo tcpInfo;
178 const bool hasTcpInfo = bgwSession->getTcpInfo(tcpInfo);
179
180 bgwSession->disconnect();
181
182 if(listener.packetGroupingDetected())
183 std::clog << "Attention: packet grouping detected! Increase the interval between sending!" << std::endl;
184
185 BenchmarkData::reportResults("Latency", listener.sendMarks(), listener.receiveMarks(), numberOfMessages, listener.overhead());
186
187 if(hasTcpInfo)
188 std::clog << "\n\n" << tcpInfo.toString();
189 }
190 catch (const std::exception& ex)
191 {
192 std::cerr << "\nEXCEPTION: " << ex.what() << std::endl;
193 return 1;
194 }
195
196 return 0;
197}
198
#define ONIXS_ICEBOE_NAMESPACE
Definition ABI.h:113
#define ONIXS_ICEBOE_MESSAGING_NAMESPACE
Definition ABI.h:114
int main(int argc, char *argv[])
#define ONIXS_ICEBOE_HOTPATH
Definition Compiler.h:156
void onError(SessionErrorReason::Enum, const std::string &description, Session *, Messaging::SbeMessage) override
Session & warmUp(Messaging::MessageHolder< SbeMessageType, MaxMessageSize > &msg, Messaging::Timestamp sendingTime=UtcWatch::now(), int warmupFlags=0)
Warms up the sending path.
Definition Session.h:674
Session & send(Messaging::MessageHolder< SbeMessageType, MaxMessageSize, MessageInitializer > &msg, Messaging::Timestamp sendingTime=UtcWatch::now())
Sends the message.
Definition Session.h:659
static void affinity(const CpuIndexes &cpuIndexes)
Sets the processor affinity mask for the current thread. The thread is rescheduled after this call.
static Span elapsedMicroseconds(const PerformanceCounter::Count &start)
static Count current()
Retrieves the current value of the high-resolution performance counter.
static MessageHolder< NewOrderRequest > createOrder(const std::string &traderId)
Definition Helpers.h:104
constexpr Threading::CpuIndex AuxiliarySendingThreadAffinity
Definition Defaults.h:42
std::shared_ptr< void > setPriorityAndPolicy(Session *session=nullptr)
Definition Helpers.h:150
std::pair< std::unique_ptr< GatewayEmulatorThread< BusSessionGatewayListener > >, std::unique_ptr< GatewayEmulatorThread< GatewayListener > > > createEmulator(const SessionSettings &settings, const ConnectivityConfiguration &cfg, bool tcpDirect=false)
Definition Emulator.h:159
BgwCredentials receiveBgwCredentials(SessionSettings settings, std::string host, Port port)
Definition Listener.h:265
SessionSettings fillSettings(const LogonConfiguration &logonCfg, const ConnectivityConfiguration &connCfg, const SettingsConfiguration &settingsCfg)
Definition Settings.h:32
void printBenchmarkSettings(std::ostream &o, size_t numberOfMessages, size_t intervalBetweenSending, size_t warmupInterval, SessionStorageType::Enum storageType)
Definition Helpers.h:182
std::unique_ptr< T > makeUnique(Args &&...args)
Definition Tools.h:30
static void reportResults(const std::string &name, const SendMarks *sendMarksArray, const ReceiveMarks *receiveMarksArray, std::size_t count, const Overhead &overhead)
TCP state information.
Definition TcpInfo.h:30
std::string toString() const
static void manageSignals() noexcept
Definition Signal.h:46