| 3190 | } |
| 3191 | |
| 3192 | uint64_t Task::MemoryReclaimer::reclaimTask( |
| 3193 | const std::shared_ptr<Task>& task, |
| 3194 | uint64_t targetBytes, |
| 3195 | uint64_t maxWaitMs, |
| 3196 | memory::MemoryReclaimer::Stats& stats) { |
| 3197 | BOLT_CHECK( |
| 3198 | !isAsyncPreloadThread(), |
| 3199 | "Memory reclamation should not be called from async load thread {}, id {}, task id {}, stack {}", |
| 3200 | folly::getCurrentThreadName().value(), |
| 3201 | std::this_thread::get_id(), |
| 3202 | task->taskId(), |
| 3203 | google::GetStackTrace()); |
| 3204 | |
| 3205 | auto resumeGuard = folly::makeGuard([&]() { |
| 3206 | try { |
| 3207 | Task::resume(task); |
| 3208 | } catch (const BoltRuntimeError& exception) { |
| 3209 | LOG(WARNING) << "Failed to resume task " << task->taskId_ |
| 3210 | << " after memory reclamation: " << exception.message(); |
| 3211 | } |
| 3212 | }); |
| 3213 | |
| 3214 | uint64_t reclaimWaitTimeUs{0}; |
| 3215 | bool paused{true}; |
| 3216 | { |
| 3217 | MicrosecondTimer timer{&reclaimWaitTimeUs}; |
| 3218 | if (maxWaitMs == 0) { |
| 3219 | task->requestPause().wait(); |
| 3220 | } else { |
| 3221 | paused = task->requestPause().wait(std::chrono::milliseconds(maxWaitMs)); |
| 3222 | } |
| 3223 | } |
| 3224 | BOLT_CHECK(paused || maxWaitMs != 0); |
| 3225 | if (!paused) { |
| 3226 | RECORD_METRIC_VALUE(kMetricTaskMemoryReclaimWaitTimeoutCount, 1); |
| 3227 | BOLT_FAIL( |
| 3228 | "Memory reclaim failed to wait for task {} to pause after {} with max timeout {}", |
| 3229 | task->taskId(), |
| 3230 | succinctMicros(reclaimWaitTimeUs), |
| 3231 | succinctMillis(maxWaitMs)); |
| 3232 | } |
| 3233 | |
| 3234 | stats.reclaimWaitTimeUs += reclaimWaitTimeUs; |
| 3235 | RECORD_METRIC_VALUE(kMetricTaskMemoryReclaimCount, 1); |
| 3236 | RECORD_HISTOGRAM_METRIC_VALUE( |
| 3237 | kMetricTaskMemoryReclaimWaitTimeMs, reclaimWaitTimeUs / 1'000); |
| 3238 | |
| 3239 | // Don't reclaim from a cancelled task as it will terminate soon. |
| 3240 | if (task->isCancelled()) { |
| 3241 | return 0; |
| 3242 | } |
| 3243 | |
| 3244 | task->recordMemoryPressureWatermarkBytes(task->pool()->currentBytes()); |
| 3245 | |
| 3246 | uint64_t reclaimedBytes{0}; |
| 3247 | reclaimedBytes = memory::MemoryReclaimer::reclaim( |
| 3248 | task->pool(), targetBytes, maxWaitMs, stats); |
| 3249 | return reclaimedBytes; |
nothing calls this directly
no test coverage detected