From 2ef2ea1728fce0c9a6526b0820b03b7002d234d1 Mon Sep 17 00:00:00 2001 From: wqking Date: Fri, 19 Jul 2024 15:58:29 +0800 Subject: [PATCH] When ranking overloaded callables, break when an exactly matched callable is found to improve performance --- .../metapp/implement/internal/declareutil_i.h | 13 ++++++----- include/metapp/interfaces/metacallable.h | 8 +++++++ tests/benchmark/benchmark_misc.cpp | 22 +++++++++++++++++++ .../metatypes/test_default_args_function.cpp | 2 +- tests/unittest/test_metacallable.cpp | 4 ++-- 5 files changed, 40 insertions(+), 9 deletions(-) diff --git a/include/metapp/implement/internal/declareutil_i.h b/include/metapp/implement/internal/declareutil_i.h index 0da2c7ae..f3fb9f74 100644 --- a/include/metapp/implement/internal/declareutil_i.h +++ b/include/metapp/implement/internal/declareutil_i.h @@ -24,13 +24,10 @@ #include #include #include +#include namespace metapp { -static constexpr int invokeRankMatch = 1000; -static constexpr int invokeRankCast = 1; -static constexpr int invokeRankNone = 0; - namespace internal_ { template @@ -88,7 +85,7 @@ struct MetaCallableInvokeChecker template static int doRankInvoke(const ArgumentSpan & arguments, IntConstantList) { if(argCount == arguments.size() && arguments.empty()) { - return invokeRankMatch; + return invokeRankMax; } std::array rankList { rankArgumentMatching(arguments)... @@ -97,13 +94,17 @@ struct MetaCallableInvokeChecker (void)arguments; (void)rankList; int rank = 0; + bool allMatchExactly = true; for(auto it = std::begin(rankList); it != std::end(rankList); ++it) { if(*it == invokeRankNone) { return invokeRankNone; } + if(*it != invokeRankMatch) { + allMatchExactly = false; + } rank += *it; } - return rank; + return allMatchExactly ? invokeRankMax : rank; } }; diff --git a/include/metapp/interfaces/metacallable.h b/include/metapp/interfaces/metacallable.h index e02e5f03..b3fbec2a 100644 --- a/include/metapp/interfaces/metacallable.h +++ b/include/metapp/interfaces/metacallable.h @@ -115,6 +115,11 @@ class MetaCallable } }; +static constexpr int invokeRankMatch = 1000; +static constexpr int invokeRankCast = 1; +static constexpr int invokeRankNone = 0; +static constexpr int invokeRankMax = std::numeric_limits::max(); + template Iterator findCallable( Iterator first, @@ -133,6 +138,9 @@ Iterator findCallable( if(rank > maxRank) { maxRank = rank; result = first; + if(rank == invokeRankMax) { + break; + } } } diff --git a/tests/benchmark/benchmark_misc.cpp b/tests/benchmark/benchmark_misc.cpp index c63e5653..4344957d 100644 --- a/tests/benchmark/benchmark_misc.cpp +++ b/tests/benchmark/benchmark_misc.cpp @@ -144,5 +144,27 @@ BenchmarkFunc printResult(t2, iterations, "Misc, Fill std::vector, MetaIndexable"); } +metapp::Variant tempGet(const int n) +{ + switch(n) { + case 0: + return 5LL; + case 1: + return 6LL; + } + return "abc"; +} + +TEST_CASE("temp") +{ + constexpr int iterations = generalIterations; + const auto t1 = measureElapsedTime([iterations]() { + for(int i = 0; i < iterations; ++i) { + metapp::Variant v = tempGet(i % 2); + dontOptimizeAway(v); + } + }); + printResult(t1, iterations, "Misc, temp"); +} } //namespace diff --git a/tests/unittest/metatypes/test_default_args_function.cpp b/tests/unittest/metatypes/test_default_args_function.cpp index 0ab9374e..1e7b7ea0 100644 --- a/tests/unittest/metatypes/test_default_args_function.cpp +++ b/tests/unittest/metatypes/test_default_args_function.cpp @@ -112,7 +112,7 @@ TEST_CASE("metatypes, DefaultArgsFunction, MyClass::myFunc2") REQUIRE(metapp::callableRankInvoke(v, &obj, 5) == metapp::invokeRankNone); // metapp::invokeRankMatch * 3 is each of the three default arguments receives metapp::invokeRankMatch. REQUIRE(metapp::callableRankInvoke(v, &obj, 5, std::string("abc")) - == metapp::invokeRankMatch + metapp::invokeRankMatch + metapp::invokeRankMatch * 3); + == metapp::invokeRankMax); REQUIRE(metapp::callableRankInvoke(v, &obj, 5, "abc") == metapp::invokeRankMatch + metapp::invokeRankCast + metapp::invokeRankMatch * 3); REQUIRE(metapp::callableRankInvoke(v, &obj, 5, "abc", 6) diff --git a/tests/unittest/test_metacallable.cpp b/tests/unittest/test_metacallable.cpp index 5bfdd142..9f1c3df1 100644 --- a/tests/unittest/test_metacallable.cpp +++ b/tests/unittest/test_metacallable.cpp @@ -28,10 +28,10 @@ namespace { TEST_CASE("MetaCallable, rankInvoke") { - REQUIRE(metapp::callableRankInvoke(std::function(), nullptr, 5) == metapp::invokeRankMatch); + REQUIRE(metapp::callableRankInvoke(std::function(), nullptr, 5) == metapp::invokeRankMax); REQUIRE(metapp::callableRankInvoke(std::function(), nullptr, metapp::Variant(5)) == metapp::invokeRankCast); - REQUIRE(metapp::callableRankInvoke(std::function(), nullptr, std::string("abc")) == metapp::invokeRankMatch); + REQUIRE(metapp::callableRankInvoke(std::function(), nullptr, std::string("abc")) == metapp::invokeRankMax); REQUIRE(metapp::callableRankInvoke(std::function(), nullptr, "abc") == metapp::invokeRankCast); REQUIRE(metapp::callableRankInvoke(std::function(), nullptr, 5, "abc") == metapp::invokeRankCast + metapp::invokeRankCast);