- 数据湖
- 湖仓一体
- 大数据
【免费下载链接】iceberg
Apache Iceberg
Apache Iceberg 项目内置了一套基于 JMH(Java Microbenchmark Harness)的基准测试体系,用于量化 Spark + Iceberg 在读、写、过滤、向量化读取等场景下的性能表现,并与 Spark 内置 file source 直接对比。本文以 site/docs/benchmarks.md 为主线,结合仓库中的 jmh.gradle、.github/workflows/jmh-benchmarks.yml 以及spark/*/spark/src/jmh目录下的 benchmark 源码,完整讲解 Iceberg JMH 基准测试的组成、GitHub Actions 云端运行方式、本地 Gradle 命令,以及每个 benchmark 的评测目标与底层实现要点,帮助你快速上手并正确解读测试结果。
一、JMH 基准测试在 Iceberg 仓库中的位置与运行约定
1.1 Benchmark 源码的存放目录
Iceberg 仓库中所有 JMH benchmark 的 Java 源码统一放在各模块的src/jmh/java目录下,而不是src/main/java或src/test/java:
- core 模块:core/src/jmh/java/org/apache/iceberg(例如
ManifestReadBenchmark、ZOrderByteUtilsBenchmark、metrics/CountersBenchmark); - data 模块:data/src/jmh/java/org/apache/iceberg(例如
GenericParquetReaderBenchmark、GenericOrcReaderBenchmark、ReaderBenchmark); - Spark 模块:
spark/v3.3|v3.4|v3.5/spark/src/jmh/java/org/apache/iceberg/spark下,按source/avro、source/orc、source/parquet、source/parquet/vectorized、data/parquet等目录组织,分别对应不同的数据源与读写路径; - Flink 模块:
flink/v1.17|v1.18|v1.19/flink/src/jmh下也有对应 benchmark(如 flink/v1.19/flink/src/jmh)。
文档明确建议:只运行你关心的 benchmark,而不是一次性跑完所有测试。这是因为 JMH 基准测试本身耗时较长,且某些 benchmark 的数据集规模很大(例如单文件 1000 万行),全量运行会浪费大量计算资源。
1.2 两个重要的运行约定
关联文档特别强调两点,理解它们对解读结果至关重要:
- JMH benchmark 与被测系统运行在同一个 JVM 中。这意味着 JIT 编译、GC、类加载、线程调度等 JVM 内部行为会直接影响测量结果,因此不同运行之间结果可能有所波动;
- 结果应视为"变化趋势的指示器"而非绝对性能标尺。由于存在运行间波动,不应直接根据单次 benchmark 结果去推断生产环境中的选型决策。
此外,jmh.gradle 对运行环境还有硬性约束:
if (jdkVersion != '8' && jdkVersion != '11' && jdkVersion != '17') { throw new GradleException("The JMH benchmarks must be run with JDK 8 or JDK 11 or JDK 17") }即JMH 基准测试必须使用 JDK 8、JDK 11 或 JDK 17运行,其他 JDK 版本会直接抛出 GradleException。这与仓库 CI(GitHub Actions 使用zulu发行版 JDK 11)保持一致。
二、在 GitHub Actions 上运行 Iceberg JMH 基准测试
2.1 通过 "JMH Benchmarks" 工作流手动触发
Iceberg 提供了开箱即用的 GitHub Actions 工作流 .github/workflows/jmh-benchmarks.yml,你可以在自己 fork 的 Iceberg 仓库上手动触发(workflow_dispatch)。工作流需要提供三个输入参数:
| 输入参数 | 含义 | 示例 |
|---|---|---|
repo | 要运行基准测试的仓库名(含 owner) | apache/iceberg或<user>/iceberg |
ref | 要运行基准测试的分支名 | master或my-cool-feature-branch |
benchmarks | 逗号分隔的、带双引号的 Benchmark 类名列表 | "IcebergSourceFlatParquetDataReadBenchmark", "IcebergSourceFlatParquetDataFilterBenchmark" |
另有可选的spark_version输入,默认值为iceberg-spark-3.5,用于指定要运行的 Spark 项目版本(如iceberg-spark-3.5)。
工作流的执行逻辑如下:
- matrix 任务:先 checkout 指定仓库和分支,然后用
jq解析benchmarks输入,筛选出所有以Benchmark结尾的类名,构造一个运行矩阵; - run-benchmark 任务:对矩阵中的每一个 benchmark,在
ubuntu-22.04上执行:
./gradlew :iceberg-spark:<spark_version>:jmh \ -PjmhIncludeRegex=<Benchmark类名> \ -PjmhOutputPath=benchmark/<Benchmark类名>.txt- 上传结果:使用
actions/upload-artifact@v4在所有 benchmark 完成后(if: ${{ always() }},即使失败也会上传)把**/benchmark/*.txt作为名为benchmark-results的 artifact 上传。
工作流还做了两件环境准备:通过actions/setup-java@v4安装 Zulu JDK 11,并将容器内的eth0IP 与主机名写入/etc/hosts,以保证 Spark local 模式在 CI 环境中正常解析网络地址。
2.2 定时基准测试工作流
除了手动触发,仓库还维护了另一个定时工作流 .github/workflows/recurring-jmh-benchmarks.yml,通过 cron 表达式0 0 * * 0在每周日 00:00 UTC自动运行一组精选的 benchmark(仅当仓库 owner 为apache时生效)。其矩阵固定为iceberg-spark-3.5版本的 15 个 benchmark,涵盖 Parquet 读写、过滤器、删除文件(Eq/Pos/Multi/Unrelated Delete)等场景,且该工作流额外传入了-PjmhJsonOutputPath以同时输出 JSON 结果。
2.3 对 CI 结果的正确态度
关联文档明确提醒:GitHub Actions 的 runner 资源有限,因此:
- 结果只能作为帮助开发者理解代码变更的参考指标;
- 不同运行之间存在明显的结果波动性;
- 不应用 CI 结果来形成生产环境选型假设。
这正是 1.2 节所述"同 JVM 测量 + 资源受限"双重因素下的必然结论。
三、在本地运行 Iceberg JMH 基准测试
3.1 Gradle 属性与任务机制
本地运行的核心命令模式统一为:
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh \ -PjmhIncludeRegex=<Benchmark类名> \ -PjmhOutputPath=benchmark/<结果文件名>.txt其中:iceberg-spark:iceberg-spark[2|3]表示在 Spark 2 或 Spark 3 系列模块中选择对应的 Gradle 子项目(文档中的命令为泛化写法;实际执行时需要替换为具体版本,例如:iceberg-spark:iceberg-spark-3.5_2.12)。三个关键 Gradle 属性在 gradle.properties 中都有默认值:
| Gradle 属性 | 默认值 | 作用 |
|---|---|---|
jmhOutputPath | build/reports/jmh/human-readable-output.txt | JMH 人类可读文本结果输出路径 |
jmhJsonOutputPath | build/reports/jmh/results.json | JMH JSON 结果输出路径 |
jmhIncludeRegex | .* | 匹配要运行的 benchmark 的正则表达式 |
从 jmh.gradle 的配置可以看到任务的具体行为:
jmh { jmhVersion = '1.37' failOnError = true forceGC = true includeTests = true humanOutputFile = file(jmhOutputPath) resultsFile = file(jmhJsonOutputPath) resultFormat = 'JSON' includes = [jmhIncludeRegex] zip64 = true }要点解读:
- JMH 版本固定为 1.37;
failOnError = true:任何 benchmark 运行出错都会导致构建失败,避免静默吞掉错误;forceGC = true:每次迭代前强制执行 GC,降低 GC 噪声对测量的影响;- 结果同时输出人类可读文本(
humanOutputFile)和JSON(resultsFile,格式resultFormat = 'JSON'); - 任务执行完毕后,
tasks.jmh.finalizedBy tasks.jmhReport会自动生成 JMH 报告(HTML 形式,输出在 JSON 路径去掉.json后缀的目录中)。
另外,jmh.gradle会根据系统属性sparkVersions(默认取defaultSparkVersions)决定将哪些模块纳入 JMH 构建:3.3、3.4、3.5各自对应:iceberg-spark:iceberg-spark-X_<scalaVersion>与:iceberg-spark:iceberg-spark-extensions-X_<scalaVersion>两个项目。从源码注释可见,针对某个具体版本运行时可显式指定,例如:
./gradlew -DsparkVersions=3.5 :iceberg-spark:iceberg-spark-3.5_2.12:jmh \ -PjmhIncludeRegex=IcebergSourceFlatParquetDataReadBenchmark \ -PjmhOutputPath=benchmark/iceberg-source-flat-parquet-data-read-benchmark-result.txt3.2 Benchmark 公共配置注解
无论是 Spark source 类 benchmark 还是纯 Writer 类 benchmark,其 JMH 注解配置保持一致(可在 IcebergSourceBenchmark.java 与 SparkParquetWritersFlatDataBenchmark.java 中看到):
@Fork(1) // 单 fork,避免多次 JVM 启动开销 @State(Scope.Benchmark) // benchmark 级共享状态 @Warmup(iterations = 3) // 3 次预热迭代 @Measurement(iterations = 5) // 5 次正式测量迭代 @BenchmarkMode(Mode.SingleShotTime) // 单次执行计时模式Mode.SingleShotTime意味着每次迭代只执行一次被测方法并测量其耗时,适合数据规模大、单次执行耗时长的场景(如写 2000 万行数据)。所有被测方法均使用@Threads(1)单线程执行,以消除并发调度带来的干扰。
四、19 个本地 benchmark 逐个详解
以下按关联文档的顺序,完整列出所有本地 benchmark 的评测目标与运行命令。每个命令中[2|3]表示可在 Spark 2 或 Spark 3 系列模块中选择对应 Gradle 子项目执行;你也可以参照上文显式指定-DsparkVersions=3.5与iceberg-spark-3.5_2.12。
4.1 嵌套 List 结构 Parquet 写入
评测 Iceberg 与 Spark 内置 file source 在嵌套 List 数据 Parquet 写入上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceNestedListParquetDataWriteBenchmark -PjmhOutputPath=benchmark/iceberg-source-nested-list-parquet-data-write-benchmark-result.txt源码 IcebergSourceNestedListParquetDataWriteBenchmark.java 继承自 IcebergSourceNestedListDataBenchmark.java,后者定义了id+outerlist<struct<innerlist<list<string>>>>的嵌套 schema,并设置METADATA_COMPRESSION=gzip。被测方法通过@Param({"2000", "20000"})分别在 2000 行与 20000 行两个数据规模下,对比writeIceberg()(format("iceberg")追加写入)与writeFileSource()(设置 gzip 压缩后直接写 Parquet)两条路径。
4.2 Spark Parquet Readers 嵌套数据读取
评测 Iceberg 与 Spark Parquet reader 在嵌套 Parquet 数据读取上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=SparkParquetReadersNestedDataBenchmark -PjmhOutputPath=benchmark/spark-parquet-readers-nested-data-benchmark-result.txt源码位于 SparkParquetReadersNestedDataBenchmark.java(同目录下还有SparkParquetReadersFlatDataBenchmark),属于纯 reader 层对比:使用RandomData.generateSpark生成随机行,分别用 Iceberg 的Parquet.read(...).project(SCHEMA).createReaderFunc(...)与 Spark 的向量化 reader 读取同一份 Parquet 文件。
4.3 Spark Parquet Writers 扁平数据写入
评测 Iceberg 与 Spark Parquet writer 在扁平 schema Parquet 写入上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=SparkParquetWritersFlatDataBenchmark -PjmhOutputPath=benchmark/spark-parquet-writers-flat-data-benchmark-result.txt源码 SparkParquetWritersFlatDataBenchmark.java 定义了 8 列(long/int/float/double/decimal/date/timestamp/string)的扁平 schema,用RandomData.generateSpark生成 100 万条记录,对比:
writeUsingIcebergWriter():通过Parquet.write(...).createWriterFunc(...)传入SparkParquetWriters.buildWriter,走 Iceberg 的 Spark 写入适配层;writeUsingSparkWriter():通过Parquet.write(...).writeSupport(new ParquetWriteSupport())并设置spark.sql.parquet.writeLegacyFormat、outputTimestampType=TIMESTAMP_MICROS、fieldId.write.enabled=false等参数,模拟 Spark 原生写入路径。
4.4 Iceberg Source 扁平 ORC 数据读取
评测 Iceberg 与 Spark 内置 file source 在扁平 ORC 数据读取上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceFlatORCDataReadBenchmark -PjmhOutputPath=benchmark/iceberg-source-flat-orc-data-read-benchmark-result.txt源码 IcebergSourceFlatORCDataReadBenchmark.java 生成 10 个文件、每文件 100 万行的扁平数据集,对比readIceberg()(format("iceberg"))与readFileSource()(直接orc(dataLocation()))两条读取路径。同目录的 IcebergSourceFlatORCDataBenchmark.java 是共享基类,负责 ORC 表的创建与数据追加。
4.5 Spark Parquet Readers 扁平数据读取
评测 Iceberg 与 Spark Parquet reader 在扁平 Parquet 数据读取上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=SparkParquetReadersFlatDataBenchmark -PjmhOutputPath=benchmark/spark-parquet-readers-flat-data-benchmark-result.txt4.6 向量化读取字典编码的扁平 Parquet
对比 Iceberg向量化读取路径与 Spark 内置 file source 在字典编码扁平 Parquet上的读取性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=VectorizedReadDictionaryEncodedFlatParquetDataBenchmark -PjmhOutputPath=benchmark/vectorized-read-dict-encoded-flat-parquet-data-result.txt源码 VectorizedReadDictionaryEncodedFlatParquetDataBenchmark.java 继承自VectorizedReadFlatParquetDataBenchmark,差异在于:
setupBenchmark()调用setupSpark(true)开启字典编码(默认关闭字典编码,强制走 plain 编码);- 数据生成时对 long/int/float/double/decimal(18,5)/date/timestamp/string 各列用
pmod(id, 9)制造低基数值以触发字典编码;bigDecimalCol(decimal(20,5))在 Parquet v1 中以固定长度二进制存储,天然不适用字典编码,作为对照列保留。
4.7 嵌套 List 结构 ORC 写入
评测 Iceberg 与 Spark 内置 file source 在嵌套 List 数据 ORC 写入上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceNestedListORCDataWriteBenchmark -PjmhOutputPath=benchmark/iceberg-source-nested-list-orc-data-write-benchmark-result.txt源码 IcebergSourceNestedListORCDataWriteBenchmark.java 与 4.1 的 Parquet 版本结构对称,但额外包含三个方法:writeIceberg()(write-format=orc)、writeIcebergDictionaryOff()(通过表属性orc.dictionary.key.threshold=0关闭 ORC 字典编码后写入)以及writeFileSource()。
4.8 向量化读取扁平 Parquet
对比 Iceberg向量化读取路径与 Spark 内置 file source 在扁平 Parquet上的读取性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=VectorizedReadFlatParquetDataBenchmark -PjmhOutputPath=benchmark/vectorized-read-flat-parquet-data-result.txt源码 VectorizedReadFlatParquetDataBenchmark.java 是向量化基准的核心基类:
- 数据集规模为5 个文件 × 每文件 1000 万行(
NUM_FILES = 5,NUM_ROWS_PER_FILE = 10_000_000); - 表写入属性设置
METADATA_COMPRESSION=gzip与PARQUET_DICT_SIZE_BYTES=1(把字典页大小压到 1 字节,避免字典编码干扰); - 对 intCol/longCol/floatCol/doubleCol/decimalCol/bigDecimalCol/dateCol/timestampCol/stringCol9 种列类型分别提供一对方法:
readXxxIcebergVectorized5k()通过表属性开启 Iceberg 向量化(PARQUET_VECTORIZATION_ENABLED=true、PARQUET_BATCH_SIZE=5000),readXxxSparkVectorized5k()通过 Spark SQL 配置开启 Spark 向量化(spark.sql.parquet.enableVectorizedReader=true、批大小 5000)。
4.9 Iceberg Source 扁平 Parquet 写入
评测 Iceberg 与 Spark 内置 file source 在扁平 Parquet 写入上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceFlatParquetDataWriteBenchmark -PjmhOutputPath=benchmark/iceberg-source-flat-parquet-data-write-benchmark-result.txt4.10 Iceberg Source 嵌套 Avro 数据读取
评测 Iceberg 与 Spark 内置 file source 在嵌套 Avro 数据读取上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceNestedAvroDataReadBenchmark -PjmhOutputPath=benchmark/iceberg-source-nested-avro-data-read-benchmark-result.txt源码位于 iceberg-spark 的 avro 目录,其中IcebergSourceFlatAvroDataReadBenchmark.java采用DEFAULT_FILE_FORMAT+SPLIT_OPEN_FILE_COST=128MB的表属性组合,对比 Iceberg 读取与 Spark 直接读 Avro 的性能。
4.11 Iceberg Source 扁平 Avro 数据读取
评测 Iceberg 与 Spark 内置 file source 在扁平 Avro 数据读取上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceFlatAvroDataReadBenchmark -PjmhOutputPath=benchmark/iceberg-source-flat-avro-data-read-benchmark-result.txt4.12 Iceberg Source 嵌套 Parquet 写入
评测 Iceberg 与 Spark 内置 file source 在嵌套 Parquet 写入上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceNestedParquetDataWriteBenchmark -PjmhOutputPath=benchmark/iceberg-source-nested-parquet-data-write-benchmark-result.txt4.13 Iceberg Source 嵌套 Parquet 数据读取
评测 Iceberg 与 Spark 内置 file source 在嵌套 Parquet 数据读取上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceNestedParquetDataReadBenchmark -PjmhOutputPath=benchmark/iceberg-source-nested-parquet-data-read-benchmark-result.txt4.14 Iceberg Source 嵌套 ORC 数据读取
评测 Iceberg 与 Spark 内置 file source 在嵌套 ORC 数据读取上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceNestedORCDataReadBenchmark -PjmhOutputPath=benchmark/iceberg-source-nested-orc-data-read-benchmark-result.txt4.15 Iceberg Source 扁平 Parquet 数据读取
评测 Iceberg 与 Spark 内置 file source 在扁平 Parquet 数据读取上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceFlatParquetDataReadBenchmark -PjmhOutputPath=benchmark/iceberg-source-flat-parquet-data-read-benchmark-result.txt源码 IcebergSourceFlatParquetDataReadBenchmark.java 是理解读取基准实现的最佳范例:
- 数据为 10 个文件 × 每文件 100 万行的扁平 schema(long/int/float/double/decimal/date/timestamp/string 八列),通过
appendAsFile()逐文件写入 Iceberg 表; - 五个被测方法分别覆盖:
readIceberg()(Iceberg 全量读取)、readFileSourceVectorized()/readFileSourceNonVectorized()(Spark 向量化开/关的 file source 读取)、readWithProjectionIceberg()与readWithProjectionFileSource*()(只投影longCol一列的列裁剪读取); - 对比前会设置
SPLIT_OPEN_FILE_COST=128MB(Iceberg 侧)或spark.sql.files.openCostInBytes=128MB(Spark 侧),保证两者在文件合并策略上口径一致。
4.16 Iceberg Source 扁平 Parquet 过滤基准
评测Spark 数据源中 Iceberg 的 file skipping(文件跳过)能力。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceFlatParquetDataFilterBenchmark -PjmhOutputPath=benchmark/iceberg-source-flat-parquet-data-filter-benchmark-result.txt源码 IcebergSourceFlatParquetDataFilterBenchmark.java 是理解 Iceberg 元数据裁剪能力的关键基准:
- 数据集为 499 个文件 × 每文件 1 万行,
dateCol按文件序号递增(date_add(current_date(), fileNum)),使记录沿过滤谓词所用的列聚集; - 过滤条件固定为
FILTER_COND = "dateCol == date_add(current_date(), 1)",即只命中第 1 个文件; - 三个被测方法对比:
readWithFilterIceberg()依赖 Iceberg 元数据(manifest + partition stats)在读取前跳过 498 个文件;readWithFilterFileSourceVectorized()与readWithFilterFileSourceNonVectorized()则让 Spark file source 在列统计层面做 row-group 过滤,且不享受文件级跳过。
4.17 Iceberg Source 嵌套 Parquet 过滤基准
评测 Iceberg 数据源在嵌套数据上的 file skipping 能力。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=IcebergSourceNestedParquetDataFilterBenchmark -PjmhOutputPath=benchmark/iceberg-source-nested-parquet-data-filter-benchmark-result.txt与 4.16 逻辑一致,区别在于数据为嵌套 schema,且记录同样沿过滤谓词列聚集,用于验证嵌套结构下的文件跳过效果。
4.18 Spark Parquet Writers 嵌套数据写入
评测 Iceberg 与 Spark Parquet writer 在嵌套 Parquet 写入上的性能。
./gradlew :iceberg-spark:iceberg-spark[2|3]:jmh -PjmhIncludeRegex=SparkParquetWritersNestedDataBenchmark -PjmhOutputPath=benchmark/spark-parquet-writers-nested-data-benchmark-result.txt4.19 关于结果输出
上述命令中-PjmhOutputPath指定的文本文件即为 JMH 的人类可读结果;同时默认会在build/reports/jmh/results.json输出 JSON 结果,并自动生成 HTML 报告。如果你想用 recurring-jmh-benchmarks.yml 的方式把结果落到指定目录,可追加-PjmhJsonOutputPath=benchmark/<名称>.json参数。
五、更多进阶素材:删除文件与 Writer 层基准
关联文档列出的 19 个命令之外,仓库的 jmh 目录还沉淀了更多同体系基准,可作为深入阅读的入口:
- 删除文件系列(位于 spark/v3.5/spark/src/jmh/java/org/apache/iceberg/spark/source/parquet):
IcebergSourceParquetEqDeleteBenchmark(equality delete)、IcebergSourceParquetPosDeleteBenchmark(position delete)、IcebergSourceParquetMultiDeleteFileBenchmark(多删除文件)、IcebergSourceParquetWithUnrelatedDeleteBenchmark(无关删除文件),均已在每周定时工作流中运行; - Writer 层基准WritersBenchmark.java:直接对比
ClusteredDataWriter、FanoutDataWriter、UnpartitionedWriter、SparkPartitionedWriter等 Iceberg 写入器在分区分桶(bucket(32))与未分区两种 spec 下的表现,还覆盖ClusteredEqualityDeleteWriter、ClusteredPositionDeleteWriter(PARTITION/FILE 两种DeleteGranularity)与FanoutPositionOnlyDeleteWriter(含 shuffle 与未 shuffle 两种位置删除顺序); - core/data 模块基准:如 core/src/jmh/java/org/apache/iceberg/ManifestReadBenchmark.java(manifest 读取)、data/src/jmh/java/org/apache/iceberg/GenericParquetReaderBenchmark.java(通用 Parquet reader)。
六、结语与最佳实践建议
综合关联文档与源码实现,使用 Iceberg JMH 基准测试时建议遵循以下原则:
- 按需运行:用
-PjmhIncludeRegex=<类名>精确指定单个 benchmark,避免全量运行浪费算力; - 固定环境:必须使用 JDK 8/11/17(jmh.gradle 强制校验);尽量在相同机器、相同数据规模下对比多次运行,观察趋势而非绝对值;
- 理解口径:多数 benchmark 是"一对多"设计(一个 Iceberg 路径对比 Spark file source 的向量化/非向量化路径),且通过
SPLIT_OPEN_FILE_COST与spark.sql.files.openCostInBytes等参数对齐比较口径; - CI 结果仅作参考:GitHub Actions runner 资源受限,其结果适合辅助代码评审与变更分析,不应直接用于生产选型决策;
- 结合 JSON 与报告:文本结果便于快速阅读,
results.json与自动生成的 HTML 报告便于长期留存和横向对比。
通过本地命令或 fork 上的 JMH 工作流,你可以随时复现上述任一基准,将性能指标纳入 Iceberg 的日常开发与优化循环中。
- 数据湖
- 湖仓一体
- 大数据
【免费下载链接】iceberg
Apache Iceberg
相关推荐
Apache Iceberg JMH 基准测试完全指南:本地运行与 GitHub Actions 实战
Apache Iceberg JMH 基准测试完全指南:本地运行与 GitHub Actions 实战 本指南系统讲解 Apache Iceberg 仓库内置的
数据湖大数据数据存储GraalVM GraalWasm 测试与基准测试完全指南:从基础测试套件到 JMH 基准测试
GraalVM GraalWasm 测试与基准测试完全指南:从基础测试套件到 JMH 基准测试 本文基于 GraalVM 仓库中 wasm/docs/contr
编译器JIT编译语言运行时高性能计算内存管理Apache Kafka JMH 基准测试模块(jmh-benchmarks)实战指南:运行、调参与编写微基准
Apache Kafka JMH 基准测试模块(jmh benchmarks)实战指南:运行、调参与编写微基准 本文以 Apache Kafka 仓库中的 jm
消息队列流处理数据集成存储
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考