diff --git a/.github/workflows/ci v2.yml b/.github/workflows/ci v2.yml index 8d4208783..d952d1518 100644 --- a/.github/workflows/ci v2.yml +++ b/.github/workflows/ci v2.yml @@ -140,10 +140,11 @@ jobs: {name: ci-macos, os: macos-12}] type: [tests, benchmarks] build_type: [{config: Release, test_preset: ci-tests}, {config: Debug, test_preset: ci-tests-debug}] + optimization_disabled: [{mode: 0, postfix: ""}, {mode: 1, postfix: " (Optimizations disabled)"}] timeout-minutes: 20 runs-on: ${{ matrix.config.os }} - name: ${{ matrix.type }} ${{ matrix.config.name }} ${{ matrix.build_type.config }} + name: ${{ matrix.type }} ${{ matrix.config.name }} ${{ matrix.build_type.config }}${{ matrix.optimization_disabled.postfix}} steps: - uses: actions/checkout@v4 @@ -198,7 +199,7 @@ jobs: uses: lukka/run-cmake@v10 with: configurePreset: ${{ matrix.config.name }}-${{ matrix.type }} - configurePresetAdditionalArgs: "['-DCMAKE_BUILD_TYPE=${{ matrix.build_type.config }}', '-DCMAKE_CONFIGURATION_TYPES=${{ matrix.build_type.config }}']" + configurePresetAdditionalArgs: "['-DCMAKE_BUILD_TYPE=${{ matrix.build_type.config }}', '-DCMAKE_CONFIGURATION_TYPES=${{ matrix.build_type.config }}', '-DRPP_DISABLE_DISPOSABLES_OPTIMIZATION=${{matrix.optimization_disabled.mode}}']" buildPreset: ci-build buildPresetAdditionalArgs: "['--config ${{ matrix.build_type.config }}']" testPreset: ${{matrix.build_type.test_preset}} @@ -208,7 +209,7 @@ jobs: uses: actions/upload-artifact@v4 if: matrix.type == 'benchmarks' && matrix.build_type.config == 'Release' with: - name: ${{ matrix.config.name }} + name: ${{ matrix.config.name }}${{ matrix.optimization_disabled.postfix}} path: ${{github.workspace}}/build/test_results/benchmarks_results.json docs: diff --git a/src/benchmarks/CMakeLists.txt b/src/benchmarks/CMakeLists.txt index 38ffd201f..a7bc16391 100644 --- a/src/benchmarks/CMakeLists.txt +++ b/src/benchmarks/CMakeLists.txt @@ -20,6 +20,9 @@ if (RPP_BUILD_RXCPP) get_target_property(DEP_DIR rxcpp INTERFACE_INCLUDE_DIRECTORIES) target_include_directories(${TARGET} SYSTEM PRIVATE ${DEP_DIR}) endif() +if(RPP_DISABLE_DISPOSABLES_OPTIMIZATION) + target_compile_definitions(${TARGET} PRIVATE "RPP_DISABLE_DISPOSABLES_OPTIMIZATION=${RPP_DISABLE_DISPOSABLES_OPTIMIZATION}") +endif() set_target_properties(${TARGET} PROPERTIES FOLDER Tests) set_target_properties(${TARGET} PROPERTIES CXX_CLANG_TIDY "") diff --git a/src/benchmarks/benchmarks.cpp b/src/benchmarks/benchmarks.cpp index 616e9631a..3743cc520 100644 --- a/src/benchmarks/benchmarks.cpp +++ b/src/benchmarks/benchmarks.cpp @@ -801,6 +801,133 @@ int main(int argc, char* argv[]) // NOLINT(bugprone-exception-escape) | rxcpp::operators::subscribe([](char v) { ankerl::nanobench::doNotOptimizeAway(v); }); }); } + SECTION("mix operators with disposables and without disposables") + { + TEST_RPP([&]() { + rpp::subjects::publish_subject s{}; + s.get_observable() + | rpp::ops::filter([](int v) -> bool { return v; }) + | rpp::ops::finally([]() noexcept { ankerl::nanobench::doNotOptimizeAway(1); }) + + | rpp::ops::map([](int v) { return rpp::immediate_just(v * 2, v * 3); }) + | rpp::ops::concat() + + | rpp::ops::filter([](int v) -> bool { return v; }) + | rpp::ops::delay(std::chrono::seconds{0}, rpp::schedulers::immediate{}) + + | rpp::ops::filter([](int v) -> bool { return v; }) + | rpp::ops::subscribe([](int v) { ankerl::nanobench::doNotOptimizeAway(v); }); + const auto obs = s.get_observer(); + obs.on_next(1); + obs.on_completed(); + }); + + TEST_RXCPP([&]() { + rxcpp::subjects::subject s{}; + s.get_observable() + | rxcpp::operators::filter([](int v) -> bool { return v; }) + | rxcpp::operators::finally([]() noexcept { ankerl::nanobench::doNotOptimizeAway(1); }) + + | rxcpp::operators::map([](int v) { return rxcpp::immediate_just(v * 2, v * 3); }) + | rxcpp::operators::concat() + + | rxcpp::operators::filter([](int v) -> bool { return v; }) + | rxcpp::operators::delay(std::chrono::seconds{0}, rxcpp::identity_immediate()) + + | rxcpp::operators::filter([](int v) -> bool { return v; }) + | rxcpp::operators::subscribe([](int v) { ankerl::nanobench::doNotOptimizeAway(v); }); + const auto obs = s.get_subscriber(); + obs.on_next(1); + obs.on_completed(); + }); + } + SECTION("single disposable and looooooong indentity chain") + { + TEST_RPP([&]() { + const auto d = rpp::composite_disposable_wrapper::make(); + rpp::source::create([&](auto&& obs) { + obs.set_upstream(rpp::make_callback_disposable([]() noexcept { ankerl::nanobench::doNotOptimizeAway(1); })); + obs.on_next(1); + obs.on_completed(); + }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::operators::map([](int v) { return v * 2; }) + | rpp::ops::subscribe(d, [](int) {}); + }); + + TEST_RXCPP([&]() { + const auto d = rxcpp::composite_subscription{}; + rxcpp::observable<>::create([&](auto&& obs) { + obs.get_subscription().add([]() noexcept { ankerl::nanobench::doNotOptimizeAway(1); }); + obs.on_next(1); + obs.on_completed(); + }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::map([](int v) { return v * 2; }) + | rxcpp::operators::subscribe(d, [](int) {}); + }); + } + } // BENCHMARK("Scenarios") if (dump.has_value()) diff --git a/src/rpp/rpp/observers/details/fwd.hpp b/src/rpp/rpp/observers/details/fwd.hpp index 6232b0fdc..89fe914b0 100644 --- a/src/rpp/rpp/observers/details/fwd.hpp +++ b/src/rpp/rpp/observers/details/fwd.hpp @@ -74,6 +74,12 @@ namespace rpp::details::observers { static_assert(mode == disposables_mode::Auto || mode == disposables_mode::None || mode == disposables_mode::External || mode == disposables_mode::Boolean); +#if defined(RPP_DISABLE_DISPOSABLES_OPTIMIZATION) and RPP_DISABLE_DISPOSABLES_OPTIMIZATION + if constexpr (mode == disposables_mode::External) + return static_cast(nullptr); + else + return static_cast(nullptr); +#else if constexpr (mode == disposables_mode::Auto) return static_cast(nullptr); else if constexpr (mode == disposables_mode::None) @@ -84,6 +90,7 @@ namespace rpp::details::observers return static_cast(nullptr); else return static_cast(nullptr); +#endif } } // namespace details