spring-startup-analyzer采集 Spring 应用启动过程数据,生成交互式分析报告(HTML),用于分析 Spring 应用启动卡点,支持 Spring Bean 异步初始化,减少优化 Spring 应用启动时间。
其中 Wall Clock 采样火焰图是基于async-profiler的,async-profiler 只支持 linux 和 mac ,问题在于 windows 没有 POSIX 信号的概念,也没有类似 Linux 中 perf_event_open 的 API 。为了在 windows 下也能生成火焰图,使用了一种简单的方法,采样结果与 async-profiler 相比虽然会存在一些偏差Safepoint bias problem,但是基本上也能用。
思路很简单:
1.首先获取线程名为 main 的线程(主线程)
List<Thread> sampledThreads = new ArrayList<>(ThreadUtils.findThreads(thread -> StringUtils.equals("main", thread.getName())));
2.起一个周期调度任务进行采样,采样结果放到一个LinkedBlockingQueue
中
LinkedBlockingQueue<StackTraceElement[]> STACK_TRACE_QUEUE = new LinkedBlockingQueue<>();
ScheduledExecutorService SAMPLE_SCHEDULER = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
SAMPLE_SCHEDULER.scheduleAtFixedRate(() -> {
sampledThreads = getTargetThreads();
for (Thread thread : sampledThreads) {
STACK_TRACE_QUEUE.add(thread.getStackTrace());
}
}, 0, 5, TimeUnit.MILLISECONDS);
3.起一个处理线程将队列中的采样结果放到 Map 中
while (true) {
try {
StackTraceElement[] traces = STACK_TRACE_QUEUE.poll(5, TimeUnit.SECONDS);
if (traces == null || traces.length == 0) {
continue;
}
List<StackTraceElement> elements = Arrays.asList(traces);
Collections.reverse(elements);
String trace = elements.stream().map(element -> element.getClassName() + "." + element.getMethodName()).collect(Collectors.joining(";"));
TRACE_MAP.put(trace, TRACE_MAP.getOrDefault(trace, 0) + 1);
} catch (InterruptedException ignored) {
}
if (stop && STACK_TRACE_QUEUE.isEmpty()) {
break;
}
}
将采样和处理两个逻辑通过阻塞队列分开可以在一定程度上保证采样周期的稳定性。
将采样到的调用栈样本集进行整合后,需输出如下所示的文本格式。每一行代表一“类“调用栈,空格左边是调用栈的方法名排列,以分号分割,左栈底右栈顶,空格右边是该样本出现的次数。这样就可以进行可视化输出 svg 了,可视化的逻辑参考了 async-profiler 的实现,这里就不在具体描述了。
base_func;func1;func2;func3 10
base_func;funca;funcb 15
最后再推荐一下项目,如果感兴趣欢迎 star, 提 PR
项目地址: https://github.com/linyimin0812/spring-startup-analyzer
项目描述:
采集 Spring 应用启动过程数据——Spring Bean 初始化详情信息,支持初始化耗时/beanName 搜索、Spring Bean 初始化时序图、方法调用次数及耗时统计(支持自定义方法)、应用未加载的 jar 包(帮助 fatjar 瘦身)及应用启动过程线程 wall clock 火焰图,并生成交互式分析报告(HTML),用于分析 Spring 应用启动卡点,支持 Spring Bean 异步初始化,减少优化 Spring 应用启动时间。
亮点:
截图:
Spring Bean 初始化详情
Spring Bean 初始化时序图
方法调用次数、耗时统计(支持自定义方法)
应用未加载的 jar 包(帮助 fatjar 瘦身)
应用启动过程线程 wall clock 火焰图(支持指定线程名称,不指定则采集全部线程)
1
lyxeno 2023-08-08 10:14:07 +08:00 1
用了一下,蛮不错的,已 star
|
2
xubeiyou 2023-08-08 10:51:03 +08:00 1
这个感觉不错的样子! STAR 了 破坏了队形 本来是 666 的 变成 667 了
|
3
chengyiqun 2023-08-08 14:09:57 +08:00
感觉不错, mark 了
|
4
banzhe0421 2023-08-08 18:49:43 +08:00
简单跑了一下,感觉不错,后续有时间看一下代码
|
5
258 2023-08-09 09:07:03 +08:00
感觉不错,
|