Add performance compare to Poco::NotifactionCenter

This commit is contained in:
Dawid Drozd 2018-07-24 14:16:05 +02:00
parent 1d25b99758
commit beb6599ee4
3 changed files with 239 additions and 145 deletions

View File

@ -3,11 +3,13 @@ cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
# http://www.levelofindirection.com/journal/2010/12/28/unit-testing-in-c-and-objective-c-just-got-easier.html
# Thanks for CATCH!
find_package(Poco COMPONENTS Foundation Util)
add_subdirectory(benchmark/)
if(NOT TARGET Dexode::EventBus)
if (NOT TARGET Dexode::EventBus)
find_package(EventBus CONFIG REQUIRED)
endif()
endif ()
# If you want to compare with CCNotificationCenter read about it in README and uncomment line below
#INCLUDE(cocos2d-x-compare/Cocos2dxCompare.cmake)
@ -15,6 +17,7 @@ endif()
add_executable(EventBusPerformance
src/EventBusPerformance.cpp
${CCNOTIFICATION_CENTER_SRC}
$<$<BOOL:${Poco_FOUND}>:src/PocoEventBus.cpp>
)
target_compile_options(EventBusPerformance PUBLIC
@ -38,4 +41,9 @@ target_include_directories(EventBusPerformance PUBLIC
${CCNOTIFICATION_CENTER_INCLUDE}
)
target_link_libraries(EventBusPerformance PUBLIC Dexode::EventBus benchmark)
target_link_libraries(EventBusPerformance PUBLIC
Dexode::EventBus
benchmark
$<$<BOOL:${Poco_FOUND}>:Poco::Foundation>
$<$<BOOL:${Poco_FOUND}>:Poco::Util>
)

View File

@ -19,17 +19,15 @@ void checkNListeners(benchmark::State& state, const int listenersCount)
int value;
};
for (int i = 0; i < listenersCount; ++i)
for(int i = 0; i < listenersCount; ++i)
{
bus.listen<SimpleEvent>([&](const SimpleEvent& event)
{
benchmark::DoNotOptimize(sum += event.value * 2);
});
bus.listen<SimpleEvent>(
[&](const SimpleEvent& event) { benchmark::DoNotOptimize(sum += event.value * 2); });
}
const auto event = SimpleEvent{2};
while (state.KeepRunning())//Performance area!
while(state.KeepRunning()) // Performance area!
{
const auto event = SimpleEvent{2};
bus.notify(event);
}
state.counters["sum"] = sum;
@ -60,18 +58,15 @@ void call1kLambdas_compare(benchmark::State& state)
int sum = 0;
std::vector<std::function<void(int)>> callbacks;
callbacks.reserve(1000);
for (int i = 0; i < 1000; ++i)
for(int i = 0; i < 1000; ++i)
{
callbacks.emplace_back([&](int value)
{
benchmark::DoNotOptimize(sum += value * 2);
});
callbacks.emplace_back([&](int value) { benchmark::DoNotOptimize(sum += value * 2); });
}
while (state.KeepRunning())//Performance area!
while(state.KeepRunning()) // Performance area!
{
for (int i = 0; i < 1000; ++i)
// for (auto& callback :callbacks)
for(int i = 0; i < 1000; ++i)
// for (auto& callback :callbacks)
{
callbacks[i](2);
}
@ -79,140 +74,133 @@ void call1kLambdas_compare(benchmark::State& state)
state.counters["sum"] = sum;
}
template<int N>
template <int N>
struct SimpleEvent
{
int value = N;
};
void checkNNotificationsForNListeners(benchmark::State& state, const int notificationsCount, const int listenersCount)
void checkNNotificationsForNListeners(benchmark::State& state,
const int notificationsCount,
const int listenersCount)
{
std::mt19937 generator(311281);
std::uniform_int_distribution<int> uniformDistribution(0, notificationsCount - 1);
Dexode::EventBus bus;
int sum = 0;
for (int i = 0; i < listenersCount; ++i)//We register M listeners for N notifications using uniform distribution
for(int i = 0; i < listenersCount;
++i) // We register M listeners for N notifications using uniform distribution
{
const auto which = uniformDistribution(generator);
//We generate here N different notifications
switch (which)
// We generate here N different notifications
switch(which)
{
case 0:
bus.listen<SimpleEvent<0>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 1:
bus.listen<SimpleEvent<1>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 2:
bus.listen<SimpleEvent<2>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 3:
bus.listen<SimpleEvent<3>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 4:
bus.listen<SimpleEvent<4>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 5:
bus.listen<SimpleEvent<5>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 6:
bus.listen<SimpleEvent<6>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 7:
bus.listen<SimpleEvent<7>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 8:
bus.listen<SimpleEvent<8>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
case 9:
bus.listen<SimpleEvent<9>>([&](const auto& event)
{
benchmark::DoNotOptimize(sum += event.value *
2);//we use it to prevent some? optimizations
});
break;
default:
assert(false);
case 0:
bus.listen<SimpleEvent<0>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 1:
bus.listen<SimpleEvent<1>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 2:
bus.listen<SimpleEvent<2>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 3:
bus.listen<SimpleEvent<3>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 4:
bus.listen<SimpleEvent<4>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 5:
bus.listen<SimpleEvent<5>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 6:
bus.listen<SimpleEvent<6>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 7:
bus.listen<SimpleEvent<7>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 8:
bus.listen<SimpleEvent<8>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
case 9:
bus.listen<SimpleEvent<9>>([&](const auto& event) {
benchmark::DoNotOptimize(sum += event.value *
2); // we use it to prevent some? optimizations
});
break;
default:
assert(false);
}
}
while (state.KeepRunning())//Performance area!
while(state.KeepRunning()) // Performance area!
{
//Pick random notification
// Pick random notification
const auto which = uniformDistribution(generator);
const auto number = uniformDistribution(generator);
//We generate here N different notifications
switch (which)
// We generate here N different notifications
switch(which)
{
case 0:
bus.notify(SimpleEvent<0>{number});
break;
case 1:
bus.notify(SimpleEvent<1>{number});
break;
case 2:
bus.notify(SimpleEvent<2>{number});
break;
case 3:
bus.notify(SimpleEvent<3>{number});
break;
case 4:
bus.notify(SimpleEvent<4>{number});
break;
case 5:
bus.notify(SimpleEvent<5>{number});
break;
case 6:
bus.notify(SimpleEvent<6>{number});
break;
case 7:
bus.notify(SimpleEvent<7>{number});
break;
case 8:
bus.notify(SimpleEvent<8>{number});
break;
case 9:
bus.notify(SimpleEvent<9>{number});
break;
default:
assert(false);
case 0:
bus.notify(SimpleEvent<0>{number});
break;
case 1:
bus.notify(SimpleEvent<1>{number});
break;
case 2:
bus.notify(SimpleEvent<2>{number});
break;
case 3:
bus.notify(SimpleEvent<3>{number});
break;
case 4:
bus.notify(SimpleEvent<4>{number});
break;
case 5:
bus.notify(SimpleEvent<5>{number});
break;
case 6:
bus.notify(SimpleEvent<6>{number});
break;
case 7:
bus.notify(SimpleEvent<7>{number});
break;
case 8:
bus.notify(SimpleEvent<8>{number});
break;
case 9:
bus.notify(SimpleEvent<9>{number});
break;
default:
assert(false);
}
}
state.counters["sum"] = sum;
@ -223,18 +211,18 @@ void check10NotificationsFor1kListeners(benchmark::State& state)
checkNNotificationsForNListeners(state, 10, 1000);
}
//Sorry not available
//void check100NotificationsFor1kListeners(benchmark::State& state)
// Sorry not available
// void check100NotificationsFor1kListeners(benchmark::State& state)
//{
// checkNNotificationsForNListeners(state, 100, 1000);
//}
//
//void check1kNotificationsFor1kListeners(benchmark::State& state)
// void check1kNotificationsFor1kListeners(benchmark::State& state)
//{
// checkNNotificationsForNListeners(state, 1000, 1000);
//}
//
//void check100NotificationsFor10kListeners(benchmark::State& state)
// void check100NotificationsFor10kListeners(benchmark::State& state)
//{
// checkNNotificationsForNListeners(state, 100, 10000);
//}
@ -251,22 +239,19 @@ void checkNotifyFor10kListenersWhenNoOneListens(benchmark::State& state)
{
int value;
};
for (int i = 0; i < 10000; ++i)
for(int i = 0; i < 10000; ++i)
{
bus.listen<SimpleEvent>([&](const SimpleEvent& event)
{
benchmark::DoNotOptimize(sum += event.value * 2);
});
bus.listen<SimpleEvent>(
[&](const SimpleEvent& event) { benchmark::DoNotOptimize(sum += event.value * 2); });
}
const auto unknownEvent = UnknownEvent{2};
while (state.KeepRunning())//Performance area!
while(state.KeepRunning()) // Performance area!
{
bus.notify(unknownEvent);
}
state.counters["sum"] = sum;
}
}
BENCHMARK(call1kLambdas_compare);
@ -276,9 +261,9 @@ BENCHMARK(check10Listeners);
BENCHMARK(check100Listeners);
BENCHMARK(check1kListeners);
BENCHMARK(check10NotificationsFor1kListeners);
//BENCHMARK(check100NotificationsFor1kListeners); //Not available
//BENCHMARK(check1kNotificationsFor1kListeners); //Not available
//BENCHMARK(check100NotificationsFor10kListeners); //Not available
// BENCHMARK(check100NotificationsFor1kListeners); //Not available
// BENCHMARK(check1kNotificationsFor1kListeners); //Not available
// BENCHMARK(check100NotificationsFor10kListeners); //Not available
BENCHMARK(checkNotifyFor10kListenersWhenNoOneListens);
BENCHMARK_MAIN()

View File

@ -0,0 +1,101 @@
//
// Created by Dawid Drozd aka Gelldur on 24.07.18.
//
#include <functional>
#include <random>
#include <benchmark/benchmark.h>
#include <Poco/NObserver.h>
#include <Poco/Notification.h>
#include <Poco/NotificationCenter.h>
namespace
{
template <class T>
struct Wrapper : public Poco::Notification
{
T data;
Wrapper(T data)
: data(std::move(data))
{
}
};
template <class Egg>
class Target
{
public:
Target(std::function<void(const Egg&)> callback)
: _callback(std::move(callback))
{
}
void handle(const Poco::AutoPtr<Wrapper<Egg>>& event)
{
_callback((*event.get()).data);
}
private:
std::function<void(const Egg&)> _callback;
};
void checkNListeners(benchmark::State& state, const int listenersCount)
{
Poco::NotificationCenter bus;
int sum = 0;
struct SimpleEvent
{
int value;
};
using MyEvent = Wrapper<SimpleEvent>;
using Listener = Target<SimpleEvent>;
std::vector<Listener> targets;
targets.reserve(listenersCount + 1);
for(int i = 0; i < listenersCount; ++i)
{
targets.emplace_back(
[&](const SimpleEvent& event) { benchmark::DoNotOptimize(sum += event.value * 2); });
bus.addObserver(Poco::NObserver<Listener, MyEvent>(targets.back(), &Listener::handle));
}
while(state.KeepRunning()) // Performance area!
{
const Poco::AutoPtr<MyEvent> event = new Wrapper<SimpleEvent>{SimpleEvent{2}};
bus.postNotification(event);
}
state.counters["sum"] = sum;
}
void Poco_checkSimpleNotification(benchmark::State& state)
{
checkNListeners(state, 1);
}
void Poco_check10Listeners(benchmark::State& state)
{
checkNListeners(state, 10);
}
void Poco_check100Listeners(benchmark::State& state)
{
checkNListeners(state, 100);
}
void Poco_check1kListeners(benchmark::State& state)
{
checkNListeners(state, 1000);
}
BENCHMARK(Poco_checkSimpleNotification);
BENCHMARK(Poco_check10Listeners);
BENCHMARK(Poco_check100Listeners);
BENCHMARK(Poco_check1kListeners);
}