diff --git a/ydb/library/yql/minikql/aligned_page_pool.cpp b/ydb/library/yql/minikql/aligned_page_pool.cpp index bfc06d0b853f..0ff6519f112a 100644 --- a/ydb/library/yql/minikql/aligned_page_pool.cpp +++ b/ydb/library/yql/minikql/aligned_page_pool.cpp @@ -379,6 +379,7 @@ void TAlignedPagePoolImpl::ReturnBlock(void* ptr, size_t size) noexcept { Y_DEBUG_ABORT_UNLESS(ActiveBlocks.erase(ptr)); } #endif + UpdateMemoryYellowZone(); } template @@ -500,6 +501,19 @@ void TAlignedPagePoolImpl::Free(void* ptr, size_t size) noexcept { } } +template +void TAlignedPagePoolImpl::UpdateMemoryYellowZone() { + if (IncreaseMemoryLimitCallback) return; + if (Limit == 0) return; + + ui8 usedMemoryPercent = 100 * GetUsed() / Limit; + if (usedMemoryPercent >= EnableMemoryYellowZoneThreshold) { + IsMemoryYellowZoneReached = true; + } else if (usedMemoryPercent <= DisableMemoryYellowZoneThreshold) { + IsMemoryYellowZoneReached = false; + } +} + template bool TAlignedPagePoolImpl::TryIncreaseLimit(ui64 required) { if (!IncreaseMemoryLimitCallback) { diff --git a/ydb/library/yql/minikql/aligned_page_pool.h b/ydb/library/yql/minikql/aligned_page_pool.h index 9a10c2997862..d7bb5f088008 100644 --- a/ydb/library/yql/minikql/aligned_page_pool.h +++ b/ydb/library/yql/minikql/aligned_page_pool.h @@ -237,13 +237,7 @@ class TAlignedPagePoolImpl { UpdateMemoryYellowZone(); } - void UpdateMemoryYellowZone() { - if (IncreaseMemoryLimitCallback) return; - - if (Limit != 0) { - IsMemoryYellowZoneReached = (100 * GetUsed() / Limit) > MemoryYellowZoneThreshold; - } - } + void UpdateMemoryYellowZone(); bool TryIncreaseLimit(ui64 required); @@ -279,8 +273,10 @@ class TAlignedPagePoolImpl { // Indicates when memory limit is almost reached. bool IsMemoryYellowZoneReached = false; // This theshold is used to determine is memory limit is almost reached. - // If TIncreaseMemoryLimitCallback is set this threshold should be ignored. - const ui8 MemoryYellowZoneThreshold = 80; + // If TIncreaseMemoryLimitCallback is set this thresholds should be ignored. + // The yellow zone turns on when memory consumption reaches 80% and turns off when consumption drops below 50%. + const ui8 EnableMemoryYellowZoneThreshold = 80; + const ui8 DisableMemoryYellowZoneThreshold = 50; }; using TAlignedPagePool = TAlignedPagePoolImpl<>; diff --git a/ydb/library/yql/minikql/aligned_page_pool_ut.cpp b/ydb/library/yql/minikql/aligned_page_pool_ut.cpp index f387b5df0c39..b917176dd12d 100644 --- a/ydb/library/yql/minikql/aligned_page_pool_ut.cpp +++ b/ydb/library/yql/minikql/aligned_page_pool_ut.cpp @@ -131,6 +131,49 @@ Y_UNIT_TEST(UnalignedMmapUnalignedSize) { ); } +Y_UNIT_TEST(YellowZoneSwitchesCorrectlyBlock) { + TAlignedPagePool::ResetGlobalsUT(); + TAlignedPagePoolImpl alloc(__LOCATION__); + + // choose relatively big chunk so ALLOC_AHEAD_PAGES don't affect the correctness of the test + auto size = 1024 * TAlignedPagePool::POOL_PAGE_SIZE; + + alloc.SetLimit(size * 10); + + // 50% allocated -> no yellow zone + auto block1 = alloc.GetBlock(size * 5); + UNIT_ASSERT_VALUES_EQUAL(false, alloc.IsMemoryYellowZoneEnabled()); + + // 70% allocated -> no yellow zone + auto block2 = alloc.GetBlock(size * 2); + UNIT_ASSERT_VALUES_EQUAL(false, alloc.IsMemoryYellowZoneEnabled()); + + // 90% allocated -> yellow zone is enabled (> 80%) + auto block3 = alloc.GetBlock(size * 2); + UNIT_ASSERT_VALUES_EQUAL(true, alloc.IsMemoryYellowZoneEnabled()); + + // 70% allocated -> yellow zone is still enabled (> 50%) + alloc.ReturnBlock(block3, size * 2); + UNIT_ASSERT_VALUES_EQUAL(true, alloc.IsMemoryYellowZoneEnabled()); + + // 50% allocated -> yellow zone is disabled + alloc.ReturnBlock(block2, size * 2); + UNIT_ASSERT_VALUES_EQUAL(false, alloc.IsMemoryYellowZoneEnabled()); + + // 0% allocated -> yellow zone is disabled + alloc.ReturnBlock(block1, size * 5); + UNIT_ASSERT_VALUES_EQUAL(false, alloc.IsMemoryYellowZoneEnabled()); +} + +Y_UNIT_TEST(YellowZoneZeroDivision) { + TAlignedPagePool::ResetGlobalsUT(); + TAlignedPagePoolImpl alloc(__LOCATION__); + + alloc.SetLimit(0); + + UNIT_ASSERT_EQUAL(false, alloc.IsMemoryYellowZoneEnabled()); +} + } // Y_UNIT_TEST_SUITE(TAlignedPagePoolTest) } // namespace NMiniKQL