Copilot commented on code in PR #3739:
URL: https://github.com/apache/celeborn/pull/3739#discussion_r3593117838


##########
client/src/main/scala/org/apache/celeborn/client/ApplicationHeartbeater.scala:
##########
@@ -47,6 +47,11 @@ class ApplicationHeartbeater(
   private var stopped = false
   private val reviseLostShuffles = conf.reviseLostShufflesEnabled
 
+  private val gcOnOverloadEnabled = conf.clientGcOnOverloadEnabled
+  private val gcOnOverloadMinIntervalMs = conf.clientGcOnOverloadMinIntervalMs
+  private val gcOnOverloadMinIntervalNs = gcOnOverloadMinIntervalMs * 1000000L
+  @volatile private var lastGcTriggerTimeNs = 0L
+

Review Comment:
   `gcOnOverloadMinIntervalNs` is computed via `gcOnOverloadMinIntervalMs * 
1000000L`, which can overflow for large intervals, and the class doesn't expose 
any `lastGcTriggerTimeMs` value even though the new unit test expects it. Use 
`TimeUnit.MILLISECONDS.toNanos(...)` for conversion and add a package-visible 
`lastGcTriggerTimeMs` that tests can read.



##########
master/src/main/scala/org/apache/celeborn/service/deploy/master/quota/QuotaManager.scala:
##########
@@ -141,6 +153,23 @@ class QuotaManager(
     checkQuotaSpace(CLUSTER_EXHAUSTED, consumption, getClusterStorageQuota)
   }
 
+  // Calling the cluster overloaded (leads to gc triggers on app side to 
relieve storage)
+  private def checkClusterOverloaded(consumption: ResourceConsumption): 
Boolean = {
+    val overloadQuota = getClusterStorageQuota
+    val factor = getClusterOverloadLimitFactor
+    def scale(q: Long): Long = {
+      if (q <= 0L || q == Long.MaxValue) q
+      else math.max(1L, math.ceil(factor * q.toDouble).toLong)
+    }
+
+    val threshold = StorageQuota(
+      diskBytesWritten = scale(overloadQuota.diskBytesWritten),
+      diskFileCount = scale(overloadQuota.diskFileCount),
+      hdfsBytesWritten = scale(overloadQuota.hdfsBytesWritten),
+      hdfsFileCount = scale(overloadQuota.hdfsFileCount))
+    checkConsumptionExceeded(consumption, threshold)
+  }

Review Comment:
   `checkClusterOverloaded` can report overload permanently if any cluster 
quota dimension is configured as 0 (often used to mean "disabled"), because 
`scale` keeps `q <= 0` as 0 and `checkConsumptionExceeded` uses `>=` without a 
`> 0` guard. This would cause `shouldTriggerGc` to be true continuously even 
when the cluster isn't actually constrained. Consider treating non-positive 
thresholds as "ignored" in overload checks.



##########
client/src/main/scala/org/apache/celeborn/client/ApplicationHeartbeater.scala:
##########
@@ -170,6 +176,21 @@ class ApplicationHeartbeater(
     }
   }
 
+  private[client] def handleGcSignal(shouldTriggerGc: Boolean): Unit = {
+    if (!gcOnOverloadEnabled || !shouldTriggerGc) return
+    val nowNs = System.nanoTime()
+    if (nowNs - lastGcTriggerTimeNs >= gcOnOverloadMinIntervalNs) {
+      logInfo(
+        "Cluster is overloaded; triggering System.gc() to release stale 
shuffle dependencies.")
+      lastGcTriggerTimeNs = nowNs
+      System.gc()

Review Comment:
   When GC is triggered, only `lastGcTriggerTimeNs` is updated. The new unit 
test asserts on `lastGcTriggerTimeMs`, so it should be set at the same time as 
the successful GC trigger (using `System.currentTimeMillis()`), and remain 
unchanged when the signal is skipped.



##########
docs/configuration/master.md:
##########
@@ -37,6 +37,7 @@ license: |
 | celeborn.internal.port.enabled | false | false | Whether to create a 
internal port on Masters/Workers for inter-Masters/Workers communication. This 
is beneficial when SASL authentication is enforced for all interactions between 
clients and Celeborn Services, but the services can exchange messages without 
being subject to SASL authentication. | 0.5.0 |  | 
 | celeborn.logConf.enabled | false | false | When `true`, log the CelebornConf 
for debugging purposes. | 0.5.0 |  | 
 | celeborn.master.allowWorkerHostPattern | &lt;undefined&gt; | false | Pattern 
of worker host that allowed to register with the master. If not set, all 
workers are allowed to register. | 0.6.0 |  | 
+| celeborn.master.clusterOverload.gc.enabled | false | false | Whether to 
enable the master signaling clients to trigger GC when the cluster storage is 
overloaded (disk usage exceeds the threshold). | 0.7.0 |  | 

Review Comment:
   This description says overload is based on "disk usage", but the 
implementation triggers overload when *any* configured cluster quota dimension 
(disk bytes/files, HDFS bytes/files) crosses the overload threshold. Updating 
the text will prevent operator confusion when overload is driven by non-disk 
dimensions.



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

Reply via email to