Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce a runtime parameter for lazy result max cache size #1638

Merged
Merged
5 changes: 5 additions & 0 deletions src/ServerMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,11 @@ int main(int argc, char** argv) {
optionFactory.getProgramOption<"cache-max-size-single-entry">(),
"Maximum size for a single cache entry. That is, "
"results larger than this will not be cached unless pinned.");
add("lazy-result-max-cache-size,E",
optionFactory.getProgramOption<"lazy-result-max-cache-size">(),
"Maximum size up to which lazy results will be cached by aggregating "
"partial results. Caching does cause significant overhead for this "
"case.");
add("cache-max-num-entries,k",
optionFactory.getProgramOption<"cache-max-num-entries">(),
"Maximum number of entries in the cache. If exceeded, remove "
Expand Down
8 changes: 5 additions & 3 deletions src/engine/Operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,13 @@ CacheValue Operation::runComputationAndPrepareForCache(
const QueryCacheKey& cacheKey, bool pinned) {
auto& cache = _executionContext->getQueryTreeCache();
auto result = runComputation(timer, computationMode);
if (!result.isFullyMaterialized() &&
!unlikelyToFitInCache(cache.getMaxSizeSingleEntry())) {
auto maxSize =
std::min(RuntimeParameters().get<"lazy-result-max-cache-size">(),
cache.getMaxSizeSingleEntry());
if (!result.isFullyMaterialized() && !unlikelyToFitInCache(maxSize)) {
AD_CONTRACT_CHECK(!pinned);
result.cacheDuringConsumption(
[maxSize = cache.getMaxSizeSingleEntry()](
[maxSize](
const std::optional<Result::IdTableVocabPair>& currentIdTablePair,
const Result::IdTableVocabPair& newIdTable) {
auto currentSize =
Expand Down
5 changes: 4 additions & 1 deletion src/global/RuntimeParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ inline auto& RuntimeParameters() {
Bool<"group-by-disable-index-scan-optimizations">{false},
SizeT<"service-max-value-rows">{10'000},
SizeT<"query-planning-budget">{1500},
Bool<"throw-on-unbound-variables">{false}};
Bool<"throw-on-unbound-variables">{false},
// Control up until which size lazy results should be cached. Caching
// does cause significant overhead for this case.
MemorySizeParameter<"lazy-result-max-cache-size">{5_MB}};
}();
return params;
}
Expand Down
29 changes: 17 additions & 12 deletions test/OperationTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@

#include "engine/NeutralElementOperation.h"
#include "engine/ValuesForTesting.h"
#include "global/RuntimeParameters.h"
#include "util/IdTableHelpers.h"
#include "util/IndexTestHelpers.h"
#include "util/OperationTestHelpers.h"
#include "util/RuntimeParametersTestHelpers.h"

using namespace ad_utility::testing;
using namespace ::testing;
Expand Down Expand Up @@ -591,20 +593,23 @@ TEST(Operation, checkLazyOperationIsNotCachedIfTooLarge) {

ad_utility::Timer timer{ad_utility::Timer::InitialStatus::Started};

auto originalSize = qec->getQueryTreeCache().getMaxSizeSingleEntry();

// Too small for storage
qec->getQueryTreeCache().setMaxSizeSingleEntry(1_B);

auto cacheValue = valuesForTesting.runComputationAndPrepareForCache(
timer, ComputationMode::LAZY_IF_SUPPORTED, makeQueryCacheKey("test"),
false);
EXPECT_FALSE(
qec->getQueryTreeCache().cacheContains(makeQueryCacheKey("test")));
qec->getQueryTreeCache().setMaxSizeSingleEntry(originalSize);
std::optional<CacheValue> cacheValue = std::nullopt;
{
// Too small for storage, make sure to change back before consuming
// generator to additionally assert sure it is not re-read on every
// iteration.
auto cleanup =
setRuntimeParameterForTest<"lazy-result-max-cache-size">(1_B);

cacheValue = valuesForTesting.runComputationAndPrepareForCache(
timer, ComputationMode::LAZY_IF_SUPPORTED, makeQueryCacheKey("test"),
false);
EXPECT_FALSE(
qec->getQueryTreeCache().cacheContains(makeQueryCacheKey("test")));
}

for ([[maybe_unused]] Result::IdTableVocabPair& _ :
cacheValue.resultTable().idTables()) {
cacheValue->resultTable().idTables()) {
}

EXPECT_FALSE(
Expand Down
Loading