dwsmith1983 commented on code in PR #5615:
URL: https://github.com/apache/datafusion-comet/pull/5615#discussion_r3924448154


##########
spark/src/main/scala/org/apache/spark/sql/comet/operators.scala:
##########
@@ -136,9 +230,52 @@ private[comet] object PlanDataInjector extends Logging {
    * reference rather than rebuilt; only the root-to-scan paths are rebuilt.
    */
   def injectPlanData(
+      op: Operator,
+      commonByKey: Map[String, Array[Byte]],
+      partitionByKey: Map[String, Array[Byte]]): Operator =
+    injectPlanData(op, commonByKey, partitionByKey, null)
+
+  /**
+   * Injects planning data into a cached base plan, memoizing each scan's 
prepared common inside
+   * the plan's own cache entry so it is prepared once per stage rather than 
once per task.
+   */
+  def injectPlanData(
+      cachedPlan: CachedPlanData,
+      commonByKey: Map[String, Array[Byte]],
+      partitionByKey: Map[String, Array[Byte]]): Operator =
+    injectPlanData(cachedPlan.plan, commonByKey, partitionByKey, 
cachedPlan.preparedCommons)
+
+  // The native shuffle writer's unified plan differs per task (output paths), 
so those plans
+  // never pass through parseBasePlan. Prepared commons for that path are 
scoped to the
+  // shuffleId instead: one shuffle stage's scans still share a single 
eviction unit.
+  private val shufflePreparedCommons = java.util.Collections.synchronizedMap(
+    new LinkedHashMap[Integer, ConcurrentHashMap[String, PreparedCommon]](4, 
0.75f, true) {

Review Comment:
   Fixed in f24e4fcc6, at both boundaries you named. unregisterShuffle now 
releases that shuffle's prepared commons in both managers, which is the precise 
lifetime (verified the ContextCleaner path in the 3.5.9 bytecode: 
doCleanupShuffle to BlockManagerStorageEndpoint RemoveShuffle to 
ShuffleManager.unregisterShuffle, and neither Comet manager delegates that call 
away), and stop() clears the whole store as the safety net for recreated 
contexts. Your reused-id scenario is the regression: two manager instances with 
a stop between them, shuffle 0 holds exactly the second context's keys instead 
of four. There is also a real SparkContext suite that runs a native shuffle, 
proves the cleaner path releases the entry, stops the context, recreates a 
session, and asserts the store holds only the new context's keys. The base plan 
cache is left alone deliberately since it is keyed by plan bytes rather than a 
per-context counter, so a recreated context either hits or evicts through the 
existing bo
 und. One residual note: a straggling map task calling injection after 
unregister would re-insert an empty inner map for that id, bounded by the outer 
LRU and cleared on stop, so I did not add a tombstone.



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