diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index e81d035..f287bcb 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/checkout@v3 - run: sudo apt update - run: sudo apt install build-essential cmake ninja-build - - run: sudo apt install libjsoncpp-dev libgflags-dev libgtest-dev libgoogle-glog-dev libunwind-dev + - run: sudo apt install libjsoncpp-dev libgflags-dev libgoogle-glog-dev libunwind-dev - name: Setup Ninja uses: ashutoshvarma/setup-ninja@master diff --git a/CMakeLists.txt b/CMakeLists.txt index 28f48d1..04df54e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(myframe) +project(myframe VERSION 0.8.1) ### gcc version if (CMAKE_COMPILER_IS_GNUCC) @@ -40,7 +40,6 @@ set(MYFRAME_CONF_DIR "conf") ### deps libs find_package(jsoncpp REQUIRED) find_package(gflags REQUIRED) -find_package(GTest REQUIRED) link_libraries( pthread dl rt m @@ -78,26 +77,52 @@ install(DIRECTORY tools DESTINATION .) install(DIRECTORY conf DESTINATION .) install(DIRECTORY DESTINATION ${MYFRAME_LOG_DIR}) install(DIRECTORY DESTINATION ${MYFRAME_SERVICE_DIR}) -execute_process( - COMMAND git rev-parse --abbrev-ref HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_BRANCH - OUTPUT_STRIP_TRAILING_WHITESPACE -) -execute_process( - COMMAND git rev-parse HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT_ID - OUTPUT_STRIP_TRAILING_WHITESPACE -) -execute_process( - COMMAND git show -s --format=%ci HEAD - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE GIT_COMMIT_DATE - OUTPUT_STRIP_TRAILING_WHITESPACE -) install(CODE " file( WRITE ${CMAKE_INSTALL_PREFIX}/version.txt - \"${GIT_BRANCH}\n${GIT_COMMIT_ID}\n${GIT_COMMIT_DATE}\n\") + \"${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}\" + ) ") + +### package +include(InstallRequiredSystemLibraries) +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +set(CPACK_PACKAGE_VERSION_MAJOR "${${PROJECT_NAME}_VERSION_MAJOR}") +set(CPACK_PACKAGE_VERSION_MINOR "${${PROJECT_NAME}_VERSION_MINOR}") +set(CPACK_PACKAGE_VERSION_PATCH "${${PROJECT_NAME}_VERSION_PATCH}") +include(CPack) + +### export cmake file +install(EXPORT "${PROJECT_NAME}Targets" + FILE "${PROJECT_NAME}Targets.cmake" + DESTINATION lib/cmake/${PROJECT_NAME} +) + +include(CMakePackageConfigHelpers) +# generate the config file that is includes the exports +configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "lib/cmake/${PROJECT_NAME}" + NO_SET_AND_CHECK_MACRO + NO_CHECK_REQUIRED_COMPONENTS_MACRO +) + +# generate the version file for the config file +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + VERSION "${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}" + COMPATIBILITY AnyNewerVersion +) + +# install the configuration file +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION lib/cmake/${PROJECT_NAME} +) + +# generate the export targets for the build tree +# needs to be after the install(TARGETS ) command +export(EXPORT "${PROJECT_NAME}Targets" + FILE "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake" +) diff --git a/Config.cmake.in b/Config.cmake.in new file mode 100644 index 0000000..ac260c0 --- /dev/null +++ b/Config.cmake.in @@ -0,0 +1,4 @@ + +@PACKAGE_INIT@ + +include ( "${CMAKE_CURRENT_LIST_DIR}/myframeTargets.cmake" ) diff --git a/LICENSE b/LICENSE index efd643f..d9876b9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2018 李柯鹏 +Copyright (c) 2019 李柯鹏 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/doc/version_release.md b/doc/version_release.md new file mode 100644 index 0000000..2f95042 --- /dev/null +++ b/doc/version_release.md @@ -0,0 +1,6 @@ +# 版本发布 +* 修改CMakeLists.txt中版本号 +* 提交修改 +* 合入master +* 生成版本tag并发布 + * 发布tag中详细描述版本更新内容 diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 02af264..5f2bb28 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -9,6 +9,8 @@ add_library(example_actor_serial SHARED example_actor_serial.cpp) target_link_libraries(example_actor_serial ${PROJECT_NAME}) add_library(example_actor_concurrent SHARED example_actor_concurrent.cpp) target_link_libraries(example_actor_concurrent ${PROJECT_NAME}) +add_library(example_actor_subscribe SHARED example_actor_subscribe.cpp) +target_link_libraries(example_actor_subscribe ${PROJECT_NAME}) ### worker add_library(example_worker_publish SHARED example_worker_publish.cpp) @@ -39,6 +41,7 @@ INSTALL(TARGETS example_actor_timer example_actor_serial example_actor_concurrent + example_actor_subscribe example_worker_actor_interactive example_worker_publish example_worker_talk diff --git a/examples/example_actor_subscribe.cpp b/examples/example_actor_subscribe.cpp new file mode 100644 index 0000000..9bd3d64 --- /dev/null +++ b/examples/example_actor_subscribe.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ +#include +#include +#include +#include + +#include + +#include "myframe/msg.h" +#include "myframe/actor.h" + +class ExampleActorPub : public myframe::Actor { + public: + int Init(const char* param) override { + (void)param; + Timeout("1000ms", 100); + return 0; + } + + void Proc(const std::shared_ptr& msg) override { + if (msg->GetType() == "SUBSCRIBE") { + pub_list_.push_back(msg->GetSrc()); + return; + } + if (msg->GetType() == "TIMER") { + auto mailbox = GetMailbox(); + for (size_t i = 0; i < pub_list_.size(); ++i) { + mailbox->Send(pub_list_[i], + std::make_shared("pub msg")); + } + Timeout("1000ms", 100); + } + } + private: + std::vector pub_list_; +}; + +class ExampleActorSub : public myframe::Actor { + public: + int Init(const char* param) override { + (void)param; + Subscribe("actor.example_b_pub.#1"); + return 0; + } + + void Proc(const std::shared_ptr& msg) override { + LOG(INFO) << "-----> get pub msg: " << *msg; + } +}; + +extern "C" std::shared_ptr actor_create( + const std::string& actor_name) { + if (actor_name == "example_b_pub") { + return std::make_shared(); + } + if (actor_name == "example_a_sub") { + return std::make_shared(); + } + return nullptr; +} diff --git a/examples/example_actor_subscribe.json b/examples/example_actor_subscribe.json new file mode 100644 index 0000000..8e11087 --- /dev/null +++ b/examples/example_actor_subscribe.json @@ -0,0 +1,18 @@ +{ + "type":"library", + "lib":"libexample_actor_subscribe.so", + "actor":{ + "example_b_pub":[ + { + "instance_name":"#1", + "instance_params":"" + } + ], + "example_a_sub":[ + { + "instance_name":"#1", + "instance_params":"" + } + ] + } +} diff --git a/myframe/CMakeLists.txt b/myframe/CMakeLists.txt index aecfc05..5bb041c 100644 --- a/myframe/CMakeLists.txt +++ b/myframe/CMakeLists.txt @@ -5,6 +5,11 @@ aux_source_directory(. __srcs) ### lib add_library(${PROJECT_NAME} SHARED ${__srcs}) +target_include_directories(${PROJECT_NAME} + INTERFACE + $ + $ +) ### install file(GLOB header_files @@ -26,7 +31,6 @@ install(FILES DESTINATION ${MYFRAME_INC_DIR}/${PROJECT_NAME} ) install(TARGETS ${PROJECT_NAME} - LIBRARY DESTINATION ${MYFRAME_LIB_DIR} - ARCHIVE DESTINATION ${MYFRAME_LIB_DIR} - RUNTIME DESTINATION ${MYFRAME_BIN_DIR} + DESTINATION lib + EXPORT "${PROJECT_NAME}Targets" ) diff --git a/myframe/actor.cpp b/myframe/actor.cpp index 2f001b9..4fc934c 100644 --- a/myframe/actor.cpp +++ b/myframe/actor.cpp @@ -12,6 +12,7 @@ Author: likepeng #include "myframe/app.h" #include "myframe/actor_context.h" #include "myframe/worker_timer.h" +#include "myframe/mailbox.h" namespace myframe { @@ -71,6 +72,21 @@ int Actor::Timeout(const std::string& timer_name, int expired) { return timer_worker->SetTimeout(GetActorName(), timer_name, expired); } +bool Actor::Subscribe(const std::string& name) { + auto ctx = ctx_.lock(); + if (ctx == nullptr) { + return false; + } + if (name == GetActorName()) { + return false; + } + auto msg = std::make_shared(); + msg->SetType("SUBSCRIBE"); + auto mailbox = ctx->GetMailbox(); + mailbox->Send(name, msg); + return true; +} + void Actor::SetContext(std::shared_ptr c) { ctx_ = c; } const Json::Value* Actor::GetConfig() const { diff --git a/myframe/actor.h b/myframe/actor.h index de675c3..34443ad 100644 --- a/myframe/actor.h +++ b/myframe/actor.h @@ -85,6 +85,17 @@ class Actor { */ int Timeout(const std::string& timer_name, int expired); + /** + * Subscribe() - 订阅actor或者worker的消息 + * @name: 订阅actor或者worker的名称 + * + * 被订阅的组件需要处理订阅消息,消息格式: + * msg->GetType() == "SUBSCRIBE" 确认是订阅消息 + * msg->GetSrc() 确定是订阅组件名称 + * @return: 成功返回true,失败返回false + */ + bool Subscribe(const std::string& name); + /** * GetApp() - 获得应用实例 * diff --git a/myframe/app.cpp b/myframe/app.cpp index c732a74..f60d668 100644 --- a/myframe/app.cpp +++ b/myframe/app.cpp @@ -355,12 +355,34 @@ bool App::CreateActorContext( bool App::CreateActorContext( std::shared_ptr mod_inst, const std::string& params) { + auto actor_name = mod_inst->GetActorName(); auto ctx = std::make_shared(shared_from_this(), mod_inst); if (ctx->Init(params.c_str())) { - LOG(ERROR) << "init " << mod_inst->GetActorName() << " fail"; + LOG(ERROR) << "init " << actor_name << " fail"; return false; } actor_ctx_mgr_->RegContext(ctx); + // 接收缓存中发给自己的消息 + if (cache_msg_.find(actor_name) != cache_msg_.end()) { + auto& cache_list = cache_msg_[actor_name]; + LOG(INFO) << actor_name + << " recv msg from cache, size " << cache_list.size(); + DispatchMsg(&cache_list); + cache_msg_.erase(actor_name); + } + // 目的地址不存在的暂时放到缓存消息队列 + auto send_list = ctx->GetMailbox()->GetSendList(); + for (auto it = send_list->begin(); it != send_list->end();) { + if (!HasUserInst((*it)->GetDst())) { + LOG(WARNING) << "can't found " << (*it)->GetDst() + << ", cache this msg"; + cache_msg_[(*it)->GetDst()].push_back(*it); + it = send_list->erase(it); + continue; + } + ++it; + } + // 分发目的地址已经存在的消息 DispatchMsg(ctx); return true; } @@ -710,4 +732,19 @@ void App::Quit() { worker_ctx_mgr_->StopAllWorker(); } +bool App::HasUserInst(const std::string& name) { + if (name.substr(0, 6) == "worker") { + auto worker_ctx = ev_mgr_->Get(name); + if (worker_ctx != nullptr + && worker_ctx->GetType() == Event::Type::kWorkerUser) { + return true; + } + } else if (name.substr(0, 5) == "actor") { + if (actor_ctx_mgr_->HasActor(name)) { + return true; + } + } + return false; +} + } // namespace myframe diff --git a/myframe/app.h b/myframe/app.h index 33be462..b59a5a2 100644 --- a/myframe/app.h +++ b/myframe/app.h @@ -92,6 +92,7 @@ class App final : public std::enable_shared_from_this { std::shared_ptr inst, const std::string& params); + bool HasUserInst(const std::string& name); std::shared_ptr GetTimerWorker(); bool LoadActors( @@ -128,6 +129,10 @@ class App final : public std::enable_shared_from_this { std::atomic_bool quit_{true}; std::mutex dispatch_mtx_; std::mutex local_mtx_; + /// 缓存消息列表 + std::unordered_map< + std::string, + std::list>> cache_msg_; /// poller std::unique_ptr poller_; /// 模块管理对象 diff --git a/myframe/event_conn_manager.cpp b/myframe/event_conn_manager.cpp index 633d96c..1110953 100644 --- a/myframe/event_conn_manager.cpp +++ b/myframe/event_conn_manager.cpp @@ -70,9 +70,11 @@ void EventConnManager::Notify( std::shared_ptr ev = nullptr; ev = ev_mgr_->Get(h); if (ev == nullptr) { + LOG(ERROR) << "can't find handle " << h; return; } if (ev->GetConnType() == EventConn::Type::kSend) { + LOG(WARNING) << "event " << ev->GetName() << " need't resp msg"; return; } // push msg to event_conn diff --git a/myframe/event_manager.cpp b/myframe/event_manager.cpp index 63b2fa3..c4adc54 100644 --- a/myframe/event_manager.cpp +++ b/myframe/event_manager.cpp @@ -9,8 +9,8 @@ Author: likepeng #include -#include -#include +#include "myframe/worker.h" +#include "myframe/event_conn.h" namespace myframe { diff --git a/templates/CMakeLists.txt b/templates/CMakeLists.txt index c690e6f..6d40406 100644 --- a/templates/CMakeLists.txt +++ b/templates/CMakeLists.txt @@ -14,7 +14,6 @@ SET(MYFRAME_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/lib) #### dep 3rd lib FIND_PACKAGE(jsoncpp REQUIRED) FIND_PACKAGE(gflags REQUIRED) -FIND_PACKAGE(GTest REQUIRED) #### include directory INCLUDE_DIRECTORIES(${CMAKE_INSTALL_PREFIX}/include) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index a74992d..a6f4492 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -3,16 +3,46 @@ cmake_minimum_required(VERSION 3.10) ### configure file configure_file(${CMAKE_CURRENT_SOURCE_DIR}/performance_test_config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/performance_test_config.h @ONLY) -AUX_SOURCE_DIRECTORY(. TEST_SRCS) -ADD_EXECUTABLE(myframe_test ${TEST_SRCS}) -target_link_libraries(myframe_test - GTest::GTest - GTest::Main +### test bin +add_executable(app_send_test app_send_test.cpp) +target_link_libraries(app_send_test myframe ) -INSTALL(TARGETS myframe_test +add_executable(performance_trans1_cost_test performance_trans1_cost_test.cpp) +target_link_libraries(performance_trans1_cost_test + myframe +) + +add_executable(performance_trans10_cost_test performance_trans10_cost_test.cpp) +target_link_libraries(performance_trans10_cost_test + myframe +) + +add_executable(performance_trans1_fullspeed_test performance_trans1_fullspeed_test.cpp) +target_link_libraries(performance_trans1_fullspeed_test + myframe +) + +add_executable(performance_trans20_fullspeed_test performance_trans20_fullspeed_test.cpp) +target_link_libraries(performance_trans20_fullspeed_test + myframe +) + +add_executable(performance_trans100_fullspeed_test performance_trans100_fullspeed_test.cpp) +target_link_libraries(performance_trans100_fullspeed_test + myframe +) + +### install +INSTALL(TARGETS + app_send_test + performance_trans1_cost_test + performance_trans10_cost_test + performance_trans1_fullspeed_test + performance_trans20_fullspeed_test + performance_trans100_fullspeed_test LIBRARY DESTINATION ${MYFRAME_LIB_DIR} ARCHIVE DESTINATION ${MYFRAME_LIB_DIR} RUNTIME DESTINATION ${MYFRAME_TEST_DIR} -) \ No newline at end of file +) diff --git a/test/app_send_test.cpp b/test/app_send_test.cpp new file mode 100644 index 0000000..f6c5bf7 --- /dev/null +++ b/test/app_send_test.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "myframe/common.h" +#include "myframe/log.h" +#include "myframe/msg.h" +#include "myframe/actor.h" +#include "myframe/mod_manager.h" +#include "myframe/app.h" + +#include "performance_test_config.h" + +class EchoActorTest : public myframe::Actor { + public: + int Init(const char* param) override { + (void)param; + LOG(INFO) << "init EchoActorTest"; + return 0; + } + + void Proc(const std::shared_ptr& msg) override { + LOG(INFO) << "recv " << msg->GetSrc() << ":" << msg->GetData(); + if (msg->GetData() == "hello") { + auto re = std::make_shared( + "resp:" + std::to_string(seq_++)); + auto mailbox = GetMailbox(); + mailbox->Send(msg->GetSrc(), re); + } + } + + private: + int seq_{0}; +}; + +int main() { + auto lib_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LIB_DIR); + auto log_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LOG_DIR); + + myframe::InitLog(log_dir, "app_send_test"); + + auto app = std::make_shared(); + if (false == app->Init(lib_dir, 4)) { + LOG(ERROR) << "Init failed"; + return -1; + } + + // mod manager + auto& mod = app->GetModManager(); + + // 注册echo Actor + mod->RegActor("EchoActorTest", [](const std::string&) { + return std::make_shared(); + }); + auto actor = mod->CreateActorInst("class", "EchoActorTest"); + app->AddActor("1", "", actor); + + // 创建一个线程请求服务 + std::thread th([&]() { + int cnt = 100; + while (cnt--) { + auto resp = app->SendRequest( + "actor.EchoActorTest.1", + std::make_shared("hello")); + LOG(INFO) << "get resp: " << resp->GetData(); + app->Send( + "actor.EchoActorTest.1", + std::make_shared("world")); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + } + app->Quit(); + }); + + app->Exec(); + th.join(); + return 0; +} diff --git a/test/main.cpp b/test/main.cpp deleted file mode 100644 index adef69d..0000000 --- a/test/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -/**************************************************************************** -Copyright (c) 2018, likepeng -All rights reserved. - -Author: likepeng -****************************************************************************/ - -#include - -class Environment : public testing::Environment { - public: - void SetUp() override { std::cout << "Environment SetUP" << std::endl; } - - void TearDown() override { std::cout << "Environment TearDown" << std::endl; } -}; - -int main(int argc, char** argv) { - testing::AddGlobalTestEnvironment(new Environment); - testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/test/performance_test.cpp b/test/performance_test.cpp deleted file mode 100644 index 0a16d0b..0000000 --- a/test/performance_test.cpp +++ /dev/null @@ -1,395 +0,0 @@ -/**************************************************************************** -Copyright (c) 2018, likepeng -All rights reserved. - -Author: likepeng -****************************************************************************/ -#include -#include -#include - -#include -#include - -#include "myframe/common.h" -#include "myframe/actor.h" -#include "myframe/app.h" -#include "myframe/log.h" -#include "myframe/mod_manager.h" -#include "myframe/msg.h" -#include "performance_test_config.h" - -class EchoActorTest : public myframe::Actor { - public: - int Init(const char* param) override { - (void)param; - LOG(INFO) << "init EchoActorTest"; - return 0; - } - - void Proc(const std::shared_ptr& msg) override { - LOG(INFO) << "recv " << msg->GetSrc() << ":" << msg->GetData(); - auto re = std::make_shared("resp:" + std::to_string(seq_++)); - auto mailbox = GetMailbox(); - mailbox->Send(msg->GetSrc(), re); - } - - private: - int seq_{0}; -}; - -class TransMsgCostTest : public myframe::Actor { - public: - TransMsgCostTest() : msg_(8192, 'x') {} - - int Init(const char* param) override { - (void)param; - LOG(INFO) << "begin runing TransMsgCostTest"; - last_ = std::chrono::high_resolution_clock::now(); - begin_ = std::chrono::high_resolution_clock::now(); - auto mailbox = GetMailbox(); - mailbox->Send(GetActorName(), std::make_shared(msg_)); - return 0; - } - - void Proc(const std::shared_ptr& msg) override { - (void)msg; - auto now = std::chrono::high_resolution_clock::now(); - auto us = std::chrono::duration_cast(now - last_) - .count(); - LOG(INFO) << GetActorName() << " trans msg cost(us) " << us; - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - last_ = std::chrono::high_resolution_clock::now(); - - auto sec = std::chrono::duration_cast(last_ - begin_) - .count(); - if (sec < 60) { - auto mailbox = GetMailbox(); - mailbox->Send(GetActorName(), std::make_shared(msg_)); - } else { - LOG(INFO) << "runing next test..."; - auto mailbox = GetMailbox(); - mailbox->Send("actor.Trans10ActorCostTest.0", - std::make_shared(msg_)); - } - } - - private: - std::chrono::high_resolution_clock::time_point begin_; - std::chrono::high_resolution_clock::time_point last_; - std::string msg_; -}; - -class Trans10ActorCostTest : public myframe::Actor { - public: - Trans10ActorCostTest() : msg_(8192, 'y') {} - - int Init(const char* param) override { - task_num_ = std::stoi(param); - LOG(INFO) << "init trans msg num " << task_num_; - return 0; - } - - void Proc(const std::shared_ptr& msg) override { - (void)msg; - if (!init_) { - init_ = true; - total_ = std::chrono::high_resolution_clock::now(); - } - if (task_num_ == 0) { - begin_ = std::chrono::high_resolution_clock::now(); - } - if (task_num_ == 9) { - auto now = std::chrono::high_resolution_clock::now(); - auto us = - std::chrono::duration_cast(now - begin_) - .count(); - LOG(INFO) << GetActorName() << " trans 10 actor msg cost(us) " << us; - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - begin_ = std::chrono::high_resolution_clock::now(); - } - auto sec = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - total_) - .count(); - std::string next_actor_name = - "actor.Trans10ActorCostTest." + std::to_string((task_num_ + 1) % 10); - if (sec < 60) { - auto mailbox = GetMailbox(); - mailbox->Send(next_actor_name, std::make_shared(msg_)); - } else { - LOG(INFO) << "runing next test..."; - auto mailbox = GetMailbox(); - mailbox->Send("actor.FullSpeedTransTest.0", - std::make_shared(msg_)); - } - } - - private: - static bool init_; - static std::chrono::high_resolution_clock::time_point total_; - static std::chrono::high_resolution_clock::time_point begin_; - int task_num_{0}; - std::string msg_; -}; -bool Trans10ActorCostTest::init_{false}; -std::chrono::high_resolution_clock::time_point Trans10ActorCostTest::total_; -std::chrono::high_resolution_clock::time_point Trans10ActorCostTest::begin_; - -class FullSpeedTransTest : public myframe::Actor { - public: - FullSpeedTransTest() : msg_(8192, 'z') {} - - int Init(const char* param) override { - (void)param; - LOG(INFO) << "init full speed trans "; - return 0; - } - - void Proc(const std::shared_ptr& msg) override { - (void)msg; - if (!init_) { - init_ = true; - begin_ = std::chrono::high_resolution_clock::now(); - last_ = std::chrono::high_resolution_clock::now(); - } - auto now = std::chrono::high_resolution_clock::now(); - auto us = std::chrono::duration_cast(now - last_) - .count(); - cnt_++; - if (us / 1000.0 > 1000.0) { - LOG(INFO) << GetActorName() << ": full speed msg count " << cnt_; - cnt_ = 0; - last_ = std::chrono::high_resolution_clock::now(); - } - auto sec = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - begin_) - .count(); - if (sec < 60) { - auto mailbox = GetMailbox(); - mailbox->Send(GetActorName(), std::make_shared()); - } else { - LOG(INFO) << "runing next test..."; - for (int i = 0; i < 20; ++i) { - std::string name = - "actor.FullSpeed20ActorTransTest." + std::to_string(i); - auto mailbox = GetMailbox(); - mailbox->Send(name, std::make_shared(msg_)); - } - } - } - - private: - bool init_{false}; - int cnt_{0}; - std::chrono::high_resolution_clock::time_point begin_; - std::chrono::high_resolution_clock::time_point last_; - std::string msg_; -}; - -class FullSpeed20ActorTransTest : public myframe::Actor { - public: - FullSpeed20ActorTransTest() : msg_(8192, 'j') {} - - int Init(const char* param) override { - (void)param; - LOG(INFO) << "init full speed 20 actor trans "; - return 0; - } - - void Proc(const std::shared_ptr& msg) override { - (void)msg; - if (!init_) { - init_ = true; - begin_ = std::chrono::high_resolution_clock::now(); - last_ = std::chrono::high_resolution_clock::now(); - } - auto now = std::chrono::high_resolution_clock::now(); - auto us = std::chrono::duration_cast(now - last_) - .count(); - cnt_++; - if (us / 1000.0 > 1000.0) { - LOG(INFO) << GetActorName() << ": full speed 20 actor msg count " << cnt_; - cnt_ = 0; - last_ = std::chrono::high_resolution_clock::now(); - } - auto sec = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - begin_) - .count(); - if (sec < 60) { - auto mailbox = GetMailbox(); - mailbox->Send(GetActorName(), std::make_shared()); - } else { - if (!is_send_) { - is_send_ = true; - LOG(INFO) << "runing next test..."; - for (int i = 0; i < 100; ++i) { - std::string name = - "actor.FullSpeed100ActorTransTest." + std::to_string(i); - auto mailbox = GetMailbox(); - mailbox->Send(name, std::make_shared(msg_)); - } - } - } - } - - private: - static std::atomic_bool is_send_; - bool init_{false}; - int cnt_{0}; - std::chrono::high_resolution_clock::time_point begin_; - std::chrono::high_resolution_clock::time_point last_; - std::string msg_; -}; -std::atomic_bool FullSpeed20ActorTransTest::is_send_{false}; - -class FullSpeed100ActorTransTest : public myframe::Actor { - public: - FullSpeed100ActorTransTest() : msg_(8192, 'k') {} - - int Init(const char* param) override { - (void)param; - LOG(INFO) << "init full speed 100 actor trans "; - return 0; - } - - void Proc(const std::shared_ptr& msg) override { - (void)msg; - if (!init_) { - init_ = true; - begin_ = std::chrono::high_resolution_clock::now(); - last_ = std::chrono::high_resolution_clock::now(); - } - auto now = std::chrono::high_resolution_clock::now(); - auto us = std::chrono::duration_cast(now - last_) - .count(); - cnt_++; - if (us / 1000.0 > 1000.0) { - LOG(INFO) << GetActorName() << ": full speed 100 actor msg count " - << cnt_; - cnt_ = 0; - last_ = std::chrono::high_resolution_clock::now(); - } - auto sec = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now() - begin_) - .count(); - if (sec < 60) { - auto mailbox = GetMailbox(); - mailbox->Send(GetActorName(), std::make_shared()); - } - } - - private: - bool init_{false}; - int cnt_{0}; - std::chrono::high_resolution_clock::time_point begin_; - std::chrono::high_resolution_clock::time_point last_; - std::string msg_; -}; - -TEST(App, performance_test) { - auto lib_dir = - myframe::Common::GetAbsolutePath(MYFRAME_LIB_DIR); - auto log_dir = - myframe::Common::GetAbsolutePath(MYFRAME_LOG_DIR); - - myframe::InitLog(log_dir, "myframe_test"); - - auto app = std::make_shared(); - if (false == app->Init(lib_dir, 4)) { - LOG(ERROR) << "Init failed"; - return; - } - - // mod manager - auto& mod = app->GetModManager(); - - // 注册echo Actor - { - mod->RegActor("EchoActorTest", [](const std::string&) { - return std::make_shared(); - }); - auto actor = mod->CreateActorInst("class", "EchoActorTest"); - app->AddActor("1", "", actor); - } - - // 发送单条消息耗时(测试时长1分钟,每隔10毫秒发送1条消息) - // 耗时 - // 平均值: - // 99分位: - { - mod->RegActor("TransMsgCostTest", [](const std::string&) { - return std::make_shared(); - }); - auto actor = mod->CreateActorInst("class", "TransMsgCostTest"); - app->AddActor("#1", "", actor); - } - - // 消息流转10个actor耗时(测试时长1分钟,每隔10毫秒发送1条消息) - // 耗时 - // 平均值: - // 99分位: - { - mod->RegActor("Trans10ActorCostTest", [](const std::string&) { - return std::make_shared(); - }); - for (int i = 0; i < 10; ++i) { - auto actor = mod->CreateActorInst("class", "Trans10ActorCostTest"); - app->AddActor(std::to_string(i), std::to_string(i), actor); - } - } - - // 1个actor消息吞吐量(测试时长1分钟,全速运行) - // 消息个数: - // 消息大小: - { - mod->RegActor("FullSpeedTransTest", [](const std::string&) { - return std::make_shared(); - }); - auto actor = mod->CreateActorInst("class", "FullSpeedTransTest"); - app->AddActor("0", std::to_string(0), actor); - } - - // 20个actor消息吞吐量(测试时长1分钟,全速运行) - // 消息个数: - // 消息大小: - { - mod->RegActor("FullSpeed20ActorTransTest", [](const std::string&) { - return std::make_shared(); - }); - for (int i = 0; i < 20; ++i) { - auto actor = mod->CreateActorInst("class", "FullSpeed20ActorTransTest"); - app->AddActor(std::to_string(i), std::to_string(i), actor); - } - } - - // 100个actor消息吞吐量(测试时长1分钟,全速运行) - // 消息个数: - // 消息大小: - { - mod->RegActor("FullSpeed100ActorTransTest", [](const std::string&) { - return std::make_shared(); - }); - for (int i = 0; i < 100; ++i) { - auto actor = mod->CreateActorInst("class", "FullSpeed100ActorTransTest"); - app->AddActor(std::to_string(i), std::to_string(i), actor); - } - } - - // 创建一个线程请求服务 - std::thread th([&]() { - int cnt = 100; - while (cnt--) { - auto resp = app->SendRequest( - "actor.EchoActorTest.1", - std::make_shared("hello")); - LOG(INFO) << "get resp: " << resp->GetData(); - app->Send( - "actor.EchoActorTest.1", - std::make_shared("world")); - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - }); - - LOG(INFO) << "begin testing..."; - app->Exec(); -} diff --git a/test/performance_trans100_fullspeed_test.cpp b/test/performance_trans100_fullspeed_test.cpp new file mode 100644 index 0000000..53d9d1a --- /dev/null +++ b/test/performance_trans100_fullspeed_test.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "myframe/common.h" +#include "myframe/log.h" +#include "myframe/msg.h" +#include "myframe/actor.h" +#include "myframe/mod_manager.h" +#include "myframe/app.h" + +#include "performance_test_config.h" + +class FullSpeed100ActorTransTest : public myframe::Actor { + public: + FullSpeed100ActorTransTest() : msg_(8192, 'k') {} + + int Init(const char* param) override { + (void)param; + LOG(INFO) << "init full speed 100 actor trans "; + // 启动测试 + msg_cnt_per_sec_list_.reserve(64); + auto mailbox = GetMailbox(); + mailbox->Send(GetActorName(), std::make_shared(msg_)); + return 0; + } + + void Proc(const std::shared_ptr& msg) override { + (void)msg; + if (!init_) { + init_ = true; + begin_ = std::chrono::high_resolution_clock::now(); + last_ = std::chrono::high_resolution_clock::now(); + } + auto now = std::chrono::high_resolution_clock::now(); + auto us = std::chrono::duration_cast(now - last_) + .count(); + cnt_++; + if (us / 1000.0 > 1000.0) { + LOG(INFO) << GetActorName() << ": full speed 100 actor msg count " + << cnt_; + msg_cnt_per_sec_list_.push_back(cnt_); + cnt_ = 0; + last_ = std::chrono::high_resolution_clock::now(); + } + auto sec = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - begin_) + .count(); + if (sec < 60) { + auto mailbox = GetMailbox(); + mailbox->Send(GetActorName(), std::make_shared()); + } else { + if (!is_send_) { + is_send_.store(true); + LOG(INFO) << "runing FullSpeed100ActorTransTest end"; + int sum = std::accumulate(msg_cnt_per_sec_list_.begin(), + msg_cnt_per_sec_list_.end(), 0); + int avg = sum / msg_cnt_per_sec_list_.size(); + LOG(INFO) << "100 actor fullspeed trans msg avg(cnt/sec): " << avg; + std::sort(msg_cnt_per_sec_list_.begin(), msg_cnt_per_sec_list_.end()); + LOG(INFO) << "100 actor fullspeed trans msg 99(cnt/sec): " + << msg_cnt_per_sec_list_[msg_cnt_per_sec_list_.size() * 0.99]; + GetApp()->Quit(); + } + } + } + + private: + static std::atomic_bool is_send_; + bool init_{false}; + int cnt_{0}; + std::chrono::high_resolution_clock::time_point begin_; + std::chrono::high_resolution_clock::time_point last_; + std::string msg_; + std::vector msg_cnt_per_sec_list_; +}; +std::atomic_bool FullSpeed100ActorTransTest::is_send_{false}; + +int main() { + auto lib_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LIB_DIR); + auto log_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LOG_DIR); + + myframe::InitLog(log_dir, "performance_trans100_fullspeed_test"); + + auto app = std::make_shared(); + if (false == app->Init(lib_dir, 4)) { + LOG(ERROR) << "Init failed"; + return -1; + } + + // mod manager + auto& mod = app->GetModManager(); + + // 100个actor消息吞吐量(测试时长1分钟,全速运行) + mod->RegActor("FullSpeed100ActorTransTest", [](const std::string&) { + return std::make_shared(); + }); + for (int i = 0; i < 100; ++i) { + auto actor = mod->CreateActorInst("class", "FullSpeed100ActorTransTest"); + app->AddActor(std::to_string(i), std::to_string(i), actor); + } + + LOG(INFO) << "FullSpeed100ActorTransTest begin..."; + return app->Exec(); +} diff --git a/test/performance_trans10_cost_test.cpp b/test/performance_trans10_cost_test.cpp new file mode 100644 index 0000000..516ae9c --- /dev/null +++ b/test/performance_trans10_cost_test.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "myframe/common.h" +#include "myframe/log.h" +#include "myframe/msg.h" +#include "myframe/actor.h" +#include "myframe/mod_manager.h" +#include "myframe/app.h" + +#include "performance_test_config.h" + + +class Trans10ActorCostTest : public myframe::Actor { + public: + Trans10ActorCostTest() : msg_(8192, 'y') {} + + int Init(const char* param) override { + task_num_ = std::stoi(param); + // 启动测试 + if (task_num_ == 0) { + cost_us_list_.reserve(6000); + auto mailbox = GetMailbox(); + mailbox->Send("actor.Trans10ActorCostTest.0", + std::make_shared(msg_)); + } + LOG(INFO) << "init trans msg num " << task_num_; + return 0; + } + + void Proc(const std::shared_ptr& msg) override { + (void)msg; + if (!init_) { + init_ = true; + total_ = std::chrono::high_resolution_clock::now(); + } + if (task_num_ == 0) { + begin_ = std::chrono::high_resolution_clock::now(); + } + if (task_num_ == 9) { + auto now = std::chrono::high_resolution_clock::now(); + auto us = + std::chrono::duration_cast(now - begin_) + .count(); + LOG(INFO) << GetActorName() << " trans 10 actor msg cost(us) " << us; + cost_us_list_.push_back(us); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + begin_ = std::chrono::high_resolution_clock::now(); + } + auto sec = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - total_) + .count(); + std::string next_actor_name = + "actor.Trans10ActorCostTest." + std::to_string((task_num_ + 1) % 10); + if (sec < 60) { + auto mailbox = GetMailbox(); + mailbox->Send(next_actor_name, std::make_shared(msg_)); + } else { + LOG(INFO) << "runing Trans10ActorCostTest end"; + // 耗时 + // 平均值: + // 99分位: + int sum = std::accumulate(cost_us_list_.begin(), cost_us_list_.end(), 0); + int avg = sum / cost_us_list_.size(); + LOG(INFO) << "trans 10 actor cnt: " << cost_us_list_.size(); + LOG(INFO) << "trans 10 actor avg(us): " << avg; + std::sort(cost_us_list_.begin(), cost_us_list_.end()); + LOG(INFO) << "trans 10 actor 99(us): " << + cost_us_list_[cost_us_list_.size() * 0.99]; + GetApp()->Quit(); + } + } + + private: + static bool init_; + static std::chrono::high_resolution_clock::time_point total_; + static std::chrono::high_resolution_clock::time_point begin_; + static std::vector cost_us_list_; + int task_num_{0}; + std::string msg_; +}; +bool Trans10ActorCostTest::init_{false}; +std::chrono::high_resolution_clock::time_point Trans10ActorCostTest::total_; +std::chrono::high_resolution_clock::time_point Trans10ActorCostTest::begin_; +std::vector Trans10ActorCostTest::cost_us_list_; + + +int main() { + auto lib_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LIB_DIR); + auto log_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LOG_DIR); + + myframe::InitLog(log_dir, "performance_trans10_cost_test"); + + auto app = std::make_shared(); + if (false == app->Init(lib_dir, 4)) { + LOG(ERROR) << "Init failed"; + return -1; + } + + // mod manager + auto& mod = app->GetModManager(); + + // 消息流转10个actor耗时(测试时长1分钟,每隔10毫秒发送1条消息) + // 耗时 + // 平均值: + // 99分位: + mod->RegActor("Trans10ActorCostTest", [](const std::string&) { + return std::make_shared(); + }); + for (int i = 0; i < 10; ++i) { + auto actor = mod->CreateActorInst("class", "Trans10ActorCostTest"); + app->AddActor(std::to_string(i), std::to_string(i), actor); + } + + return app->Exec(); +} diff --git a/test/performance_trans1_cost_test.cpp b/test/performance_trans1_cost_test.cpp new file mode 100644 index 0000000..f403ead --- /dev/null +++ b/test/performance_trans1_cost_test.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "myframe/common.h" +#include "myframe/log.h" +#include "myframe/msg.h" +#include "myframe/actor.h" +#include "myframe/mod_manager.h" +#include "myframe/app.h" + +#include "performance_test_config.h" + +class TransMsgCostTest : public myframe::Actor { + public: + TransMsgCostTest() : msg_(8192, 'x') {} + + int Init(const char* param) override { + (void)param; + LOG(INFO) << "runing TransMsgCostTest..."; + cost_us_list_.reserve(6000); + last_ = std::chrono::high_resolution_clock::now(); + begin_ = std::chrono::high_resolution_clock::now(); + auto mailbox = GetMailbox(); + mailbox->Send(GetActorName(), std::make_shared(msg_)); + return 0; + } + + void Proc(const std::shared_ptr& msg) override { + (void)msg; + auto now = std::chrono::high_resolution_clock::now(); + auto us = std::chrono::duration_cast(now - last_) + .count(); + LOG(INFO) << GetActorName() << " trans msg cost(us) " << us; + cost_us_list_.push_back(us); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + last_ = std::chrono::high_resolution_clock::now(); + + auto sec = std::chrono::duration_cast(last_ - begin_) + .count(); + if (sec < 60) { + auto mailbox = GetMailbox(); + mailbox->Send(GetActorName(), std::make_shared(msg_)); + } else { + LOG(INFO) << "runing TransMsgCostTest end"; + // 耗时 + // 平均值: + // 99分位: + int sum = std::accumulate(cost_us_list_.begin(), cost_us_list_.end(), 0); + int avg = sum / cost_us_list_.size(); + LOG(INFO) << "trans 1 actor cnt: " << cost_us_list_.size(); + LOG(INFO) << "trans 1 actor avg(us): " << avg; + std::sort(cost_us_list_.begin(), cost_us_list_.end()); + LOG(INFO) << "trans 1 actor 99(us): " << + cost_us_list_[cost_us_list_.size() * 0.99]; + GetApp()->Quit(); + } + } + + private: + std::chrono::high_resolution_clock::time_point begin_; + std::chrono::high_resolution_clock::time_point last_; + std::string msg_; + std::vector cost_us_list_; +}; + +int main() { + auto lib_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LIB_DIR); + auto log_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LOG_DIR); + + myframe::InitLog(log_dir, "performance_trans1_cost_test"); + + auto app = std::make_shared(); + if (false == app->Init(lib_dir, 4)) { + LOG(ERROR) << "Init failed"; + return -1; + } + + // mod manager + auto& mod = app->GetModManager(); + + // 发送单条消息耗时(测试时长1分钟,每隔10毫秒发送1条消息) + // 耗时 + // 平均值: + // 99分位: + mod->RegActor("TransMsgCostTest", [](const std::string&) { + return std::make_shared(); + }); + auto actor = mod->CreateActorInst("class", "TransMsgCostTest"); + app->AddActor("#1", "", actor); + + return app->Exec(); +} diff --git a/test/performance_trans1_fullspeed_test.cpp b/test/performance_trans1_fullspeed_test.cpp new file mode 100644 index 0000000..bc489ee --- /dev/null +++ b/test/performance_trans1_fullspeed_test.cpp @@ -0,0 +1,107 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "myframe/common.h" +#include "myframe/log.h" +#include "myframe/msg.h" +#include "myframe/actor.h" +#include "myframe/mod_manager.h" +#include "myframe/app.h" + +#include "performance_test_config.h" + +class FullSpeedTransTest : public myframe::Actor { + public: + FullSpeedTransTest() : msg_(8192, 'z') {} + + int Init(const char* param) override { + (void)param; + LOG(INFO) << "init full speed trans "; + // 启动测试 + msg_cnt_per_sec_list_.reserve(64); + auto mailbox = GetMailbox(); + mailbox->Send(GetActorName(), std::make_shared(msg_)); + return 0; + } + + void Proc(const std::shared_ptr& msg) override { + (void)msg; + if (!init_) { + init_ = true; + begin_ = std::chrono::high_resolution_clock::now(); + last_ = std::chrono::high_resolution_clock::now(); + } + auto now = std::chrono::high_resolution_clock::now(); + auto us = std::chrono::duration_cast(now - last_) + .count(); + cnt_++; + if (us / 1000.0 > 1000.0) { + LOG(INFO) << GetActorName() << ": full speed msg count " << cnt_; + msg_cnt_per_sec_list_.push_back(cnt_); + cnt_ = 0; + last_ = std::chrono::high_resolution_clock::now(); + } + auto sec = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - begin_) + .count(); + if (sec < 60) { + auto mailbox = GetMailbox(); + mailbox->Send(GetActorName(), std::make_shared()); + } else { + LOG(INFO) << "runing FullSpeedTransTest end"; + int sum = std::accumulate(msg_cnt_per_sec_list_.begin(), + msg_cnt_per_sec_list_.end(), 0); + int avg = sum / msg_cnt_per_sec_list_.size(); + LOG(INFO) << "1 actor fullspeed trans msg avg(cnt/sec): " << avg; + std::sort(msg_cnt_per_sec_list_.begin(), msg_cnt_per_sec_list_.end()); + LOG(INFO) << "1 actor fullspeed trans msg 99(cnt/sec): " + << msg_cnt_per_sec_list_[msg_cnt_per_sec_list_.size() * 0.99]; + GetApp()->Quit(); + } + } + + private: + bool init_{false}; + int cnt_{0}; + std::chrono::high_resolution_clock::time_point begin_; + std::chrono::high_resolution_clock::time_point last_; + std::string msg_; + std::vector msg_cnt_per_sec_list_; +}; + +int main() { + auto lib_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LIB_DIR); + auto log_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LOG_DIR); + + myframe::InitLog(log_dir, "performance_trans1_fullspeed_test"); + + auto app = std::make_shared(); + if (false == app->Init(lib_dir, 4)) { + LOG(ERROR) << "Init failed"; + return -1; + } + + // mod manager + auto& mod = app->GetModManager(); + + // 1个actor消息吞吐量(测试时长1分钟,全速运行) + mod->RegActor("FullSpeedTransTest", [](const std::string&) { + return std::make_shared(); + }); + auto actor = mod->CreateActorInst("class", "FullSpeedTransTest"); + app->AddActor("0", std::to_string(0), actor); + + return app->Exec(); +} diff --git a/test/performance_trans20_fullspeed_test.cpp b/test/performance_trans20_fullspeed_test.cpp new file mode 100644 index 0000000..f5cf62a --- /dev/null +++ b/test/performance_trans20_fullspeed_test.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +Copyright (c) 2018, likepeng +All rights reserved. + +Author: likepeng +****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include "myframe/common.h" +#include "myframe/log.h" +#include "myframe/msg.h" +#include "myframe/actor.h" +#include "myframe/mod_manager.h" +#include "myframe/app.h" + +#include "performance_test_config.h" + +class FullSpeed20ActorTransTest : public myframe::Actor { + public: + FullSpeed20ActorTransTest() : msg_(8192, 'j') {} + + int Init(const char* param) override { + (void)param; + LOG(INFO) << "init full speed 20 actor trans "; + // 启动测试 + msg_cnt_per_sec_list_.reserve(64); + auto mailbox = GetMailbox(); + mailbox->Send(GetActorName(), std::make_shared(msg_)); + return 0; + } + + void Proc(const std::shared_ptr& msg) override { + (void)msg; + if (!init_) { + init_ = true; + begin_ = std::chrono::high_resolution_clock::now(); + last_ = std::chrono::high_resolution_clock::now(); + } + auto now = std::chrono::high_resolution_clock::now(); + auto us = std::chrono::duration_cast(now - last_) + .count(); + cnt_++; + if (us / 1000.0 > 1000.0) { + LOG(INFO) << GetActorName() << ": full speed 20 actor msg count " << cnt_; + msg_cnt_per_sec_list_.push_back(cnt_); + cnt_ = 0; + last_ = std::chrono::high_resolution_clock::now(); + } + auto sec = std::chrono::duration_cast( + std::chrono::high_resolution_clock::now() - begin_) + .count(); + if (sec < 60) { + auto mailbox = GetMailbox(); + mailbox->Send(GetActorName(), std::make_shared()); + } else { + if (!is_send_) { + is_send_.store(true); + LOG(INFO) << "runing FullSpeed20ActorTransTest end"; + int sum = std::accumulate(msg_cnt_per_sec_list_.begin(), + msg_cnt_per_sec_list_.end(), 0); + int avg = sum / msg_cnt_per_sec_list_.size(); + LOG(INFO) << "20 actor fullspeed trans msg avg(cnt/sec): " << avg; + std::sort(msg_cnt_per_sec_list_.begin(), msg_cnt_per_sec_list_.end()); + LOG(INFO) << "20 actor fullspeed trans msg 99(cnt/sec): " + << msg_cnt_per_sec_list_[msg_cnt_per_sec_list_.size() * 0.99]; + GetApp()->Quit(); + } + } + } + + private: + static std::atomic_bool is_send_; + bool init_{false}; + int cnt_{0}; + std::chrono::high_resolution_clock::time_point begin_; + std::chrono::high_resolution_clock::time_point last_; + std::string msg_; + std::vector msg_cnt_per_sec_list_; +}; +std::atomic_bool FullSpeed20ActorTransTest::is_send_{false}; + +int main() { + auto lib_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LIB_DIR); + auto log_dir = + myframe::Common::GetAbsolutePath(MYFRAME_LOG_DIR); + + myframe::InitLog(log_dir, "performance_trans20_fullspeed_test"); + + auto app = std::make_shared(); + if (false == app->Init(lib_dir, 4)) { + LOG(ERROR) << "Init failed"; + return -1; + } + + // mod manager + auto& mod = app->GetModManager(); + + // 20个actor消息吞吐量(测试时长1分钟,全速运行) + mod->RegActor("FullSpeed20ActorTransTest", [](const std::string&) { + return std::make_shared(); + }); + for (int i = 0; i < 20; ++i) { + auto actor = mod->CreateActorInst("class", "FullSpeed20ActorTransTest"); + app->AddActor(std::to_string(i), std::to_string(i), actor); + } + + LOG(INFO) << "FullSpeed20ActorTransTest begin..."; + return app->Exec(); +}