liurenjie1024 commented on code in PR #18709:
URL: https://github.com/apache/iceberg/pull/18709#discussion_r4533699738


##########
spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/source/TestSparkReadMetrics.java:
##########
@@ -44,6 +61,180 @@ public class TestSparkReadMetrics extends 
TestBaseWithCatalog {
   @AfterEach
   public void removeTables() {
     sql("DROP TABLE IF EXISTS %s", tableName);
+    sql("DROP TABLE IF EXISTS dim");
+  }
+
+  @TestTemplate
+  void effectiveSplitTargetSize() throws NoSuchTableException, IOException {
+    long tableSplitSize = 128L * 1024 * 1024;
+    long optionSplitSize = 32L * 1024 * 1024;
+    int parallelism = 1000;
+    sql(
+        "CREATE TABLE %s (id BIGINT) USING iceberg TBLPROPERTIES 
('read.split.target-size'='%s')",
+        tableName, tableSplitSize);
+    spark.range(100).coalesce(1).writeTo(tableName).append();
+
+    long scanSize = 0;
+    try (CloseableIterable<FileScanTask> tasks =
+        validationCatalog.loadTable(tableIdent).newScan().planFiles()) {
+      for (FileScanTask task : tasks) {
+        scanSize += task.sizeBytes();
+      }
+    }
+    long adaptiveSplitSize = TableScanUtil.adjustSplitSize(scanSize, 
parallelism, tableSplitSize);
+    assertThat(adaptiveSplitSize).isNotEqualTo(tableSplitSize);
+
+    // adaptive sizing lowers the table target for a small scan
+    withSQLConf(
+        ImmutableMap.of(
+            SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED,
+            "true",
+            SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_PARALLELISM,
+            String.valueOf(parallelism)),
+        () -> {
+          Dataset<Row> df = spark.sql(String.format("SELECT * FROM %s", 
tableName));
+          df.collect();
+          SparkPlan scan = 
df.queryExecution().executedPlan().collectLeaves().head();
+          
assertThat(scan.metrics().get("effectiveSplitTargetSize").get().value())
+              .isEqualTo(adaptiveSplitSize);
+        });
+
+    // without adaptive sizing, the table property is the target
+    withSQLConf(
+        ImmutableMap.of(SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED, 
"false"),
+        () -> {
+          Dataset<Row> df = spark.sql(String.format("SELECT * FROM %s", 
tableName));
+          df.collect();
+          SparkPlan scan = 
df.queryExecution().executedPlan().collectLeaves().head();
+          
assertThat(scan.metrics().get("effectiveSplitTargetSize").get().value())
+              .isEqualTo(tableSplitSize);
+        });
+
+    // an explicit read option is used as is, even with adaptive sizing enabled
+    withSQLConf(
+        ImmutableMap.of(SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED, 
"true"),
+        () -> {
+          Dataset<Row> df =
+              spark
+                  .read()
+                  .format("iceberg")
+                  .option(SparkReadOptions.SPLIT_SIZE, 
String.valueOf(optionSplitSize))
+                  .load(tableName);
+          df.collect();
+          SparkPlan scan = 
df.queryExecution().executedPlan().collectLeaves().head();
+          
assertThat(scan.metrics().get("effectiveSplitTargetSize").get().value())
+              .isEqualTo(optionSplitSize);
+        });
+  }
+
+  @TestTemplate
+  void effectiveSplitTargetSizeWithoutSnapshot() {

Review Comment:
   ```suggestion
     void effectiveSplitTargetSizeWithoutData() {
   ```



##########
spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/source/TestSparkReadMetrics.java:
##########
@@ -44,6 +61,180 @@ public class TestSparkReadMetrics extends 
TestBaseWithCatalog {
   @AfterEach
   public void removeTables() {
     sql("DROP TABLE IF EXISTS %s", tableName);
+    sql("DROP TABLE IF EXISTS dim");
+  }
+
+  @TestTemplate
+  void effectiveSplitTargetSize() throws NoSuchTableException, IOException {
+    long tableSplitSize = 128L * 1024 * 1024;
+    long optionSplitSize = 32L * 1024 * 1024;
+    int parallelism = 1000;
+    sql(
+        "CREATE TABLE %s (id BIGINT) USING iceberg TBLPROPERTIES 
('read.split.target-size'='%s')",
+        tableName, tableSplitSize);
+    spark.range(100).coalesce(1).writeTo(tableName).append();
+
+    long scanSize = 0;
+    try (CloseableIterable<FileScanTask> tasks =
+        validationCatalog.loadTable(tableIdent).newScan().planFiles()) {
+      for (FileScanTask task : tasks) {
+        scanSize += task.sizeBytes();
+      }
+    }
+    long adaptiveSplitSize = TableScanUtil.adjustSplitSize(scanSize, 
parallelism, tableSplitSize);
+    assertThat(adaptiveSplitSize).isNotEqualTo(tableSplitSize);
+
+    // adaptive sizing lowers the table target for a small scan
+    withSQLConf(
+        ImmutableMap.of(
+            SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED,
+            "true",
+            SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_PARALLELISM,
+            String.valueOf(parallelism)),
+        () -> {
+          Dataset<Row> df = spark.sql(String.format("SELECT * FROM %s", 
tableName));
+          df.collect();
+          SparkPlan scan = 
df.queryExecution().executedPlan().collectLeaves().head();
+          
assertThat(scan.metrics().get("effectiveSplitTargetSize").get().value())
+              .isEqualTo(adaptiveSplitSize);
+        });
+
+    // without adaptive sizing, the table property is the target
+    withSQLConf(
+        ImmutableMap.of(SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED, 
"false"),
+        () -> {
+          Dataset<Row> df = spark.sql(String.format("SELECT * FROM %s", 
tableName));
+          df.collect();
+          SparkPlan scan = 
df.queryExecution().executedPlan().collectLeaves().head();
+          
assertThat(scan.metrics().get("effectiveSplitTargetSize").get().value())
+              .isEqualTo(tableSplitSize);
+        });
+
+    // an explicit read option is used as is, even with adaptive sizing enabled
+    withSQLConf(
+        ImmutableMap.of(SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED, 
"true"),
+        () -> {
+          Dataset<Row> df =
+              spark
+                  .read()
+                  .format("iceberg")
+                  .option(SparkReadOptions.SPLIT_SIZE, 
String.valueOf(optionSplitSize))
+                  .load(tableName);
+          df.collect();
+          SparkPlan scan = 
df.queryExecution().executedPlan().collectLeaves().head();
+          
assertThat(scan.metrics().get("effectiveSplitTargetSize").get().value())
+              .isEqualTo(optionSplitSize);
+        });
+  }
+
+  @TestTemplate
+  void effectiveSplitTargetSizeWithoutSnapshot() {
+    sql("CREATE TABLE %s (id BIGINT) USING iceberg", tableName);
+
+    // no task groups are planned for a table without a snapshot

Review Comment:
   ```suggestion
       // no task groups are planned for a table without data
   ```



##########
spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/source/TestSparkReadMetrics.java:
##########
@@ -46,6 +52,80 @@ public void removeTables() {
     sql("DROP TABLE IF EXISTS %s", tableName);
   }
 
+  @TestTemplate
+  public void testEffectiveSplitTargetSize() throws NoSuchTableException {
+    sql(
+        "CREATE TABLE %s (id BIGINT) USING iceberg TBLPROPERTIES 
('read.split.target-size'='134217728')",
+        tableName);
+    spark.range(100).coalesce(1).writeTo(tableName).append();
+
+    withSQLConf(
+        ImmutableMap.of(
+            SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED,
+            "true",
+            SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_PARALLELISM,
+            "1000"),
+        () -> assertEffectiveSplitTargetSize(16L * 1024 * 1024));
+
+    withSQLConf(
+        ImmutableMap.of(SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED, 
"false"),
+        () -> assertEffectiveSplitTargetSize(128L * 1024 * 1024));
+
+    withSQLConf(
+        ImmutableMap.of(SparkSQLProperties.READ_ADAPTIVE_SPLIT_SIZE_ENABLED, 
"true"),
+        () -> {
+          Dataset<Row> df =
+              spark
+                  .read()
+                  .format("iceberg")
+                  .option(SparkReadOptions.SPLIT_SIZE, String.valueOf(32L * 
1024 * 1024))
+                  .load(tableName);
+          assertEffectiveSplitTargetSize(df, 32L * 1024 * 1024);
+        });
+  }
+
+  @TestTemplate
+  public void testCustomMetricsAreInstantiableBySpark() {

Review Comment:
   I'm not quite convinced, I think uts should focus on expected behavior, not 
too much internal mechanism, a metric class that should be loadable is an 
internal detail, not an external user facing behavior. Even if we plan to add 
it, it should not be included in this pr.



##########
spark/v4.2/spark/src/test/java/org/apache/iceberg/spark/source/TestSparkReadMetrics.java:
##########
@@ -46,6 +52,80 @@ public void removeTables() {
     sql("DROP TABLE IF EXISTS %s", tableName);
   }
 
+  @TestTemplate
+  public void testEffectiveSplitTargetSize() throws NoSuchTableException {

Review Comment:
   Why? I think we should align with other tests?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to