Skip to content
Snippets Groups Projects
Commit 6c556ad4 authored by samarth5's avatar samarth5
Browse files

Benchmarking module complete with dequeue and enqueue operations

parent 818aa561
No related branches found
No related tags found
No related merge requests found
#include "Measurements.h"
#include "IQueue.h"
#include <algorithm>
#include <thread>
#include <chrono>
#include <numeric>
#include <assert.h>
#include <math.h>
using namespace std;
using namespace std::chrono;
template <class T>
class Benchmark
{
private:
double GetEnqueueBenchmarkSingle(Operation<T> operationToPerform)
{
IQueue<T>& baseQueue = *(operationToPerform.BaseQueuePointer->GetInstance());
thread workers[operationToPerform.NumberOfThreads];
auto start = high_resolution_clock::now();
for (int i = 0; i < operationToPerform.NumberOfThreads; i++)
{
workers[i] = thread(operationToPerform.EnqueueOperation, ref(baseQueue),
operationToPerform.NumberOfEnqueueRepititions);
}
for (int i = 0; i < operationToPerform.NumberOfThreads; i++)
{
workers[i].join();
}
auto end = high_resolution_clock::now();
duration<double> diff = end-start;
assert(baseQueue.GetSize() == operationToPerform.NumberOfThreads *
operationToPerform.NumberOfEnqueueRepititions);
return diff.count();
}
double GetEnqueueDequeueBenchmarkSingle(Operation<T> operationToPerform)
{
IQueue<T>& baseQueue = *(operationToPerform.BaseQueuePointer->GetInstance());
thread workers[operationToPerform.NumberOfThreads];
auto start = high_resolution_clock::now();
for (int i = 0; i < operationToPerform.NumberOfThreads - 1; i++)
{
workers[i] = thread(operationToPerform.EnqueueOperation, ref(baseQueue),
operationToPerform.NumberOfEnqueueRepititions);
}
workers[operationToPerform.NumberOfThreads - 1] = thread(operationToPerform.DequeueOperation,
ref(baseQueue), operationToPerform.NumberOfDequeueRepititions,
operationToPerform.NumberOfMicroSecondsToDequeueFor);
for (int i = 0; i < operationToPerform.NumberOfThreads; i++)
{
workers[i].join();
}
auto end = high_resolution_clock::now();
duration<double> diff = end-start;
long totalDequeued = operationToPerform.NumberOfDequeueRepititions * operationToPerform.NumberOfMicroSecondsToDequeueFor;
long totalEnqueued = (operationToPerform.NumberOfThreads - 1) * operationToPerform.NumberOfEnqueueRepititions;
long totalLeft = totalDequeued >= totalEnqueued ? 0 : totalEnqueued - totalDequeued;
assert((long)baseQueue.GetSize() == totalLeft);
return diff.count();
}
public:
Measure GetBenchmarkMeasure(Operation<T> operationToPerform, bool onlyEnqueue, int numberOfMeasurements)
{
vector<double> measurements;
while (numberOfMeasurements--)
{
if (onlyEnqueue)
{
measurements.push_back(GetEnqueueBenchmarkSingle(operationToPerform));
}
else
{
measurements.push_back(GetEnqueueDequeueBenchmarkSingle(operationToPerform));
}
}
double sum = accumulate(begin(measurements), end(measurements), 0.0);
double mean = sum / measurements.size();
double accum = 0.0;
for_each (begin(measurements), end(measurements), [&](const double d)
{
accum += (d - mean) * (d - mean);
});
double sd = sqrt(accum / (measurements.size() - 1));
return Measure(mean, sd);
}
};
#include <iostream>
#include "Measurements.h"
#include "LockQueue.cpp"
#include <chrono>
#include <numeric>
#include <thread>
#include <assert.h>
#include "Benchmark.cpp"
#include <cxxabi.h>
#include <iostream>
using namespace std;
using namespace std::chrono;
#define quote(x) #x
......@@ -18,49 +16,49 @@ void EnqueueNItems(IQueue<T> &queue, int n)
{
for (int i = 0; i < n; i++)
{
queue.enqueue(NumberToEnqueue);
queue.Enqueue(NumberToEnqueue);
}
}
template <class T>
void CreateNThreadsAndPerformKOperations(string operatioName, void (*OperationToPerform)(IQueue<T>
&queueInstance, int numberOfRepititions), IQueue<T> *baseQueuePointer, int n, int k)
void DequeueNItems(IQueue<T> &queue, int n, int count)
{
IQueue<T> & baseQueue = *baseQueuePointer;
thread workers[n];
auto start = high_resolution_clock::now();
for (int i = 0; i < n; i++)
{
workers[i] = thread(OperationToPerform, ref(baseQueue), k);
}
for (int i = 0; i < n; i++)
while (count--)
{
workers[i].join();
}
auto end = high_resolution_clock::now();
duration<double> diff = end-start;
assert(baseQueue.size() == n*k);
for (int i = 0; i < n; i++)
{
if (!queue.IsEmpty())
{
queue.Dequeue();
}
}
int status;
char * demangledName = abi::__cxa_demangle(typeid(baseQueue).name(), 0, 0, &status);
printf("%s,%s,%f,%d,%d\n", demangledName, operatioName.c_str(), diff.count(), n, k);
this_thread::sleep_for(microseconds(1));
}
}
// 1. Try with different types of objects (ints, classes) to see if that affects the performance.
// 2. Try only enqueue operations.
// 3. Try enqueue and dequeue operations together.
int main()
{
cout<<"Queue,OperationName,TimeTakenToExecute,NumberOfThreads,NumberOfOperations"<<endl;
CreateNThreadsAndPerformKOperations(quote(EnqueueNItems), EnqueueNItems, new LockQueue<int>(),
100, 1000);
CreateNThreadsAndPerformKOperations(quote(EnqueueNItems), EnqueueNItems, new LockQueue<int>(),
100, 100000);
// cout<<"Queue,Operation1Name,Operation2Name,TimeTakenToExecute,NumberOfThreads,NumberOfOperations"<<endl;
Operation<int> enqueueOperation1(make_shared<LockQueue<int>>(), EnqueueNItems, 1, 100);
Operation<int> enqueueOperation2(make_shared<LockQueue<int>>(), EnqueueNItems, 1, 100000);
Operation<int> enqueueOperation3(make_shared<LockQueue<int>>(), EnqueueNItems, 100, 100);
Operation<int> enqueueOperation4(make_shared<LockQueue<int>>(), EnqueueNItems, 100, 100000);
int numberOfMicrosecondsToDequeueFor = 100;
Operation<int> enqueueDequeueOperation1(make_shared<LockQueue<int>>(), EnqueueNItems, 101, 100, DequeueNItems, 1, numberOfMicrosecondsToDequeueFor);
Operation<int> enqueueDequeueOperation2(make_shared<LockQueue<int>>(), EnqueueNItems, 101, 100000, DequeueNItems, 1, numberOfMicrosecondsToDequeueFor);
Operation<int> enqueueDequeueOperation3(make_shared<LockQueue<int>>(), EnqueueNItems, 101, 100, DequeueNItems, 100, numberOfMicrosecondsToDequeueFor);
Operation<int> enqueueDequeueOperation4(make_shared<LockQueue<int>>(), EnqueueNItems, 101, 100000, DequeueNItems, 100, numberOfMicrosecondsToDequeueFor);
Benchmark<int> benchmark;
cout<<benchmark.GetBenchmarkMeasure(enqueueOperation1, true, 5);
cout<<benchmark.GetBenchmarkMeasure(enqueueOperation2, true, 5);
cout<<benchmark.GetBenchmarkMeasure(enqueueOperation3, true, 5);
cout<<benchmark.GetBenchmarkMeasure(enqueueOperation4, true, 5);
cout<<benchmark.GetBenchmarkMeasure(enqueueDequeueOperation1, false, 5);
cout<<benchmark.GetBenchmarkMeasure(enqueueDequeueOperation2, false, 5);
cout<<benchmark.GetBenchmarkMeasure(enqueueDequeueOperation3, false, 5);
cout<<benchmark.GetBenchmarkMeasure(enqueueDequeueOperation4, false, 5);
}
\ No newline at end of file
......@@ -11,10 +11,11 @@ class IQueue
}
virtual bool isEmpty() = 0;
virtual void enqueue(T elementToQueue) = 0;
virtual T dequeue() = 0;
virtual int size() = 0;
virtual bool IsEmpty() = 0;
virtual void Enqueue(T elementToQueue) = 0;
virtual T Dequeue() = 0;
virtual long GetSize() = 0;
virtual IQueue<T>* GetInstance() = 0;
};
#endif
\ No newline at end of file
#include "IQueue.h"
#include <queue>
#include <mutex>
#include <iostream>
using namespace std;
......@@ -13,33 +14,34 @@ class LockQueue : public IQueue<T>
public:
virtual bool isEmpty()
virtual bool IsEmpty()
{
mutexInstance.lock();
lock_guard<mutex> lg(mutexInstance);
return queueInstance.empty();
mutexInstance.unlock();
}
virtual void enqueue(T elementToQueue)
virtual void Enqueue(T elementToQueue)
{
mutexInstance.lock();
lock_guard<mutex> lg(mutexInstance);
queueInstance.push(elementToQueue);
mutexInstance.unlock();
}
virtual T dequeue()
virtual T Dequeue()
{
mutexInstance.lock();
T frontElement = queueInstance.front();
lock_guard<mutex> lg(mutexInstance);
T fronElement = queueInstance.front();
queueInstance.pop();
return frontElement;
mutexInstance.unlock();
return fronElement;
}
virtual int size()
virtual long GetSize()
{
mutexInstance.lock();
lock_guard<mutex> lg(mutexInstance);
return queueInstance.size();
mutexInstance.unlock();
}
virtual IQueue<T>* GetInstance()
{
return new LockQueue<T>();
}
};
\ No newline at end of file
#ifndef MEASUREMENTS_H
#define MEASUREMENTS_H
#include "IQueue.h"
#include <iostream>
#include <memory>
using namespace std;
class Measure
{
public:
double Mean;
double Sd;
Measure()
{
}
Measure(double mean, double sd)
{
this->Mean = mean;
this->Sd = sd;
}
};
template<typename T>
using EnqueueOperationFunction = void (*)(IQueue<T> &, int);
template<typename T>
using DequeueOperationFunction = void (*)(IQueue<T> &, int, int);
template<class T>
class Operation
{
public:
int NumberOfThreads;
int NumberOfEnqueueRepititions;
int NumberOfDequeueRepititions;
int NumberOfMicroSecondsToDequeueFor;
shared_ptr<IQueue<T>> BaseQueuePointer;
EnqueueOperationFunction<T> EnqueueOperation;
DequeueOperationFunction<T> DequeueOperation;
Operation(shared_ptr<IQueue<T>> baseQueuePointer, EnqueueOperationFunction<T> enqueueOperation,
int numberOfThreads, int numberOfEnqueueRepititions)
{
this->EnqueueOperation = enqueueOperation;
this->NumberOfThreads = numberOfThreads;
this->NumberOfEnqueueRepititions = numberOfEnqueueRepititions;
this->BaseQueuePointer = baseQueuePointer;
}
Operation(shared_ptr<IQueue<T>> baseQueuePointer, EnqueueOperationFunction<T> enqueueOperation,
int numberOfThreads, int numberOfEnqueueRepititions, DequeueOperationFunction<T> dequeueOperation,
int numberOfDequeueRepititions, int numberOfMicroSecondsToDequeueFor)
{
this->EnqueueOperation = enqueueOperation;
this->DequeueOperation = dequeueOperation;
this->NumberOfThreads = numberOfThreads;
this->NumberOfEnqueueRepititions = numberOfEnqueueRepititions;
this->NumberOfDequeueRepititions = numberOfDequeueRepititions;
this->BaseQueuePointer = baseQueuePointer;
this->NumberOfMicroSecondsToDequeueFor = numberOfMicroSecondsToDequeueFor;
}
};
inline ostream& operator<<(ostream &strm, const Measure &measure)
{
return strm << "Mean: " << measure.Mean << " SD: " << measure.Sd << endl;
}
#endif
\ No newline at end of file
CXX = g++
CXXFLAGS = -Wall -g -std=c++11 -pthread
BenchmarkingModule: BenchmarkingModule.o LockQueue.o
$(CXX) $(CXXFLAGS) -o BenchmarkingModule BenchmarkingModule.o LockQueue.o
BenchmarkingModule: BenchmarkingModule.o Benchmark.o LockQueue.o Measurements.h
$(CXX) $(CXXFLAGS) -o BenchmarkingModule BenchmarkingModule.o LockQueue.o Benchmark.o
BenchmarkingModule.o: BenchmarkingModule.cpp
BenchmarkingModule.o: BenchmarkingModule.cpp LockQueue.cpp Benchmark.cpp Measurements.h
$(CXX) $(CXXFLAGS) -c BenchmarkingModule.cpp
LockQueue.o: IQueue.h
Benchmark.o: Benchmark.cpp IQueue.h Measurements.h
$(CXX) $(CXXFLAGS) -c Benchmark.cpp
LockQueue.o: LockQueue.cpp IQueue.h
$(CXX) $(CXXFLAGS) -c LockQueue.cpp
clean:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment