jackylee-ch commented on PR #12549:
URL: https://github.com/apache/gluten/pull/12549#issuecomment-5572604619

   One more pass, this time asking only "does the new machinery itself have a 
defect I can trigger" rather than "is a conf classified right". It found a 
silent wrong-results bug that all four earlier passes missed, fixed in 
`9c436b2bb`.
   
   ### `spark.sql.mapKeyDedupPolicy=exception` silently disabled the 
duplicate-key error
   
   Spark's own entry declares an upper-casing transform 
(`spark-catalyst_2.12-3.5.5-sources`, `SQLConf.scala:3785-3794`) and native 
compares the delivered value against the literal `"EXCEPTION"` 
(`WholeStageResultIterator.cc:660-664`). Base delivered the raw string, so:
   
   ```sql
   SET spark.sql.mapKeyDedupPolicy=exception;   -- Spark accepts this and 
normalizes it
   SELECT map(1, 'a', 1, 'b');              -- vanilla Spark: raises. Gluten: 
returns {1 -> 'b'}
   ```
   
   because native fell into the `else` branch and set 
`kThrowExceptionOnDuplicateMapKeys=false`. Pre-existing in base, and I 
reproduced the same omission in the first version of this PR — which is the 
annoying part, because the two sibling declarations in the same block already 
guard against exactly this: `spark.sql.legacy.timeParserPolicy` upper-cases, 
and `spark.io.compression.codec` lower-cases (added two commits ago for the 
same reason). The contract in `ConfigBuilder.scala` says "a foreign conf 
declares the same converter Spark / Hadoop declares"; this one did not.
   
   ### `spark.shuffle.file.buffer` lost its only validating reader — and native 
was prefix-parsing
   
   This PR deletes the JVM-side `conf.get(SHUFFLE_FILE_BUFFER_SIZE)` that used 
to run Spark's converter *and* its `checkValue` (cap `MAX_ROUNDED_ARRAY_LENGTH 
/ 1024` = 2097151 KiB). Nothing replaced it, and `std::stoll` stops at the 
first character it cannot use without erroring. Combined with 
`convertForNative` deliberately delivering a value the converter rejected as 
the raw string, that gave:
   
   | conf value | JVM delivers | native computed | intended |
   |---|---|---|---|
   | `1.5m` | `"1.5m"` (unparseable, passed through) | **1024 bytes** | 1572864 
|
   | `10x` | `"10x"` (invalid suffix) | **10240 bytes** | rejected by Spark |
   | `4194304` | `"4194304"` | **4 GiB per open file**, from an arrow pool 
Spark does not track | rejected by Spark |
   
   The first two did not even log — the `catch` never ran. Fixed both ends: the 
declaration now carries Spark's bound as well as its unit, and 
`createPartitionWriter` requires `stoll` to consume the whole string and 
enforces the same bound, falling back to `kDefaultShuffleFileBufferSize` with a 
warning otherwise.
   
   ### Cleared, for the record
   
   The same pass checked and could not instantiate: a class-init deadlock or 
premature-`val` read in the conf objects (the reference graph is a DAG, and 
`registerNativeConfs()` is the last statement of `GlutenConfig`'s body); an 
exception escaping `selectRuntimeConf` / `selectBackendConf` (every converter 
reachable from `convertForNative` throws only `IllegalArgumentException` or its 
`NumberFormatException` subclass, both caught); a lost registration through the 
`backendConfDelivered` latch (every conf object holding a `passToNative` conf 
is force-initialized on the single-threaded plugin-init path first, and the two 
registries not in any `confs()` override declare none); and default 
round-tripping for all five terminal methods.
   
   One low-severity item I documented rather than fixed: the SQLConf mirror for 
`spark.gluten.sql.columnar.shuffle.codec` now carries a default of `lz4`, so 
`spark.conf.get` and `SET -v` report `lz4` even when 
`spark.io.compression.codec=zstd` makes the effective codec zstd. Only the 
*reported* value is wrong — every Gluten read goes through the entry, which 
resolves the fallback correctly. Base reported the key as unset. Expressing it 
properly needs a Spark-side fallback entry, which `private[spark]` puts out of 
reach; if you would rather it report nothing than report `lz4`, that is a 
one-line change back to `createOptional` plus a `None` branch at the two call 
sites.
   
   @zhztheplayer @philo-he @weiting-chen @zhouyuan — that is the last of the 
self-review; nothing outstanding from my side beyond the two design questions I 
put to you above (`ConfigEntryForeignFallback`, and whether the session-scoped 
`spark.io.compression.codec` inheritance should stay).


-- 
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