Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ option(TONLIB_ENABLE_JNI "Use \"ON\" to enable JNI-compatible TonLib API.")
option(TON_USE_ASAN "Use \"ON\" to enable AddressSanitizer." OFF)
option(TON_USE_TSAN "Use \"ON\" to enable ThreadSanitizer." OFF)
option(TON_USE_UBSAN "Use \"ON\" to enable UndefinedBehaviorSanitizer." OFF)
option(TON_USE_COVERAGE "Use \"ON\" to enable code coverage with gcov." OFF)
set(TON_ARCH "native" CACHE STRING "Architecture, will be passed to -march=")

option(TON_PRINT_BACKTRACE_ON_CRASH "Attempt to print a backtrace when a fatal signal is caught" ON)
Expand Down Expand Up @@ -251,7 +252,7 @@ elseif (CLANG OR GCC)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--exclude-libs,ALL")
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
if (NOT TON_USE_ASAN AND NOT TON_USE_TSAN AND NOT MEMPROF)
if (NOT TON_USE_ASAN AND NOT TON_USE_TSAN AND NOT TON_USE_COVERAGE AND NOT MEMPROF)
if (NOT USE_EMSCRIPTEN)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--exclude-libs,ALL")
endif()
Expand Down Expand Up @@ -337,6 +338,18 @@ endif()
if (TON_USE_UBSAN)
add_cxx_compiler_flag("-fsanitize=undefined")
endif()
if (TON_USE_COVERAGE)
add_cxx_compiler_flag("-fprofile-arcs")
add_cxx_compiler_flag("-ftest-coverage")
add_cxx_compiler_flag("--coverage")
add_cxx_compiler_flag("-O0")
add_cxx_compiler_flag("-g")
add_cxx_compiler_flag("-fno-inline")
add_cxx_compiler_flag("-fno-inline-small-functions")
add_cxx_compiler_flag("-fno-default-inline")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage --coverage")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fprofile-arcs -ftest-coverage --coverage")
endif()
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
Expand Down Expand Up @@ -554,6 +567,7 @@ add_test(test-cells test-cells ${TEST_OPTIONS})
add_test(test-smartcont test-smartcont)
add_test(test-net test-net)
add_test(test-actors test-tdactor)
add_test(test-actors-coro tdactor/test/test-coro)
add_test(test-emulator test-emulator)

#BEGIN tonlib
Expand Down
2 changes: 1 addition & 1 deletion assembly/native/build-macos-portable.sh
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ if [ "$with_tests" = true ]; then
lite-client validator-engine-console generate-random-id json2tlo dht-server dht-ping-servers dht-resolve \
http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork tlbc emulator \
test-ed25519 test-bigint test-vm test-fift test-cells test-smartcont \
test-net test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp \
test-net test-tdactor test-coro test-tdutils test-tonlib-offline test-adnl test-dht test-rldp \
test-rldp2 test-catchain test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
Expand Down
2 changes: 1 addition & 1 deletion assembly/native/build-macos-shared.sh
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ if [ "$with_tests" = true ]; then
lite-client validator-engine-console generate-random-id json2tlo dht-server dht-ping-servers dht-resolve \
http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork tlbc emulator \
test-ed25519 test-bigint test-vm test-fift test-cells test-smartcont \
test-net test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp \
test-net test-tdactor test-coro test-tdutils test-tonlib-offline test-adnl test-dht test-rldp \
test-rldp2 test-catchain test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
else
Expand Down
2 changes: 1 addition & 1 deletion assembly/native/build-ubuntu-appimages.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-
validator-engine lite-client validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy dht-ping-servers dht-resolve \
adnl-proxy create-state emulator test-ed25519 test-bigint \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-tdutils \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-coro test-tdutils \
test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain \
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
Expand Down
2 changes: 1 addition & 1 deletion assembly/native/build-ubuntu-portable.sh
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-
validator-engine lite-client validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy dht-ping-servers dht-resolve \
adnl-proxy create-state emulator test-ed25519 test-bigint \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-tdutils \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-coro test-tdutils \
test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain \
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
Expand Down
2 changes: 1 addition & 1 deletion assembly/native/build-ubuntu-shared.sh
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ ninja storage-daemon storage-daemon-cli fift func tolk tonlib tonlibjson tonlib-
validator-engine lite-client validator-engine-console blockchain-explorer \
generate-random-id json2tlo dht-server http-proxy rldp-http-proxy dht-ping-servers dht-resolve \
adnl-proxy create-state emulator test-ed25519 test-bigint \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-tdutils \
test-vm test-fift test-cells test-smartcont test-net test-tdactor test-coro test-tdutils \
test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain \
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
test $? -eq 0 || { echo "Can't compile ton"; exit 1; }
Expand Down
2 changes: 1 addition & 1 deletion assembly/native/build-windows-2019.bat
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ ninja storage-daemon storage-daemon-cli blockchain-explorer fift func tolk tonli
tonlib-cli validator-engine lite-client validator-engine-console generate-random-id ^
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator ^
test-ed25519 test-bigint test-vm test-fift test-cells test-smartcont test-net ^
test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
test-tdactor test-coro test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver dht-ping-servers dht-resolve
IF %errorlevel% NEQ 0 (
echo Can't compile TON
Expand Down
2 changes: 1 addition & 1 deletion assembly/native/build-windows-2022.bat
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ ninja storage-daemon storage-daemon-cli blockchain-explorer fift func tolk tonli
tonlib-cli validator-engine lite-client validator-engine-console generate-random-id ^
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator ^
test-ed25519 test-bigint test-vm test-fift test-cells test-smartcont test-net ^
test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
test-tdactor test-coro test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver
IF %errorlevel% NEQ 0 (
echo Can't compile TON
Expand Down
2 changes: 1 addition & 1 deletion assembly/native/build-windows.bat
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ ninja storage-daemon storage-daemon-cli blockchain-explorer fift func tolk tonli
tonlib-cli validator-engine lite-client validator-engine-console generate-random-id ^
json2tlo dht-server http-proxy rldp-http-proxy adnl-proxy create-state create-hardfork emulator ^
test-ed25519 test-bigint test-vm test-fift test-cells test-smartcont test-net ^
test-tdactor test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
test-tdactor test-coro test-tdutils test-tonlib-offline test-adnl test-dht test-rldp test-rldp2 test-catchain ^
test-fec test-tddb test-db test-validator-session-state test-emulator proxy-liteserver dht-ping-servers dht-resolve
IF %errorlevel% NEQ 0 (
echo Can't compile TON
Expand Down
5 changes: 5 additions & 0 deletions tdactor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ set(TDACTOR_SOURCE
td/actor/ActorShared.h
td/actor/ActorStats.h
td/actor/common.h
td/actor/coro.h
td/actor/PromiseFuture.h
td/actor/MultiPromise.h

Expand Down Expand Up @@ -52,8 +53,12 @@ add_library(tdactor STATIC ${TDACTOR_SOURCE})
target_include_directories(tdactor PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_link_libraries(tdactor PUBLIC tdutils)

add_executable(tdactor-example-coroutines example/actor-example-coroutines.cpp)
target_link_libraries(tdactor-example-coroutines PUBLIC tdactor)

# BEGIN-INTERNAL
add_subdirectory(benchmark)
add_subdirectory(test)

# END-INTERNAL
install(TARGETS tdactor EXPORT TdTargets
Expand Down
65 changes: 65 additions & 0 deletions tdactor/benchmark/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,68 @@ if (MSVC)
set_property(SOURCE benchmark.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " /wd4457 /wd4316")
endif()

add_executable(benchmark-coro benchmark-coro.cpp)
target_link_libraries(benchmark-coro tdactor tdutils)

# Google Benchmark based coroutine benchmarks
find_package(PkgConfig)
if(PkgConfig_FOUND)
pkg_check_modules(GBENCH benchmark)
if(GBENCH_FOUND)
add_executable(gbench-coro gbench-coro.cpp)
target_link_libraries(gbench-coro tdactor tdutils)
# Use full library paths to avoid conflicts with our "benchmark" executable
target_link_directories(gbench-coro PRIVATE ${GBENCH_LIBRARY_DIRS})
target_link_libraries(gbench-coro -lbenchmark)
target_include_directories(gbench-coro PRIVATE ${GBENCH_INCLUDE_DIRS})
target_compile_options(gbench-coro PRIVATE ${GBENCH_CFLAGS_OTHER})

message(STATUS "Google Benchmark found via pkg-config - gbench-coro target enabled")

# Check for Folly
find_package(folly CONFIG REQUIRED)
if(folly_FOUND)
add_executable(gbench-coro-folly gbench-coro-folly.cpp)
target_link_libraries(gbench-coro-folly -lbenchmark)
target_link_directories(gbench-coro-folly PRIVATE ${GBENCH_LIBRARY_DIRS})
target_include_directories(gbench-coro-folly PRIVATE ${GBENCH_INCLUDE_DIRS})
target_compile_options(gbench-coro-folly PRIVATE ${GBENCH_CFLAGS_OTHER})

find_package(gflags REQUIRED)
target_link_libraries(gbench-coro-folly Folly::folly gflags)

message(STATUS "Folly found - enabling Folly benchmarks in gbench-coro-folly")
else()
message(STATUS "Folly not found - Folly benchmarks disabled")
endif()

add_executable(gbench-coro-yaclib gbench-coro-yaclib.cpp)
target_link_libraries(gbench-coro-yaclib -lbenchmark)
target_link_directories(gbench-coro-yaclib PRIVATE ${GBENCH_LIBRARY_DIRS})
target_include_directories(gbench-coro-yaclib PRIVATE ${GBENCH_INCLUDE_DIRS})
target_compile_options(gbench-coro-yaclib PRIVATE ${GBENCH_CFLAGS_OTHER})

# Check for YACLib
find_package(yaclib CONFIG QUIET)
if(yaclib_FOUND)
target_link_libraries(gbench-coro-yaclib yaclib::yaclib)
message(STATUS "YACLib found - enabling YACLib benchmarks in gbench-coro-yaclib")
else()
message(STATUS "YACLib not found - fetching via FetchContent for gbench-coro-yaclib")
include(FetchContent)
set(YACLIB_FLAGS "CORO" CACHE STRING "" FORCE)
FetchContent_Declare(yaclib
GIT_REPOSITORY https://github.com/YACLib/YACLib.git
GIT_TAG main
)
FetchContent_MakeAvailable(yaclib)
target_link_libraries(gbench-coro-yaclib yaclib)
endif()
target_compile_definitions(gbench-coro-yaclib PRIVATE YACLIB_CORO=2)

else()
message(STATUS "Google Benchmark not found via pkg-config - gbench-coro target disabled")
endif()
else()
message(STATUS "PkgConfig not found - gbench-coro target disabled")
endif()
126 changes: 126 additions & 0 deletions tdactor/benchmark/benchmark-coro.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#include "td/actor/coro.h"
#include "td/actor/actor.h"
#include "td/utils/benchmark.h"

#include <vector>

using namespace td::actor;

class BenchmarkDatabase final : public td::actor::Actor {
public:
Task<size_t> square(size_t x) {
co_return x * x;
}
};

class CoroBenchmark final : public td::actor::Actor {
public:
void start_up() override {
db_ = td::actor::create_actor<BenchmarkDatabase>("BenchmarkDatabase").release();
flow().start_immediate().detach();
}

Task<td::Unit> run_benchmarks() {
LOG(INFO) << "=== Running benchmarks ===";
std::vector<size_t> thread_counts = {1, 10};
size_t total_ops = 100000;

for (size_t thread_count : thread_counts) {
size_t ops_per_thread = std::max<size_t>(1, total_ops / thread_count);
std::vector<StartedTask<td::Unit>> tasks;

auto run_benchmark = [&](const char* name, bool immediate) -> Task<td::Unit> {
td::Timer timer;

for (size_t t = 0; t < thread_count; t++) {
auto task_name = PSTRING() << name << "_" << t;
tasks.push_back(spawn_actor(std::move(task_name), [](auto db, auto ops_per_thread, auto immediate) -> Task<td::Unit> {
for (size_t i = 0; i < ops_per_thread; i++) {
if (immediate) {
(void)co_await ask_immediate(db, &BenchmarkDatabase::square, i);
} else {
(void)co_await ask(db, &BenchmarkDatabase::square, i);
}
}
co_return td::Unit();
}(db_, ops_per_thread, immediate)));
}

for (auto& task : tasks) {
co_await std::move(task);
}
tasks.clear();

auto elapsed = timer.elapsed();
auto ops_per_sec = total_ops / elapsed;
LOG(INFO) << name << " " << ops_per_thread << " ops: " << elapsed << "s (threads=" << thread_count
<< ", " << static_cast<size_t>(ops_per_sec) << " ops/sec)";
co_return td::Unit();
};

co_await run_benchmark("Immediate", true);
co_await run_benchmark("Delayed", false);
}

LOG(INFO) << "=== Optimized benchmarks (direct) ===";
constexpr size_t single_thread = 1;
size_t ops_count = total_ops / single_thread;

// Warm up
for (size_t i = 0; i < 1000; i++) {
(void)co_await ask(db_, &BenchmarkDatabase::square, i);
}

td::Timer timer;
for (size_t i = 0; i < ops_count; i++) {
(void)co_await ask(db_, &BenchmarkDatabase::square, i);
}
auto elapsed = timer.elapsed();
auto ops_per_sec = ops_count / elapsed;
LOG(INFO) << "Direct delayed " << ops_count << " ops: " << elapsed << "s ("
<< static_cast<size_t>(ops_per_sec) << " ops/sec)";

timer = {};
for (size_t i = 0; i < ops_count; i++) {
(void)co_await ask_immediate(db_, &BenchmarkDatabase::square, i);
}
elapsed = timer.elapsed();
ops_per_sec = ops_count / elapsed;
LOG(INFO) << "Direct immediate " << ops_count << " ops: " << elapsed << "s ("
<< static_cast<size_t>(ops_per_sec) << " ops/sec)";

timer = {};
for (size_t i = 0; i < ops_count; i++) {
auto local_square = [](size_t x) -> Task<size_t> { co_return x * x; };
(void)co_await local_square(i);
}
elapsed = timer.elapsed();
ops_per_sec = ops_count / elapsed;
LOG(INFO) << "Local coroutine " << ops_count << " ops: " << elapsed << "s ("
<< static_cast<size_t>(ops_per_sec) << " ops/sec)";

co_return td::Unit();
}

Task<td::Unit> flow() {
LOG(INFO) << "Starting benchmarks";
(void)co_await run_benchmarks();
LOG(INFO) << "Benchmarks completed";
td::actor::SchedulerContext::get()->stop();
stop();
co_return td::Unit();
}

private:
td::actor::ActorId<BenchmarkDatabase> db_;
};

int main() {
SET_VERBOSITY_LEVEL(VERBOSITY_NAME(INFO));
td::actor::Scheduler scheduler({4});

scheduler.run_in_context([&] { td::actor::create_actor<CoroBenchmark>("CoroBenchmark").release(); });

scheduler.run();
return 0;
}
4 changes: 4 additions & 0 deletions tdactor/benchmark/benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@ class ActorExecutorBenchmark : public td::Benchmark {
//queue.push_back(std::move(ptr));
q.push(ptr, 0);
}
void add_token_to_cpu_queue(SchedulerToken token, SchedulerId scheduler_id) override {
SchedulerMessage::Raw *raw = reinterpret_cast<SchedulerMessage::Raw *>(token);
q.push(SchedulerMessage(SchedulerMessage::acquire_t{}, raw), 0);
}
void set_alarm_timestamp(const ActorInfoPtr &actor_info_ptr) override {
UNREACHABLE();
}
Expand Down
Loading