


本文目录
可用内存 进程可用内存 Memory Tracker 可用内存 Memory Tracker 的设计与实现方案 ThreadMemoryStats GlobalMemoryStats · Global new/delete operator · MemoryStats Catch std::bac_alloc 算子的内存检测 RPC 的内存检测 错误码 延伸阅读

注:为了同代码保持对应,本文部分用词直接使用了英文,e.g. reserve 内存 quota。



可用内存
进程可用内存
| FLAG | 默认值 | 解释 |
|---|---|---|
| FLAG_cgroup_v2_memory_max_path | /sys/fs/cgroup/memory.max | 通过读取路径确定最大内存使用量 |
| FLAG_cgroup_v2_memory_current_path | /sys/fs/cgroup/memory.current | 通过读取路径确定当前内存使用量 |
--containerized=true
--cgroup_v2_controllers=/sys/fs/cgroup/graphd/cgroup.controllers
--cgroup_v2_memory_stat_path=/sys/fs/cgroup/graphd/memory.stat
--cgroup_v2_memory_max_path=/sys/fs/cgroup/graphd/memory.max
--cgroup_v2_memory_current_path=/sys/fs/cgroup/graphd/memory.current
Memory Tracker 可用内存

| FLAG | 默认值 | 解释 | 支持动态改 |
|---|---|---|---|
| memory_tracker_untracked_reserved_memory_mb | 50 M | Memory Tracker 会管理通过 new/delete 申请的内存,但进程除了通过此种方式申请内存外,还可能存在其他方式占用的内存;比如通过调用底层的 malloc/free 申请,这些内存通过此 flag 控制,在计算时会扣除此部分未被 track 的内存。 | Yes |
| memory_tracker_limit_ratio | 0.8 | 指定 Memory Tracker 可以使用的内存比例,在一些场景,我们可能需要调小来防止 OOM。 | Yes |
在混合部署环境中,存在多个 graphd 或 storaged 混合部署是需要调小。比如 graphd 只占用 50% 内存,则需在 nebula-graphd.conf 中将其手动改成 0.5; 取值范围:memory_tracker_limit_ratio 除了 (0,1] 取值范围外,还额外定义了两个特殊值: 2:通过数据库内核感知当前系统运行环境的可用内存,动态调整可用内存。由于此种方式非实时,有一定的概率会感知不精准; 3:limit 将被设成一个极大值,起到关闭 Memory Tracker 的效果;


Memory Tracker 的设计与实现方案

Global new/delete operator
第一步:通过 MemoryStats 进行内存申请的汇报; 第二步:调用 jemalloc 发生真正的内存分配行为;
jemalloc:Memory Tracker 不改变底层的 malloc 机制,仍然使用 jemalloc 进行内存的申请和释放;
MemoryStats
ThreadMemoryStats
Reservation
// Memory stats for each thread.
struct ThreadMemoryStats {
ThreadMemoryStats();
~ThreadMemoryStats();
// reserved bytes size in current thread
int64_t reserved;
bool throwOnMemoryExceeded{false};
};
throwOnMemoryExceeded
GlobalMemoryStats
limit:通过运行环境和配置信息,换算得到 Memory Tracker 可管理的最大内存。limit 同 Limiter 模块的作用,详细内存换算见上文“Memory Tracker 可用内存”章节; used:原子变量,汇总所有线程汇报上来的已使用内存(包括线程 reserved 的部分)。如果 used + try_to_alloc > limit,且在 throwOnMemoryExceeded 为 true 时,则会抛异常 std::bac_alloc。


Catch std::bac_alloc
算子的内存检测
thenValue([this](StorageRpcResponse<GetNeighborsResponse>&& resp) {
memory::MemoryCheckGuard guard;
// memory tracker turned on code scope
return handleResponse(resp);
})
.thenError(folly::tag_t<std::bad_alloc>{},
[](const std::bad_alloc&) {
// handle memory exceed
})
memory::MemoryCheckGuard guard; \
try {
// ...
} catch (std::bad_alloc & e) { \
// handle memory exceed
}
RPC 的内存检测


错误码
E_GRAPH_MEMORY_EXCEEDED = -2600, // Graph memory exceeded
E_STORAGE_MEMORY_EXCEEDED = -3600, // Storage memory exceeded
🌟 延伸阅读
什么是 malloc 以及动态内存分配:https://en.wikipedia.org/wiki/C_dynamic_memory_allocation jemalloc 原始论文:https://www.bsdcan.org/2006/papers/jemalloc.pdf Facebook 对 jemalloc 的优化:https://engineering.fb.com/2011/01/03/core-data/scalable-memory-allocation-using-jemalloc/


🙋♂️ 喜欢本文的话,来个分享、👍 赞、在看
谢谢~
文章转载自NebulaGraph,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




