This is an automated email from the ASF dual-hosted git repository. zouxinyi pushed a commit to branch branch-2.1 in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-2.1 by this push: new 747172237ac [branch-2.1](memory) Pick some memory GC patch (#37725) 747172237ac is described below commit 747172237ac36ff0bdb60acf59c5b0b92b02d9a2 Author: Xinyi Zou <zouxiny...@gmail.com> AuthorDate: Sun Jul 14 15:19:40 2024 +0800 [branch-2.1](memory) Pick some memory GC patch (#37725) pick #36768 #37164 #37174 #37525 --- be/src/common/config.cpp | 8 ++------ be/src/common/config.h | 10 ++++++---- be/src/common/daemon.cpp | 27 +++++++++++++++------------ be/src/olap/page_cache.cpp | 25 +++++++++---------------- be/src/olap/page_cache.h | 3 +-- be/src/util/mem_info.cpp | 8 +++++++- be/src/util/mem_info.h | 8 ++++++++ 7 files changed, 48 insertions(+), 41 deletions(-) diff --git a/be/src/common/config.cpp b/be/src/common/config.cpp index c747391abe0..7c687923803 100644 --- a/be/src/common/config.cpp +++ b/be/src/common/config.cpp @@ -113,12 +113,7 @@ DEFINE_mInt32(max_fill_rate, "2"); DEFINE_mInt32(double_resize_threshold, "23"); -// The maximum low water mark of the system `/proc/meminfo/MemAvailable`, Unit byte, default 1.6G, -// actual low water mark=min(1.6G, MemTotal * 10%), avoid wasting too much memory on machines -// with large memory larger than 16G. -// Turn up max. On machines with more than 16G memory, more memory buffers will be reserved for Full GC. -// Turn down max. will use as much memory as possible. -DEFINE_Int64(max_sys_mem_available_low_water_mark_bytes, "1717986918"); +DEFINE_Int64(max_sys_mem_available_low_water_mark_bytes, "6871947673"); // The size of the memory that gc wants to release each time, as a percentage of the mem limit. DEFINE_mString(process_minor_gc_size, "10%"); @@ -556,6 +551,7 @@ DEFINE_String(pprof_profile_dir, "${DORIS_HOME}/log"); // for jeprofile in jemalloc DEFINE_mString(jeprofile_dir, "${DORIS_HOME}/log"); DEFINE_mBool(enable_je_purge_dirty_pages, "true"); +DEFINE_mString(je_dirty_pages_mem_limit_percent, "5%"); // to forward compatibility, will be removed later DEFINE_mBool(enable_token_check, "true"); diff --git a/be/src/common/config.h b/be/src/common/config.h index 75cb0e2e272..945454079bf 100644 --- a/be/src/common/config.h +++ b/be/src/common/config.h @@ -155,10 +155,10 @@ DECLARE_mInt32(max_fill_rate); DECLARE_mInt32(double_resize_threshold); -// The maximum low water mark of the system `/proc/meminfo/MemAvailable`, Unit byte, default 1.6G, -// actual low water mark=min(1.6G, MemTotal * 10%), avoid wasting too much memory on machines -// with large memory larger than 16G. -// Turn up max. On machines with more than 16G memory, more memory buffers will be reserved for Full GC. +// The maximum low water mark of the system `/proc/meminfo/MemAvailable`, Unit byte, default 6.4G, +// actual low water mark=min(6.4G, MemTotal * 5%), avoid wasting too much memory on machines +// with large memory larger than 128G. +// Turn up max. On machines with more than 128G memory, more memory buffers will be reserved for Full GC. // Turn down max. will use as much memory as possible. DECLARE_Int64(max_sys_mem_available_low_water_mark_bytes); @@ -609,6 +609,8 @@ DECLARE_String(pprof_profile_dir); DECLARE_mString(jeprofile_dir); // Purge all unused dirty pages for all arenas. DECLARE_mBool(enable_je_purge_dirty_pages); +// Purge all unused Jemalloc dirty pages for all arenas when exceed je_dirty_pages_mem_limit and process exceed soft limit. +DECLARE_mString(je_dirty_pages_mem_limit_percent); // to forward compatibility, will be removed later DECLARE_mBool(enable_token_check); diff --git a/be/src/common/daemon.cpp b/be/src/common/daemon.cpp index d54189bce23..00d9caa4155 100644 --- a/be/src/common/daemon.cpp +++ b/be/src/common/daemon.cpp @@ -194,26 +194,29 @@ void Daemon::memory_maintenance_thread() { doris::PerfCounters::refresh_proc_status(); doris::MemInfo::refresh_proc_meminfo(); doris::GlobalMemoryArbitrator::reset_refresh_interval_memory_growth(); + ExecEnv::GetInstance()->brpc_iobuf_block_memory_tracker()->set_consumption( + butil::IOBuf::block_memory()); + // Refresh allocator memory metrics. +#if !defined(ADDRESS_SANITIZER) && !defined(LEAK_SANITIZER) && !defined(THREAD_SANITIZER) + doris::MemInfo::refresh_allocator_mem(); +#ifdef USE_JEMALLOC + if (doris::MemInfo::je_dirty_pages_mem() > doris::MemInfo::je_dirty_pages_mem_limit() && + GlobalMemoryArbitrator::is_exceed_soft_mem_limit()) { + doris::MemInfo::notify_je_purge_dirty_pages(); + } +#endif + if (config::enable_system_metrics) { + DorisMetrics::instance()->system_metrics()->update_allocator_metrics(); + } +#endif // Update and print memory stat when the memory changes by 256M. if (abs(last_print_proc_mem - PerfCounters::get_vm_rss()) > 268435456) { last_print_proc_mem = PerfCounters::get_vm_rss(); doris::MemTrackerLimiter::clean_tracker_limiter_group(); doris::MemTrackerLimiter::enable_print_log_process_usage(); - // Refresh mem tracker each type counter. doris::MemTrackerLimiter::refresh_global_counter(); - - // Refresh allocator memory metrics. -#if !defined(ADDRESS_SANITIZER) && !defined(LEAK_SANITIZER) && !defined(THREAD_SANITIZER) - doris::MemInfo::refresh_allocator_mem(); - if (config::enable_system_metrics) { - DorisMetrics::instance()->system_metrics()->update_allocator_metrics(); - } -#endif - - ExecEnv::GetInstance()->brpc_iobuf_block_memory_tracker()->set_consumption( - butil::IOBuf::block_memory()); LOG(INFO) << doris::GlobalMemoryArbitrator:: process_mem_log_str(); // print mem log when memory state by 256M } diff --git a/be/src/olap/page_cache.cpp b/be/src/olap/page_cache.cpp index fe0a99af34f..1f0556f4642 100644 --- a/be/src/olap/page_cache.cpp +++ b/be/src/olap/page_cache.cpp @@ -26,16 +26,14 @@ namespace doris { template <typename TAllocator> PageBase<TAllocator>::PageBase(size_t b, bool use_cache, segment_v2::PageTypePB page_type) - : LRUCacheValueBase(), - _size(b), - _capacity(b), - _use_cache(use_cache), - _page_type(page_type) { - if (_use_cache) { - SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER( - StoragePageCache::instance()->mem_tracker(_page_type)); - _data = reinterpret_cast<char*>(TAllocator::alloc(_capacity, ALLOCATOR_ALIGNMENT_16)); + : LRUCacheValueBase(), _size(b), _capacity(b) { + if (use_cache) { + _mem_tracker_by_allocator = StoragePageCache::instance()->mem_tracker(page_type); } else { + _mem_tracker_by_allocator = thread_context()->thread_mem_tracker_mgr->limiter_mem_tracker(); + } + { + SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(_mem_tracker_by_allocator); _data = reinterpret_cast<char*>(TAllocator::alloc(_capacity, ALLOCATOR_ALIGNMENT_16)); } } @@ -44,13 +42,8 @@ template <typename TAllocator> PageBase<TAllocator>::~PageBase() { if (_data != nullptr) { DCHECK(_capacity != 0 && _size != 0); - if (_use_cache) { - SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER( - StoragePageCache::instance()->mem_tracker(_page_type)); - TAllocator::free(_data, _capacity); - } else { - TAllocator::free(_data, _capacity); - } + SCOPED_SWITCH_THREAD_MEM_TRACKER_LIMITER(_mem_tracker_by_allocator); + TAllocator::free(_data, _capacity); } } diff --git a/be/src/olap/page_cache.h b/be/src/olap/page_cache.h index 23b3574a10a..09fc689959c 100644 --- a/be/src/olap/page_cache.h +++ b/be/src/olap/page_cache.h @@ -60,8 +60,7 @@ private: // Effective size, smaller than capacity, such as data page remove checksum suffix. size_t _size = 0; size_t _capacity = 0; - bool _use_cache; - segment_v2::PageTypePB _page_type; + std::shared_ptr<MemTrackerLimiter> _mem_tracker_by_allocator; }; using DataPage = PageBase<Allocator<false>>; diff --git a/be/src/util/mem_info.cpp b/be/src/util/mem_info.cpp index 45e609d7100..b6f35df5d9c 100644 --- a/be/src/util/mem_info.cpp +++ b/be/src/util/mem_info.cpp @@ -52,6 +52,8 @@ std::atomic<int64_t> MemInfo::_s_mem_limit = std::numeric_limits<int64_t>::max() std::atomic<int64_t> MemInfo::_s_soft_mem_limit = std::numeric_limits<int64_t>::max(); std::atomic<int64_t> MemInfo::_s_allocator_cache_mem = 0; +std::atomic<int64_t> MemInfo::_s_je_dirty_pages_mem = std::numeric_limits<int64_t>::min(); +std::atomic<int64_t> MemInfo::_s_je_dirty_pages_mem_limit = std::numeric_limits<int64_t>::max(); std::atomic<int64_t> MemInfo::_s_virtual_memory_used = 0; int64_t MemInfo::_s_cgroup_mem_limit = std::numeric_limits<int64_t>::max(); @@ -86,6 +88,8 @@ void MemInfo::refresh_allocator_mem() { get_je_metrics("stats.metadata") + get_je_all_arena_metrics("pdirty") * get_page_size(), std::memory_order_relaxed); + _s_je_dirty_pages_mem.store(get_je_all_arena_metrics("pdirty") * get_page_size(), + std::memory_order_relaxed); _s_virtual_memory_used.store(get_je_metrics("stats.mapped"), std::memory_order_relaxed); #else _s_allocator_cache_mem.store(get_tc_metrics("tcmalloc.pageheap_free_bytes") + @@ -244,6 +248,8 @@ void MemInfo::refresh_proc_meminfo() { _s_mem_limit, &is_percent)); _s_process_full_gc_size.store(ParseUtil::parse_mem_spec(config::process_full_gc_size, -1, _s_mem_limit, &is_percent)); + _s_je_dirty_pages_mem_limit.store(ParseUtil::parse_mem_spec( + config::je_dirty_pages_mem_limit_percent, -1, _s_mem_limit, &is_percent)); } // 3. refresh process available memory @@ -298,7 +304,7 @@ void MemInfo::init() { // upper sys_mem_available_low_water_mark, avoid wasting too much memory. _s_sys_mem_available_low_water_mark = std::max<int64_t>( std::min<int64_t>(std::min<int64_t>(_s_physical_mem - _s_mem_limit, - int64_t(_s_physical_mem * 0.1)), + int64_t(_s_physical_mem * 0.05)), config::max_sys_mem_available_low_water_mark_bytes), 0); _s_sys_mem_available_warning_water_mark = _s_sys_mem_available_low_water_mark * 2; diff --git a/be/src/util/mem_info.h b/be/src/util/mem_info.h index 1b92d0eb9f0..6b66d05033f 100644 --- a/be/src/util/mem_info.h +++ b/be/src/util/mem_info.h @@ -144,6 +144,12 @@ public: static inline size_t allocator_cache_mem() { return _s_allocator_cache_mem.load(std::memory_order_relaxed); } + static inline int64_t je_dirty_pages_mem() { + return _s_je_dirty_pages_mem.load(std::memory_order_relaxed); + } + static inline int64_t je_dirty_pages_mem_limit() { + return _s_je_dirty_pages_mem_limit.load(std::memory_order_relaxed); + } // Tcmalloc property `generic.total_physical_bytes` records the total length of the virtual memory // obtained by the process malloc, not the physical memory actually used by the process in the OS. @@ -178,6 +184,8 @@ private: static std::atomic<int64_t> _s_soft_mem_limit; static std::atomic<int64_t> _s_allocator_cache_mem; + static std::atomic<int64_t> _s_je_dirty_pages_mem; + static std::atomic<int64_t> _s_je_dirty_pages_mem_limit; static std::atomic<int64_t> _s_virtual_memory_used; static int64_t _s_cgroup_mem_limit; --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org