内存超限错误分析

    当查询或导入报错时,可能的原因:进程内存超限、系统剩余可用内存不足、超过单次查询执行的内存上限。

    当返回如下报错时,说明进程内存超限,或者系统剩余可用内存不足,具体原因看内存统计值。

    同时可以在 log/be.INFO 中找到如下日志,确认当前进程内存使用是否符合预期,日志同样分为三部分: 1、Process Memory Summary:进程内存统计。 2、Alloc Stacktrace:触发内存超限检测的栈,这不一定是大内存申请的位置。 3、Memory Tracker Summary:进程 memory tracker 统计,参考 分析使用内存的位置。 注意: 1、进程内存超限日志的打印间隔是1s,进程内存超限后,BE大多数位置的内存申请都会感知,并尝试做出预定的回调方法,并打印进程内存超限日志,所以如果日志中 Try Alloc 的值很小,则无须关注Alloc Stacktrace,直接分析Memory Tracker Summary即可。 2、当进程内存超限后,BE会触发内存GC。

    当错误信息中系统可用内存小于低水位线时,同样当作进程内存超限处理,其中系统可用内存的值来自于/proc/meminfo中的MemAvailable,当不足时继续内存申请可能返回 std::bad_alloc 或者导致BE进程OOM,因为刷新进程内存统计和BE内存GC都具有一定的滞后性,所以预留小部分内存buffer作为低水位线,尽可能避免OOM。

    低水位线默认最大1.6G,根据MemTotalvm/min_free_kbytesconfg::mem_limitconfig::max_sys_mem_available_low_water_mark_bytes共同算出,并避免浪费过多内存。其中MemTotal是系统总内存,取值同样来自/proc/meminfovm/min_free_kbytes是操作系统给内存GC过程预留的buffer,取值通常在 0.4% 到 5% 之间,某些云服务器上vm/min_free_kbytes可能为5%,这会导致直观上系统可用内存比真实值少;调大config::max_sys_mem_available_low_water_mark_bytes将在大于16G内存的机器上,为Full GC预留更多的内存buffer,反之调小将尽可能充分使用内存。

    查询或导入单次执行内存超限

    当返回如下报错时,说明超过单次执行内存限制。

    set global enable_profile=true后,可以在单次查询内存超限时,在 log/be.INFO 中打印日志,用于确认当前查询内存使用是否符合预期。 同时可以在 log/be.INFO 中找到如下日志,确认当前查询内存使用是否符合预期,日志同样分为三部分: 1、Process Memory Summary:进程内存统计。 2、Alloc Stacktrace:触发内存超限检测的栈,这不一定是大内存申请的位置。 3、Memory Tracker Summary:当前查询的 memory tracker 统计,可以看到查询每个算子当前使用的内存和峰值,具体可参考 Memory Tracker。 注意:一个查询在内存超限后只会打印一次日志,此时查询的多个线程都会感知,并尝试等待内存释放,或者cancel当前查询,如果日志中 Try Alloc 的值很小,则无须关注,直接分析Memory Tracker Summary即可。