Commit 5ae6269e authored by John Selbie's avatar John Selbie

Benchmarking code

parent da197c48
include ../common.inc
PROJECT_TARGET := libcommon.a
PROJECT_SRCS := atomichelpers.cpp cmdlineparser.cpp common.cpp crc32.cpp fasthash.cpp getconsolewidth.cpp getmillisecondcounter.cpp logger.cpp prettyprint.cpp stringhelper.cpp
PROJECT_SRCS := atomichelpers.cpp cmdlineparser.cpp common.cpp condmutex.cpp crc32.cpp fasthash.cpp getconsolewidth.cpp getmillisecondcounter.cpp logger.cpp prettyprint.cpp stringhelper.cpp
PROJECT_OBJS := $(subst .cpp,.o,$(PROJECT_SRCS))
INCLUDES := $(BOOST_INCLUDE)
PRECOMP_H_GCH := commonincludes.hpp.gch
......
#include "commonincludes.hpp"
#include "condmutex.h"
ConditionAndMutex::ConditionAndMutex()
{
pthread_cond_init(&_cond, nullptr);
pthread_mutex_init(&_mutex, nullptr);
}
ConditionAndMutex::~ConditionAndMutex()
{
pthread_cond_destroy(&_cond);
pthread_mutex_destroy(&_mutex);
}
void ConditionAndMutex::Wait(std::function<bool()> func)
{
pthread_mutex_lock(&_mutex);
bool testcondition = func();
while (testcondition == false)
{
pthread_cond_wait(&_cond, &_mutex);
testcondition = func();
}
pthread_mutex_unlock(&_mutex);
}
void ConditionAndMutex::ExecuteAndSignal(std::function<void()> func)
{
pthread_mutex_lock(&_mutex);
func();
pthread_mutex_unlock(&_mutex);
pthread_cond_broadcast(&_cond);
}
#ifndef STUN_COND_AND_MUTEX
#define STUN_COND_AND_MUTEX
#include <functional>
class ConditionAndMutex
{
pthread_mutex_t _mutex;
pthread_cond_t _cond;
public:
ConditionAndMutex();
~ConditionAndMutex();
void Wait(std::function<bool()> func);
void ExecuteAndSignal(std::function<void()> func);
};
#endif
......@@ -354,6 +354,7 @@ HRESULT CStunSocketThread::ProcessRequestAndSendResponse()
HRESULT hr = S_OK;
int sendret = -1;
int sockout = -1;
int err = 0;
// Reset the reader object and re-attach the buffer
_reader.Reset();
......@@ -375,11 +376,12 @@ HRESULT CStunSocketThread::ProcessRequestAndSendResponse()
// find the socket that matches the role specified by msgOut
sendret = ::sendto(sockout, _spBufferOut->GetData(), _spBufferOut->GetSize(), 0, _msgOut.addrDest.GetSockAddr(), _msgOut.addrDest.GetSockAddrLength());
err = (sendret == -1) ? errno : 0;
if (Logging::GetLogLevel() >= LL_VERBOSE)
{
Logging::LogMsg(LL_VERBOSE, "sendto returns %d (err == %d)\n", sendret, errno);
Logging::LogMsg(LL_VERBOSE, "sendto returns %d (err == %d)\n", sendret, (int)err);
}
......
include ../common.inc
PROJECT_TARGET := stuntestcode
PROJECT_OBJS := testatomichelpers.o testbuilder.o testclientlogic.o testcmdline.o testcrc32.o testcode.o testdatastream.o testfasthash.o testintegrity.o testmessagehandler.o testpolling.o testratelimiter.o testreader.o testrecvfromex.o
PROJECT_OBJS := benchmark.o testatomichelpers.o testbuilder.o testclientlogic.o testcmdline.o testcrc32.o testcode.o testdatastream.o testfasthash.o testintegrity.o testmessagehandler.o testpolling.o testratelimiter.o testreader.o testrecvfromex.o
INCLUDES := $(BOOST_INCLUDE) $(OPENSSL_INCLUDE) -I../common -I../stuncore -I../networkutils
LIB_PATH := -L../networkutils -L../stuncore -L../common
......
#include "commonincludes.hpp"
#include "condmutex.h"
#include <atomic>
#include <iostream>
#include <functional>
#include "stuncore.h"
#include "oshelper.h"
class Benchmark
{
pthread_mutex_t _mutexReady;
ConditionAndMutex _cmReady;
ConditionAndMutex _cmGo;
ConditionAndMutex _cmCompleted;
bool _shouldRun;
size_t _readyCount;
size_t _completedCount;
std::atomic<size_t> _counter;
uint32_t _startTimeMS;
uint32_t _endTimeMS;
size_t _iterations;
size_t _threads;
public:
Benchmark(size_t iterations, size_t threads);
void Run();
void* ThreadFunc();
static void* s_ThreadFunction(void* pThis);
};
Benchmark::Benchmark(size_t iterations, size_t threads):
_shouldRun(false),
_readyCount(threads),
_completedCount(threads),
_startTimeMS(0),
_endTimeMS(0),
_iterations(iterations),
_threads(threads)
{
}
void* Benchmark::s_ThreadFunction(void* pThis)
{
Benchmark* pBM = reinterpret_cast<Benchmark*>(pThis);
return pBM->ThreadFunc();
}
void* Benchmark::ThreadFunc()
{
// simulate a binding request coming in
TransportAddressSet tsa;
tsa.set[0].fValid = true;
CStunMessageBuilder builder;
builder.AddHeader(StunMsgTypeBinding, StunMsgClassRequest);
builder.AddRandomTransactionId(nullptr);
CRefCountedBuffer buffer;
builder.GetResult(&buffer);
StunMessageOut msgOut;
auto spBufferOut = CRefCountedBuffer(new CBuffer(MAX_STUN_MESSAGE_SIZE));
auto spBufferReader = CRefCountedBuffer(new CBuffer(MAX_STUN_MESSAGE_SIZE));
msgOut.spBufferOut = spBufferOut;
size_t stoppoint = _iterations;
CStunMessageReader reader;
_cmReady.ExecuteAndSignal([this](){_readyCount--;});
_cmGo.Wait([this]() {return _shouldRun;});
while (_counter.load() < _iterations)
{
reader.Reset();
spBufferReader->SetSize(0);
reader.GetStream().Attach(spBufferReader, true);
reader.AddBytes(buffer->GetData(), buffer->GetSize());
if (reader.GetState() != CStunMessageReader::BodyValidated)
{
Logging::LogMsg(LL_ALWAYS, "Error in CStunMessageReader::GetState");
break;
}
StunMessageIn msgIn;
msgIn.fConnectionOriented = false;
msgIn.pReader = &reader;
msgIn.socketrole = RolePP;
HRESULT hr = CStunRequestHandler::ProcessRequest(msgIn, msgOut, &tsa, nullptr);
if (FAILED(hr))
{
Logging::LogMsg(LL_ALWAYS, "Error in ProcessRequest (hr == %x)", hr);
break;
}
size_t prev = _counter.fetch_add(1);
if (prev == (stoppoint - 1))
{
_endTimeMS = GetMillisecondCounter();
}
}
_cmCompleted.ExecuteAndSignal([this](){_completedCount--;});
return nullptr;
}
void Benchmark::Run()
{
_readyCount = _threads;
_completedCount = _threads;
_shouldRun = false;
_counter.store(0);
_endTimeMS = 0;
_startTimeMS = 0;
std::vector<pthread_t> threadList;
for (size_t t = 0; t < _threads; t++)
{
pthread_t pt = 0;
pthread_create(&pt, nullptr, s_ThreadFunction, this);
threadList.push_back(pt);
}
_cmReady.Wait([this]() {return (_readyCount <= 0);});
_endTimeMS = GetMillisecondCounter();
_startTimeMS = _endTimeMS;
_cmGo.ExecuteAndSignal([this](){_shouldRun = true;});
_cmCompleted.Wait([this]() {return _completedCount <= 0;});
for (size_t t = 0; t < _threads; t++)
{
pthread_join(threadList[t], nullptr);
}
std::cout << "Start Time: " << _startTimeMS << std::endl;
std::cout << "End Time: " << _endTimeMS << std::endl;
std::cout << "Final Count: " << _counter.load() << std::endl;
std::cout << "Result: " << (_endTimeMS - _startTimeMS) << std::endl;
}
void benchmark_test(int threads)
{
if (threads <= 0)
{
threads = 1;
}
std::cout << "Running benchmark witih " << threads << " threads." << std::endl;
auto iterations = 100000000;
Benchmark bm(iterations, threads);
bm.Run();
}
......@@ -136,16 +136,20 @@ void PrettyPrintTest()
delete [] buffer;
}
void benchmark_test(int threads);
int main(int argc, char** argv)
{
CCmdLineParser cmdline;
std::string strFuzz;
std::string strPP;
std::string strBench;
bool fParseError = false;
cmdline.AddOption("fuzz", no_argument, &strFuzz);
cmdline.AddOption("pp", no_argument, &strPP);
cmdline.AddOption("bench", optional_argument, &strBench);
cmdline.ParseCommandLine(argc, argv, 1, &fParseError);
......@@ -157,6 +161,11 @@ int main(int argc, char** argv)
{
PrettyPrintTest();
}
else if (strBench.size() > 0)
{
int threads = atoi(strBench.c_str());
benchmark_test(threads);
}
else
{
RunUnitTests();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment