| 484 | } |
| 485 | |
| 486 | Status MemTracker::MemLimitExceeded(MemTracker* mtracker, RuntimeState* state, |
| 487 | const std::string& details, int64_t failed_allocation_size) { |
| 488 | DCHECK_GE(failed_allocation_size, 0); |
| 489 | stringstream ss; |
| 490 | if (details.size() != 0) ss << details << endl; |
| 491 | if (failed_allocation_size != 0) { |
| 492 | if (mtracker != nullptr) ss << mtracker->label(); |
| 493 | ss << " could not allocate " |
| 494 | << PrettyPrinter::Print(failed_allocation_size, TUnit::BYTES) |
| 495 | << " without exceeding limit." << endl; |
| 496 | } |
| 497 | ss << "Error occurred on backend " << GetBackendString(); |
| 498 | if (state != nullptr) ss << " by fragment " << PrintId(state->fragment_instance_id()); |
| 499 | ss << endl; |
| 500 | ExecEnv* exec_env = ExecEnv::GetInstance(); |
| 501 | MemTracker* process_tracker = exec_env->process_mem_tracker(); |
| 502 | const int64_t process_capacity = process_tracker->SpareCapacity(MemLimit::HARD); |
| 503 | ss << "Memory left in process limit: " |
| 504 | << PrettyPrinter::Print(process_capacity, TUnit::BYTES) << endl; |
| 505 | |
| 506 | // Always log the query tracker (if available). |
| 507 | MemTracker* query_tracker = nullptr; |
| 508 | if (mtracker != nullptr) { |
| 509 | query_tracker = mtracker->GetQueryMemTracker(); |
| 510 | if (query_tracker != nullptr) { |
| 511 | if (query_tracker->has_limit()) { |
| 512 | const int64_t query_capacity = |
| 513 | query_tracker->limit() - query_tracker->consumption(); |
| 514 | ss << "Memory left in query limit: " |
| 515 | << PrettyPrinter::Print(query_capacity, TUnit::BYTES) << endl; |
| 516 | } |
| 517 | ss << query_tracker->LogUsage(UNLIMITED_DEPTH); |
| 518 | } |
| 519 | } |
| 520 | |
| 521 | // Log the process level if the process tracker is close to the limit or |
| 522 | // if this tracker is not within a query's MemTracker hierarchy. |
| 523 | if (process_capacity < failed_allocation_size || query_tracker == nullptr) { |
| 524 | // IMPALA-5598: For performance reasons, limit the levels of recursion when |
| 525 | // dumping the process tracker to only two layers. |
| 526 | ss << process_tracker->LogUsage(PROCESS_MEMTRACKER_LIMITED_DEPTH); |
| 527 | } |
| 528 | |
| 529 | Status status = Status::MemLimitExceeded(ss.str()); |
| 530 | if (state != nullptr) state->LogError(status.msg()); |
| 531 | return status; |
| 532 | } |
| 533 | |
| 534 | void MemTracker::AddGcFunction(GcFunction f) { |
| 535 | gc_functions_.emplace_back(move(f)); |
no test coverage detected