OnixS C++ ICE Binary Order Entry Handler 1.1.1
API Documentation
Loading...
Searching...
No Matches
BenchmarkData.h
Go to the documentation of this file.
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#pragma once
20
21#include "PerformanceCounter.h"
22
23#include <numeric>
24#include <string>
25#include <vector>
26#include <iostream>
27#include <iomanip>
28#include <cmath>
29#include <fstream>
30#include <ios>
31#include <cstddef>
32
33#ifndef _WIN32
34#include <stdlib.h>
35#endif
36
38{
57
70
71 // Measurement overhead
81
86
87 typedef std::vector<PerformanceCounter::Span> Latencies;
88
90 {
91 explicit SquareVariance(double mean)
92 : mean_(mean)
93 {}
94
95 double operator()(double sum, PerformanceCounter::Span value) const
96 {
97 return sum + std::pow(static_cast<double>(value) - mean_, 2u);
98 }
99
100 double mean_;
101 };
102
103 static double stdDev(const Latencies& data)
104 {
105 const std::size_t size = data.size();
106 assert(size > 1);
107
108 const double mean = std::accumulate(data.begin(), data.end(), static_cast<double>(0.0f)) / size;
109
110 return std::sqrt(
111 std::accumulate(data.begin(), data.end(), static_cast<double>(0.0f), SquareVariance(mean)) / (size - 1));
112 }
113
114 static void processAndReportLatencies(const std::string & name, Latencies & latencies)
115 {
116 sort(latencies.begin(), latencies.end());
117
118 const std::size_t NameWidth = 23;
119
120 std::clog << std::setw(NameWidth) << std::left << name;
121
122 if(name.length() > NameWidth)
123 std::clog << std::endl << std::setw(NameWidth) << ' ';
124
125 std::clog
126 << std::right
127 << "min: " << std::setw(7) << *latencies.begin()
128 << " median: " << std::setw(7) << latencies.at(latencies.size() / 2)
129 << " 99th percentile: " << std::setw(6)
130 << latencies.at(static_cast<std::size_t>(std::ceil((latencies.size() * 99) / 100.0)) - 1)
131 << " stdDev: " << std::setw(10) << std::fixed << std::setprecision(2) << stdDev(latencies)
132 << std::endl;
133 }
134
135 static void reportResults(
136 const std::string & name, const SendMarks * sendMarksArray, const ReceiveMarks * receiveMarksArray,
137 std::size_t count, const Overhead & overhead)
138 {
139 const std::string baseName = name + '_';
140
141 std::ofstream receiveStream(std::string(baseName + "recv.csv").c_str(), std::ios_base::ate);
142 std::ofstream sendStream(std::string(baseName + "send.csv").c_str(), std::ios_base::ate);
143 std::ofstream overallSendStream(std::string(baseName + "overallsend.csv").c_str(), std::ios_base::ate);
144 std::ofstream sendAndReceiveStream(std::string(baseName + "sendrecv.csv").c_str(), std::ios_base::ate);
145
146#define MEASURE_NETWORK_LATENCY 1 // Includes the network-related latency and CME's or emulator processing time.
147
148#if MEASURE_NETWORK_LATENCY
149 std::ofstream oneWayStream(std::string(baseName + "oneway.csv").c_str(), std::ios_base::ate);
150 Latencies oneWayLatencies;
151#endif
152
153 Latencies sendLatencies, overallSendLatencies, receiveLatencies, sendAndReceiveLatencies;
154
155 for(std::size_t i = 0; i < count; ++i)
156 {
157 const SendMarks & sendMarks = sendMarksArray[i];
158 const ReceiveMarks & receiveMarks = receiveMarksArray[i];
159
160 assert(!PerformanceCounter::isUndefinedValue(receiveMarks.recvStart));
161
162 receiveLatencies.push_back(receiveMarks.recvSpanNano() - overhead.receive);
163 receiveStream << *receiveLatencies.rbegin() << std::endl;
164
165 sendLatencies.push_back(sendMarks.sendSpanNano() - overhead.send);
166 sendStream << *sendLatencies.rbegin() << std::endl;
167
168 overallSendLatencies.push_back(sendMarks.overallSendSpanNano() - overhead.overallSend);
169 overallSendStream << *overallSendLatencies.rbegin() << std::endl;
170
171 const PerformanceCounter::Span sendAndReceiveLatency = *sendLatencies.rbegin() + *receiveLatencies.rbegin();
172 sendAndReceiveLatencies.push_back(sendAndReceiveLatency);
173 sendAndReceiveStream << *sendAndReceiveLatencies.rbegin() << std::endl;
174
175#if MEASURE_NETWORK_LATENCY
176 oneWayLatencies.push_back((oneWaySpanNano(sendMarks, receiveMarks) - overhead.oneWay) / 2);
177 oneWayStream << *oneWayLatencies.rbegin() << std::endl;
178#endif
179 }
180
181 std::clog << std::endl << name << " (nanoseconds): \n" << std::endl;
182
183 processAndReportLatencies("Handler Receive", receiveLatencies);
184 processAndReportLatencies("Handler Send", sendLatencies);
185 processAndReportLatencies("Handler Send+Receive", sendAndReceiveLatencies);
187 "OS + Handler Send (depends on the network card, kernel bypass software, OS load)",
188 overallSendLatencies
189 );
190
191#if MEASURE_NETWORK_LATENCY
192 processAndReportLatencies("One-Way (Round-Trip/2)", oneWayLatencies);
193#endif
194
195#define REPORT_OVERHEAD 1
196
197#if REPORT_OVERHEAD
198 std::clog
199 << std::endl << "Measurement overhead:" << std::endl
200 << "Send: " << overhead.send << std::endl
201 << "Receive: " << overhead.receive << std::endl
202 << "Send+Receive: " << overhead.send + overhead.receive << std::endl
203 << "OS + Handler Send: " << overhead.overallSend << std::endl;
204#endif
205
206#if MEASURE_NETWORK_LATENCY
207 std::clog << "One way:" << overhead.oneWay << std::endl;
208#endif
209 }
210};
static Span nsSpan(const PerformanceCounter::Count &stop, const PerformanceCounter::Count &start)
static bool isUndefinedValue(const Count &value)
PerformanceCounter::Span receive
PerformanceCounter::Span oneWay
PerformanceCounter::Span overallSend
PerformanceCounter::Span send
PerformanceCounter::Span recvSpanNano() const
PerformanceCounter::Count recvStart
PerformanceCounter::Count recvFinish
PerformanceCounter::Span sendSpanNano() const
PerformanceCounter::Count sendStart
PerformanceCounter::Count sendFinish
PerformanceCounter::Span overallSendSpanNano() const
PerformanceCounter::Count overallSendFinish
double operator()(double sum, PerformanceCounter::Span value) const
static double stdDev(const Latencies &data)
std::vector< PerformanceCounter::Span > Latencies
static void processAndReportLatencies(const std::string &name, Latencies &latencies)
static PerformanceCounter::Span oneWaySpanNano(const SendMarks &sm, const ReceiveMarks &rm)
static void reportResults(const std::string &name, const SendMarks *sendMarksArray, const ReceiveMarks *receiveMarksArray, std::size_t count, const Overhead &overhead)