我已设置并使用 https://github.com/jvm-profiling-tools/async-profiler这非常有用,但我有一件奇怪的事情无法解释。
我的设置正是多个演示显示它可以提供帮助的地方:
具有节点池的 AKS kubernetes 集群
部署在一个节点上的 Pod
在容器内,我使用 debuginfo 设置了 openjdk-11
分析设置很简单 ./profiler start -e malloc PID
由于我在虚拟化环境中进行分析,因此我收到的唯一警告是
[WARN] Kernel symbols are unavailable due to restrictions. Try sysctl kernel.kptr_restrict=0 sysctl kernel.perf_event_paranoid=1
我认为关于 malloc 调用捕获可能不需要。
问题是,经过一段时间的分析后,我捕获了火焰图显示的分配部分:堆栈跟踪“未知”(参见附图)。可能是我在容器中仍然没有完整的设置,或者我真的需要这些 sysctl?
问题是,通过虚拟化将它们放置到位并不是一件小事,因为据我所知,这实际上会影响我们正在运行的底层节点。
更新
现在,在我的微服务的所有主要功能至少触发一次后,我重新启动了分析,似乎没有未知的分配。愚蠢的问题,但是我是否会在所有类加载发生之前立即开始分析(因为 bean 是惰性实例化的),这就是它被这样分类的原因?
更新2
不久之后,同样的现象再次发生,据报道,捕获的大量 malloc 事件是未知的,顶部显示没有显着增加。这是否是由于虚拟化造成的,而我实际上是从同一节点上的其他容器捕获事件?在我的容器中,不再有 java 进程,并且我还直接指定 PID
更新3
所以在 Andrei 为我提供了“dwarf stackwalker”之后,这看起来好多了。我只有一个问题还不清楚,但只有我一个人。我们在这里分析 malloc 事件: ./profile.sh start --cstack dwarf -e malloc PID 那么我在这些火焰图上看到的是:是否只有捕获的事件号可以同时释放,或者它当前由所有这些 malloc 持有 native 内存?
我目前的情况是,我看到 payara-micro healthcheck 和 autodeploy 持有大量内存,这很奇怪,也是我对泄漏源的第一个猜测。
最佳答案
这里不涉及容器环境。
系统上的libc
(其中malloc
实现所在)似乎是在没有帧指针的情况下编译的。因此内核中的标准堆栈遍历机制无法找到 malloc
框架的父级。
我最近实现了一种替代的堆栈遍历算法,该算法依赖 DWARF unwinding information 。新版本尚未发布,但您可以尝试从源代码构建它。或者,为了您的方便,我在这里准备了新版本:async-profiler-2.6-dwarf-linux-x64.tar.gz
然后添加 --cstack dwarf
选项,所有 malloc
堆栈跟踪都应该就位。
关于java - asyncprofiler malloc 未定义类别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70860682/