后台采样器

基本信息

属性 值
实现类 me.lucko.spark.common.sampler.BackgroundSamplerManager
实例化 SparkPlatform 构造时 new BackgroundSamplerManager(this, this.configuration)
初始化 SparkPlatform.enable() 末尾调用 initialise()
相关命令 /spark profiler

后台采样器是一个服务器启动时自动拉起、持续运行的采样器,让运维不必事先手动开 profiler 就能随时取到最近的性能数据。

启用判定

this.enabled = type != PlatformInfo.Type.CLIENT
        && this.configuration.getBoolean(OPTION_ENABLED, type == PlatformInfo.Type.SERVER);

(BackgroundSamplerManager.java:48)

两个条件同时成立才启用:

  1. 平台类型不是客户端 —— 客户端永远不启用后台采样器
  2. 配置项 backgroundProfiler —— 默认值取「平台是否为服务器」,因此服务端默认开启、客户端默认关闭

若 initialise() 发现 enabled == false 则直接 return,不做任何事。

首次启动的标记流程

initialise() 实现了一种「乐观启动 + 失败标记」模式(BackgroundSamplerManager.java:51-98):

  1. 若 config.json 不含 backgroundProfiler 键,说明是首次按默认值启用:setBoolean(OPTION_ENABLED, true) 并置 didEnableByDefault = true
  2. 打印「Starting background profiler…」
  3. 若为首次启用:先写 _marker_background_profiler_failed = true 并 save() 落盘,再尝试启动
  4. startSampler() 成功后再删除标记并 save()
  5. 失败则被 catch (Throwable e) { e.printStackTrace(); } 吞掉,标记留在配置里 → 下次启动走降级逻辑

这样即使 JVM 直接崩溃,下次启动也能知道上次没起来。

5 个配置项

全部在 BackgroundSamplerManager 顶部以常量声明(BackgroundSamplerManager.java:31-35),默认值如下:

配置键 类型 默认值 作用
backgroundProfiler boolean 服务端 true,客户端 false 总开关(客户端恒不生效)
backgroundProfilerEngine string "async" 采样引擎,等于 "java" 时用内置引擎
backgroundProfilerInterval int 10 采样间隔(毫秒)
backgroundProfilerThreadGrouper string "by-pool" 线程归并方式
backgroundProfilerThreadDumper string "default" 采样哪些线程

这 5 个键与 config.json 中的 3 个端点键、1 个广播键、1 个信任键互不重叠,合计 8 个顶层配置键。

backgroundProfilerThreadGrouper 与 backgroundProfilerThreadDumper 的可选值见 线程分组与导出。

backgroundProfilerInterval 的默认值 10 ms 与 SamplerMode 的 EXECUTION 默认 4 ms 不同 —— 后台采样器构造 SamplerBuilder 时直接 .samplingInterval(interval) 传 10,并不走 SamplerMode.defaultInterval() 的回退逻辑。

启动参数传递

startSampler() 构造采样器的完整链路(BackgroundSamplerManager.java:103-122):

Sampler sampler = new SamplerBuilder()
      .background(true)
      .threadDumper(threadDumper)
      .threadGrouper(threadGrouper)
      .samplingInterval(interval)
      .forceJavaSampler(forceJavaEngine)
      .start(this.platform);
this.platform.getSamplerContainer().setActiveSampler(sampler);

其中 threadDumper 若配置解析结果为 null(即配置值恰为 "default"),回退到 platform.getPlugin().getDefaultThreadDumper()。1.7.10 服务端该实现是构造时捕获的 ThreadDumper.GameThread(主线程),客户端是 ThreadDumper.Specific(minecraft.mcThread)。

与前台采样器的互斥

后台采样器占用全局唯一的采样器槽位(SamplerContainer)。SamplerModule.profilerStart 遇到已有采样器时:

  • 若是后台采样器(isRunningInBackground())→ 广播「Stopping the background profiler before starting… please wait」,停掉并 unsetActiveSampler,继续启动新的前台采样器
  • 若是前台采样器 → 只打印 info 并放弃

前台 /spark profiler stop 之后,若检测到原本跑的是后台采样器,会调用 restartBackgroundSampler() 自动重启,并提示可用 /spark profiler cancel 关闭(SamplerModule.java:181-189)。

cancel 子命令即为「关掉后台采样器且不产出结果」的官方手段。

数值

数值名 值 来源
默认采样间隔 10 ms BackgroundSamplerManager.java:112
引擎默认值 "async" BackgroundSamplerManager.java:104
线程归并默认值 "by-pool" BackgroundSamplerManager.java:106
线程导出默认值 "default" BackgroundSamplerManager.java:107
失败后降级目标 "java" BackgroundSamplerManager.java:70

相关条目