Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 23 additions & 24 deletions tcmalloc/central_freelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
#include <cstdint>
#include <iostream>

#include "absl/algorithm/container.h"
#include "absl/base/attributes.h"
#include "absl/base/const_init.h"
#include "absl/base/internal/cycleclock.h"
Expand Down Expand Up @@ -155,7 +154,8 @@ class CentralFreeList {
first_nonempty_index_(0),
pages_per_span_(0),
nonempty_(),
use_all_buckets_for_few_object_spans_(false) {}
use_all_buckets_for_few_object_spans_(false),
lifetime_bucket_bounds_() {}

CentralFreeList(const CentralFreeList&) = delete;
CentralFreeList& operator=(const CentralFreeList&) = delete;
Expand Down Expand Up @@ -305,17 +305,6 @@ class CentralFreeList {
}

static constexpr size_t kLifetimeBuckets = 8;
static constexpr std::array<size_t, kLifetimeBuckets> kLifetimeBucketBounds =
[]() {
std::array<size_t, kLifetimeBuckets> bounds{};
static_assert(kLifetimeBuckets >= 2, "Buckets must be >= 2");
bounds[0] = 0;
bounds[1] = 1;
for (size_t i = 2; i < kLifetimeBuckets; ++i) {
bounds[i] = bounds[i - 1] * 10;
}
return bounds;
}();
using LifetimeHistogram = size_t[kLifetimeBuckets];

StatsCounter completed_spans_[kLifetimeBuckets];
Expand All @@ -325,9 +314,11 @@ class CentralFreeList {

int LifetimeBucketNum(absl::Duration duration) {
int64_t duration_ms = absl::ToInt64Milliseconds(duration);
auto it = absl::c_upper_bound(kLifetimeBucketBounds, duration_ms);
TC_CHECK_NE(it, kLifetimeBucketBounds.begin());
return it - kLifetimeBucketBounds.begin() - 1;
auto it = std::upper_bound(lifetime_bucket_bounds_,
lifetime_bucket_bounds_ + kLifetimeBuckets,
duration_ms);
TC_CHECK_NE(it, lifetime_bucket_bounds_);
return it - lifetime_bucket_bounds_ - 1;
}

// The followings are kept as a StatsCounter so that they can read without
Expand Down Expand Up @@ -375,6 +366,8 @@ class CentralFreeList {

bool use_all_buckets_for_few_object_spans_;

size_t lifetime_bucket_bounds_[kLifetimeBuckets];

// Tracks the number of long-lived spans moved to the long-lived section of
// nonempty_ per call to HandleLongLivedSpans.
StatsCounters<kSpanMoveStatBuckets> long_lived_spans_moved_;
Expand Down Expand Up @@ -409,6 +402,12 @@ inline void CentralFreeList<Forwarder>::Init(size_t size_class)
std::min<size_t>(absl::bit_width(objects_per_span_), kNumLists);

TC_ASSERT_LE(absl::bit_width(objects_per_span_), kSpanUtilBucketCapacity);

lifetime_bucket_bounds_[0] = 0;
lifetime_bucket_bounds_[1] = 1;
for (int i = 2; i < kLifetimeBuckets; ++i) {
lifetime_bucket_bounds_[i] = lifetime_bucket_bounds_[i - 1] * 10;
}
}

template <class Forwarder>
Expand Down Expand Up @@ -834,7 +833,7 @@ inline void CentralFreeList<Forwarder>::PrintSpanLifetimeStats(Printer& out) {
out.printf("class %3d [ %8zu bytes ] live spans: ", size_class_,
object_size_);
for (size_t i = 0; i < kLifetimeBuckets; ++i) {
out.printf("%3zu ms < %6zu", kLifetimeBucketBounds[i], lifetime_histo[i]);
out.printf("%3zu ms < %6zu", lifetime_bucket_bounds_[i], lifetime_histo[i]);
if (i < kLifetimeBuckets - 1) {
out.printf(",");
}
Expand All @@ -844,7 +843,7 @@ inline void CentralFreeList<Forwarder>::PrintSpanLifetimeStats(Printer& out) {
out.printf("class %3d [ %8zu bytes ] completed spans: ", size_class_,
object_size_);
for (size_t i = 0; i < kLifetimeBuckets; ++i) {
out.printf("%3zu ms < %6zu", kLifetimeBucketBounds[i],
out.printf("%3zu ms < %6zu", lifetime_bucket_bounds_[i],
completed_spans_[i].value());

if (i < kLifetimeBuckets - 1) {
Expand Down Expand Up @@ -938,19 +937,19 @@ inline void CentralFreeList<Forwarder>::PrintSpanLifetimeStatsInPbtxt(

for (size_t i = 0; i < kLifetimeBuckets; ++i) {
PbtxtRegion histogram = region.CreateSubRegion("span_lifetime_histogram");
histogram.PrintI64("lower_bound", kLifetimeBucketBounds[i]);
histogram.PrintI64("lower_bound", lifetime_bucket_bounds_[i]);
histogram.PrintI64("upper_bound", (i == kLifetimeBuckets - 1
? kLifetimeBucketBounds[i]
: kLifetimeBucketBounds[i + 1]));
? lifetime_bucket_bounds_[i]
: lifetime_bucket_bounds_[i + 1]));
histogram.PrintI64("value", lifetime_histo[i]);
}
for (size_t i = 0; i < kLifetimeBuckets; ++i) {
PbtxtRegion histogram =
region.CreateSubRegion("span_completed_lifetime_histogram");
histogram.PrintI64("lower_bound", kLifetimeBucketBounds[i]);
histogram.PrintI64("lower_bound", lifetime_bucket_bounds_[i]);
histogram.PrintI64("upper_bound", (i == kLifetimeBuckets - 1
? kLifetimeBucketBounds[i]
: kLifetimeBucketBounds[i + 1]));
? lifetime_bucket_bounds_[i]
: lifetime_bucket_bounds_[i + 1]));
histogram.PrintI64("value", completed_spans_[i].value());
}
}
Expand Down