Arrays.parallelSort() 的性能临界点通常在数组长度≥8192时显现,但需通过JMH在固定核心数、不同数据分布下实测确定;小数组因线程开销反超收益,自动退化为串行Dual-Pivot Quicksort。

要定量评估 Arrays.sort() 和 Arrays.parallelSort() 的性能临界点,关键不是“猜大小”,而是用 JMH 在可控条件下测出数组长度与线程数、数据特征共同作用下的真实拐点。这个临界点通常在 8192 左右浮动,但必须实测确认。
明确测试目标和变量组合
临界点不是固定值,它受三类因素影响:数组长度、CPU核心数、数据初始有序度。JMH 测试需覆盖这些维度:
- 数组长度梯度:从 1024 开始,按 2 倍递增(1024 → 2048 → 4096 → 8192 → 16384 → 32768 → 65536),覆盖 JDK 默认阈值前后区间
- 数据分布类型:分别构造随机乱序、已升序、已降序、含大量重复值的数组——parallelSort 对部分有序数据可能退化
-
运行环境约束:用
@Fork(jvmArgs = {"-XX:ParallelGCThreads=4"})固定 GC 线程;用@Threads(4)匹配物理核心数,避免超线程干扰
编写可复现的基准测试类
一个典型 JMH 测试应隔离排序逻辑,防止死码消除,并确保每次迭代使用新数组:
- 用
@State(Scope.Benchmark)在类级预生成不同长度/类型的数组副本,避免每次@Benchmark方法内重复创建开销 - 每个
@Benchmark方法只调用一次Arrays.sort()或Arrays.parallelSort(),并返回排序后首尾元素校验结果(如array[0] + array[array.length-1]),防止 JIT 优化掉整个调用 - 设置
@Warmup(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)和@Measurement(iterations = 10, time = 2, timeUnit = TimeUnit.SECONDS),保证 JIT 充分编译且统计稳定
提取并分析临界点数据
运行后导出 JSON 结果,重点关注 AverageTime 模式下的毫秒级均值及误差范围(±):
- 对每组长度+数据类型组合,画出 sort 与 parallelSort 的平均耗时折线图;两条线交叉处即为该条件下的临界长度
- 若在 8192 处 parallelSort 反而更慢,检查是否触发了 fallback 行为(如单核环境或数组 ≤ 8192 时自动退回到 Dual-Pivot Quicksort)
- 对比吞吐量(
Throughput模式)结果:当 parallelSort 的 ops/s 首次超过 sort 时,对应长度即为实际可用临界点
验证结果的工程适用性
实验室数据需映射到真实场景:
- 若业务中数组多为部分有序(如日志时间戳追加写入),即使长度超 10000,parallelSort 也可能因合并开销不占优,此时临界点上移
- 容器化部署时,若 JVM 被限制只分配 1 个 CPU 核心(
cgroups),parallelSort 会强制走串行路径,临界点失去意义 - 注意 parallelSort 对基本类型是非稳定排序,若业务依赖相等元素的原始顺序,即使性能更好也不能替换


















