Calling this on the query tracker results in output like: Query(4a4c81fedaed337d:4acadfda00000000) Limit=10.00 GB Total=508.28 MB Peak=508.45 MB Fragment 4a4c81fedaed337d:4acadfda00000000: Total=8.00 KB Peak=8.00 KB EXCHANGE_NODE (id=4): Total=0 Peak=0 DataStreamRecvr: Total=0 Peak=0 Block Manager: Limit=6.68 GB Total=394.00 MB Peak=394.00 MB Fragment 4a4c81fedaed337d:4acadfda00000006: Total=233.
| 298 | // Total=6.04 MB Peak=6.45 MB |
| 299 | // |
| 300 | string MemTracker::LogUsage(int max_recursive_depth, const string& prefix, |
| 301 | int64_t* logged_consumption) { |
| 302 | // Make sure the consumption is up to date. |
| 303 | if (consumption_metric_ != nullptr) RefreshConsumptionFromMetric(); |
| 304 | int64_t curr_consumption = consumption(); |
| 305 | int64_t peak_consumption = consumption_->value(); |
| 306 | if (logged_consumption != nullptr) *logged_consumption = curr_consumption; |
| 307 | |
| 308 | if (!log_usage_if_zero_ && curr_consumption == 0) return ""; |
| 309 | |
| 310 | stringstream ss; |
| 311 | ss << prefix << label_ << ":"; |
| 312 | if (CheckLimitExceeded(MemLimit::HARD)) ss << " memory limit exceeded."; |
| 313 | if (limit_ > 0) ss << " Limit=" << PrettyPrinter::Print(limit_, TUnit::BYTES); |
| 314 | |
| 315 | ReservationTrackerCounters* reservation_counters = reservation_counters_.Load(); |
| 316 | if (reservation_counters != nullptr) { |
| 317 | int64_t reservation = reservation_counters->peak_reservation->current_value(); |
| 318 | ss << " Reservation=" << PrettyPrinter::Print(reservation, TUnit::BYTES); |
| 319 | if (reservation_counters->reservation_limit != nullptr) { |
| 320 | int64_t limit = reservation_counters->reservation_limit->value(); |
| 321 | ss << " ReservationLimit=" << PrettyPrinter::Print(limit, TUnit::BYTES); |
| 322 | } |
| 323 | ss << " OtherMemory=" |
| 324 | << PrettyPrinter::Print(curr_consumption - reservation, TUnit::BYTES); |
| 325 | } |
| 326 | ss << " Total=" << PrettyPrinter::Print(curr_consumption, TUnit::BYTES); |
| 327 | // Peak consumption is not accurate if the metric is lazily updated (i.e. |
| 328 | // this is a non-root tracker that exists only for reporting purposes). |
| 329 | // Only report peak consumption if we actually call Consume()/Release() on |
| 330 | // this tracker or an descendent. |
| 331 | if (consumption_metric_ == nullptr || parent_ == nullptr) { |
| 332 | ss << " Peak=" << PrettyPrinter::Print(peak_consumption, TUnit::BYTES); |
| 333 | } |
| 334 | |
| 335 | // This call does not need the children, so return early. |
| 336 | if (max_recursive_depth == 0) return ss.str(); |
| 337 | |
| 338 | // Recurse and get information about the children |
| 339 | string new_prefix = Substitute(" $0", prefix); |
| 340 | int64_t child_consumption; |
| 341 | string child_trackers_usage; |
| 342 | { |
| 343 | lock_guard<SpinLock> l(child_trackers_lock_); |
| 344 | child_trackers_usage = LogUsage(max_recursive_depth - 1, new_prefix, |
| 345 | child_trackers_, &child_consumption); |
| 346 | } |
| 347 | if (!child_trackers_usage.empty()) ss << "\n" << child_trackers_usage; |
| 348 | |
| 349 | if (parent_ == nullptr) { |
| 350 | // Log the difference between the metric value and children as "untracked" memory so |
| 351 | // that the values always add up. This value is not always completely accurate because |
| 352 | // we did not necessarily get a consistent snapshot of the consumption values for all |
| 353 | // children at a single moment in time, but is good enough for our purposes. |
| 354 | int64_t untracked_bytes = curr_consumption - child_consumption; |
| 355 | ss << "\n" |
| 356 | << new_prefix << "Untracked Memory: Total=" |
| 357 | << PrettyPrinter::Print(untracked_bytes, TUnit::BYTES); |