mirror of
https://github.com/gelldur/EventBus.git
synced 2024-12-27 12:21:02 +08:00
Add performance compare to Poco::NotifactionCenter
This commit is contained in:
parent
1d25b99758
commit
beb6599ee4
@ -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>
|
||||
)
|
@ -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()
|
||||
|
101
performance/src/PocoNotificationCenterPerformance.cpp
Normal file
101
performance/src/PocoNotificationCenterPerformance.cpp
Normal 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user