
Apache Gluten单元测试指南如何为原生引擎编写可靠测试用例【免费下载链接】glutenGluten is a middle layer responsible for offloading JVM-based SQL engines execution to native engines.项目地址: https://gitcode.com/GitHub_Trending/glu/glutenApache Gluten作为JVM-based SQL引擎与原生执行引擎之间的中间层其单元测试对于确保查询执行的正确性和性能至关重要。本文将详细介绍如何为Gluten原生引擎编写可靠的测试用例涵盖测试环境搭建、测试框架使用、关键测试类型及最佳实践帮助开发者快速上手单元测试开发。单元测试在Gluten中的重要性Gluten通过Substrait协议将Spark执行计划转换为原生引擎如Velox、ClickHouse可执行的计划单元测试需验证这一转换过程的准确性、数据处理的正确性以及性能表现。可靠的单元测试能够确保原生引擎正确执行SQL算子逻辑提前发现跨引擎数据类型转换问题验证内存管理和资源释放的有效性保障不同Spark版本和原生后端的兼容性Gluten的测试代码主要分布在以下目录gluten-ut/包含针对不同Spark版本的单元测试backends-clickhouse/src/test/ClickHouse后端测试backends-velox/src/test/Velox后端测试cpp/velox/tests/C层原生执行测试测试环境搭建1. 基础环境准备首先需要构建Gluten项目及测试相关组件# 克隆仓库 git clone https://gitcode.com/GitHub_Trending/glu/gluten cd gluten # 构建Velox后端并开启测试选项 ./dev/buildbundle-veloxbe.sh --build_testsON --build_benchmarksON # 生成测试所需的Parquet数据和Substrait计划文件 mvn test -Pspark-3.5 -Pbackends-velox -pl backends-velox \ -am -DtagsToIncludeorg.apache.gluten.tags.GenerateExample \ -Dtestnone -DfailIfNoTestsfalse -Dexec.skip生成的测试文件位于backends-velox/generated-native-benchmark/目录包含plan_{stageId}_{partitionId}_{vId}.jsonSubstrait执行计划data_{stageId}_{partitionId}_{vId}_{iteratorIdx}.parquet输入测试数据conf_{stageId}_{partitionId}_{vId}.ini测试配置文件2. 测试配置与依赖Gluten提供了统一的测试基类GlutenSQLTestsBaseTrait位于gluten-ut/common/src/test/scala/org/apache/spark/sql/GlutenSQLTestsBaseTrait.scala该类预设了测试所需的Spark配置// 关键测试配置 .set(spark.plugins, org.apache.gluten.GlutenPlugin) .set(spark.shuffle.manager, org.apache.spark.shuffle.sort.ColumnarShuffleManager) .set(spark.sql.adaptive.enabled, true) .set(spark.memory.offHeap.enabled, true) .set(spark.memory.offHeap.size, 1024MB)通过继承该Trait可以快速搭建测试环境并获取预配置的SparkSession。核心测试类型与实现方法1. SQL查询结果验证测试这类测试验证Gluten执行SQL查询的结果是否与Spark原生执行一致是最基础也最重要的测试类型。典型实现如下class GlutenDataFrameAggregateSuite extends GlutenSQLTestsTrait { test(test aggregate function sum) { val df spark.createDataFrame(Seq((1, a), (2, b), (3, a))) .toDF(id, name) // Gluten执行结果 val glutenResult df.groupBy(name).sum(id).orderBy(name).collect() // 禁用Gluten的基准结果 withSQLConf(GlutenConfig.GLUTEN_ENABLED.key - false) { val sparkResult df.groupBy(name).sum(id).orderBy(name).collect() assert(glutenResult sameElements sparkResult) } } }Gluten提供了GlutenSQLTestsTrait测试特质自动处理测试前后的环境切换确保测试的隔离性。2. 执行计划验证测试验证Spark计划是否被正确转换为原生执行计划确保算子下推和优化的正确性test(validate columnar execution plan) { val df spark.sql(SELECT id, count(*) FROM test_table GROUP BY id) val executedPlans getExecutedPlan(df) // 验证是否生成了ColumnarShuffleExchange assert(executedPlans.exists(_.nodeName.contains(ColumnarShuffleExchange))) // 验证Aggregate算子是否下推到原生引擎 assert(executedPlans.exists(_.nodeName.contains(ColumnarAggregate))) }getExecutedPlan方法定义于GlutenSQLTestsBaseTrait可提取DataFrame的执行计划树便于验证计划转换结果。3. 原生引擎C层测试对于C实现的核心逻辑可使用Google Test框架直接测试例如Velox后端的内存管理测试TEST(MemoryManagerTest, TestMemoryAllocation) { auto memoryManager std::make_sharedVeloxMemoryManager(); auto pool memoryManager-getPool(); // 测试内存分配 auto buffer pool-allocateuint8_t(1024); ASSERT_NE(buffer.get(), nullptr); ASSERT_EQ(buffer-size(), 1024); // 测试内存限制 memoryManager-setMemoryLimit(2048); ASSERT_THROW(pool-allocateuint8_t(3072), std::bad_alloc); }C测试可通过以下命令单独运行cd cpp/build/velox/tests ./velox_tests --gtest_filterMemoryManagerTest.*4. 性能基准测试使用Gluten提供的基准测试框架验证原生执行性能位于cpp/velox/benchmarks/目录。以TPCH Q5查询为例# 运行TPCH Q5基准测试 ./generic_benchmark \ --plan ../data/generic_q5/q5_first_stage_0.json \ --split ../data/generic_q5/q5_first_stage_0_split.json \ --with-shuffle --threads 8 --iterations 10基准测试会输出详细的性能指标包括执行时间、内存使用和算子耗时帮助评估优化效果。图TPCH Q5查询的第一阶段执行计划展示了Gluten如何将SQL转换为原生执行算子测试结果分析与调试1. 测试报告解读Gluten使用Surefire插件生成详细的测试报告包含测试用例执行情况、失败原因和性能数据。典型的测试报告界面如下图Gluten单元测试报告示例显示测试总数、跳过数和失败数以及详细的失败原因报告中会高亮显示失败的测试用例并提供完整的错误堆栈信息便于定位问题。2. 调试技巧1Java/Scala层调试使用IntelliJ IDEA远程调试Spark测试export SPARK_SUBMIT_OPTS-agentlib:jdwptransportdt_socket,servery,suspendy,address8008 mvn test -Pspark-3.5 -Pbackends-velox -DwildcardSuitesGlutenDataFrameAggregateSuite在IDEA中配置远程调试连接到8008端口即可断点调试。2C层调试使用GDB调试原生执行逻辑gdb cpp/build/velox/benchmarks/generic_benchmark (gdb) b VeloxBackend.cc:50 # 在Velox后端初始化处设置断点 (gdb) r --plan /path/to/plan.json --data /path/to/data.parquet通过bt命令查看调用栈p命令打印变量值定位C代码中的问题。3执行计划调试开启调试模式输出Substrait计划mvn test -Pspark-3.5 -Pbackends-velox -Dspark.gluten.sql.debugtrue生成的JSON格式计划可通过Substrait可视化工具进行分析验证计划转换的正确性。测试最佳实践1. 测试用例设计原则原子性每个测试用例只验证一个功能点便于定位问题可重复性测试数据固定确保每次运行结果一致覆盖全面覆盖不同数据类型、边界条件和异常场景性能平衡单元测试应快速执行避免过度复杂的数据集2. 常用测试工具与框架ScalaTest用于Scala层测试提供丰富的断言和测试风格Google TestC层单元测试框架支持参数化测试和测试夹具BenchmarkGoogle Benchmark框架用于性能基准测试SurefireMaven插件生成统一的测试报告3. CI集成Gluten的CI流程会自动运行所有单元测试确保代码质量。开发者提交PR前应本地运行# 运行所有单元测试 mvn test -Pspark-3.5 -Pbackends-velox -Pspark-ut # 运行特定模块测试 mvn test -Pspark-3.5 -pl gluten-ut/spark35总结编写可靠的单元测试是保障Gluten原生引擎质量的关键环节。本文介绍了Gluten单元测试的环境搭建、核心测试类型、实现方法和调试技巧涵盖从SQL层到C原生层的全栈测试。通过遵循本文所述的最佳实践开发者可以有效验证Gluten的功能正确性和性能表现为SQL引擎的原生加速提供坚实保障。Gluten的测试框架持续演进更多测试工具和用例可参考官方测试文档和测试示例代码。【免费下载链接】glutenGluten is a middle layer responsible for offloading JVM-based SQL engines execution to native engines.项目地址: https://gitcode.com/GitHub_Trending/glu/gluten创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考