github-actions[bot] commented on code in PR #67845:
URL: https://github.com/apache/doris/pull/67845#discussion_r4227415389


##########
be/src/runtime/workload_group/workload_group_manager.cpp:
##########
@@ -602,14 +603,33 @@ bool WorkloadGroupMgr::handle_process_memory_exceeded_(
         return false;
     }
 
+    // The process memory pressure may have been relieved by cache reclamation 
or by other
+    // queries that finished. Check it before routing the query below, 
otherwise a query in a
+    // workload group that uses less than its min memory limit has to wait for 
the timeout.
+    // Test the recorded reservation itself: this is the predicate the failed 
reservation used,
+    // so the query is resumed exactly when its request fits now.
+    if 
(!GlobalMemoryArbitrator::is_exceed_soft_mem_limit(query_it->reserve_size_)) {
+        LOG(INFO) << "Query: " << 
print_id(resource_ctx->task_controller()->task_id())

Review Comment:
   [P2] Preserve the deadline for all pending reservations of a query. Two 
pipeline tasks can fail process reservations before this pass, but 
`PausedQuerySet` retains only the first `reserve_size_` for their shared query 
ID. If a 4 MiB failure is recorded before a 64 MiB sibling failure, 16 MiB of 
recovered headroom passes this check and wakes both tasks even though the 64 
MiB request still fails. Its new paused entry starts a fresh 60-second timer, 
extending the promised bounded wait. Track all outstanding request sizes or 
retain the original deadline until the query can retry its pending requests; 
cover two concurrent task sizes near timeout.



##########
be/src/runtime/workload_group/workload_group_manager.cpp:
##########
@@ -678,32 +702,50 @@ int64_t 
WorkloadGroupMgr::revoke_memory_from_other_groups_() {
                 // then not revoke memory from it.
                 continue;
             }
-            if (total_used_memory - min_memory_limit > max_exceeded_memory) {
-                max_wg = workload_group.second;
-                max_exceeded_memory = total_used_memory - min_memory_limit;
-            }
+            exceeded_wgs.emplace_back(total_used_memory - min_memory_limit, 
workload_group.second);
         }
     }
-    if (max_wg == nullptr) {
-        return 0;
-    }
-    if (max_exceeded_memory < 1 << 27) {
-        LOG(INFO) << "The workload group that exceed most memory is :"
-                  << max_wg->memory_debug_string() << ", max_exceeded_memory: "
-                  << PrettyPrinter::print(max_exceeded_memory, TUnit::BYTES)
-                  << " less than 128MB, no need to revoke memory";
-        return 0;
-    }
-    int64_t freed_mem = static_cast<int64_t>((double)max_exceeded_memory * 
0.1);
-    // Revoke 10% of memory from the workload group that exceed most memory
-    max_wg->revoke_memory(freed_mem, "exceed_memory", profile.get());
-    std::stringstream ss;
-    profile->pretty_print(&ss);
-    LOG(INFO) << fmt::format(
-            "[MemoryGC] process memory not enough, revoke memory from 
workload_group: {}, "
-            "free memory {}. cost(us): {}, details: {}",
-            max_wg->memory_debug_string(), 
PrettyPrinter::print_bytes(freed_mem),
-            watch.elapsed_time() / 1000, ss.str());
+    std::sort(exceeded_wgs.begin(), exceeded_wgs.end(),
+              [](const auto& lhs, const auto& rhs) { return lhs.first > 
rhs.first; });
+
+    int64_t freed_mem = 0;
+    size_t tried_wgs = 0;
+    for (const auto& [exceeded_memory, wg] : exceeded_wgs) {
+        if (exceeded_memory < 1 << 27) {
+            // The remaining workload groups exceed even less.
+            LOG(INFO) << "The workload group that exceed most memory among the 
untried ones is :"
+                      << wg->memory_debug_string() << ", exceeded_memory: "
+                      << PrettyPrinter::print(exceeded_memory, TUnit::BYTES)
+                      << " less than 128MB, no need to revoke memory";
+            break;
+        }

Review Comment:
   [P1] Recheck a later peer's excess before cancelling it. The list and 
`exceeded_memory` are snapshotted before earlier groups are scanned. If the 
first group cannot reclaim and a second group drops from 250 MiB to 70 MiB 
while it is scanned (with a 100 MiB minimum), this call still uses its old 150 
MiB excess to request cancellation. `WorkloadGroup::revoke_memory()` refreshes 
current usage but does not reject the now below-minimum group, so its active 70 
MiB query can be killed despite the reservation. Recompute eligibility and the 
target from current usage for each peer immediately before revoking; test the 
intervening release.



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