Skip to content

Commit 0c435d8

Browse files
committed
crimson/os/seastore/segment_cleaner: add statistics for segment utilization
Signed-off-by: Xuehan Xu <xxhdx1985126@gmail.com>
1 parent 8b8a96d commit 0c435d8

File tree

2 files changed

+79
-17
lines changed

2 files changed

+79
-17
lines changed

src/crimson/os/seastore/segment_cleaner.cc

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,14 @@ bool SpaceTrackerSimple::equals(const SpaceTrackerI &_other) const
4949
bool all_match = true;
5050
for (auto i = live_bytes_by_segment.begin(), j = other.live_bytes_by_segment.begin();
5151
i != live_bytes_by_segment.end(); ++i, ++j) {
52-
if (i->second != j->second) {
52+
if (i->second.live_bytes != j->second.live_bytes) {
5353
all_match = false;
5454
logger().debug(
5555
"{}: segment_id {} live bytes mismatch *this: {}, other: {}",
5656
__func__,
5757
i->first,
58-
i->second,
59-
j->second);
58+
i->second.live_bytes,
59+
j->second.live_bytes);
6060
}
6161
}
6262
return all_match;
@@ -176,13 +176,20 @@ SegmentCleaner::SegmentCleaner(
176176
config(config),
177177
scanner(std::move(scr)),
178178
gc_process(*this)
179-
{
180-
register_metrics();
181-
}
179+
{}
182180

183181
void SegmentCleaner::register_metrics()
184182
{
185183
namespace sm = seastar::metrics;
184+
stats.segment_util.buckets.resize(11);
185+
for (int i = 0; i < 11; i++) {
186+
stats.segment_util.buckets[i].upper_bound = ((double)(i + 1)) / 10;
187+
if (!i) {
188+
stats.segment_util.buckets[i].count = segments.num_segments();
189+
} else {
190+
stats.segment_util.buckets[i].count = 0;
191+
}
192+
}
186193
metrics.add_group("segment_cleaner", {
187194
sm::make_counter("segments_released", stats.segments_released,
188195
sm::description("total number of extents released by SegmentCleaner")),
@@ -205,7 +212,12 @@ void SegmentCleaner::register_metrics()
205212
[this] {
206213
return segments.get_opened_segments();
207214
},
208-
sm::description("the number of segments whose state is open"))
215+
sm::description("the number of segments whose state is open")),
216+
sm::make_histogram("segment_utilization_distribution",
217+
[this]() -> seastar::metrics::histogram& {
218+
return stats.segment_util;
219+
},
220+
sm::description("utilization distribution of all segments"))
209221
});
210222
}
211223

src/crimson/os/seastore/segment_cleaner.h

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55

66
#include <boost/intrusive/set.hpp>
7+
#include <seastar/core/metrics_types.hh>
78

89
#include "common/ceph_time.h"
910

@@ -255,6 +256,16 @@ class segment_info_set_t {
255256
device_segment_id_t get_journal_segments() const {
256257
return journal_segments;
257258
}
259+
device_segment_id_t num_segments() const {
260+
device_segment_id_t num = 0;
261+
for (auto& sm_info : sm_infos) {
262+
if (!sm_info) {
263+
continue;
264+
}
265+
num += sm_info->num_segments;
266+
}
267+
return num;
268+
}
258269
private:
259270
std::vector<std::optional<segment_manager_info_t>> sm_infos;
260271
segment_map_t<segment_info_t> segments;
@@ -309,20 +320,26 @@ class SpaceTrackerI {
309320

310321
virtual void dump_usage(segment_id_t) const = 0;
311322

323+
virtual double calc_utilization(segment_id_t segment) const = 0;
324+
312325
virtual void reset() = 0;
313326

314327
virtual ~SpaceTrackerI() = default;
315328
};
316329
using SpaceTrackerIRef = std::unique_ptr<SpaceTrackerI>;
317330

318331
class SpaceTrackerSimple : public SpaceTrackerI {
332+
struct segment_bytes_t {
333+
int64_t live_bytes = 0;
334+
seastore_off_t total_bytes = 0;
335+
};
319336
// Tracks live space for each segment
320-
segment_map_t<int64_t> live_bytes_by_segment;
337+
segment_map_t<segment_bytes_t> live_bytes_by_segment;
321338

322339
int64_t update_usage(segment_id_t segment, int64_t delta) {
323-
live_bytes_by_segment[segment] += delta;
324-
assert(live_bytes_by_segment[segment] >= 0);
325-
return live_bytes_by_segment[segment];
340+
live_bytes_by_segment[segment].live_bytes += delta;
341+
assert(live_bytes_by_segment[segment].live_bytes >= 0);
342+
return live_bytes_by_segment[segment].live_bytes;
326343
}
327344
public:
328345
SpaceTrackerSimple(const SpaceTrackerSimple &) = default;
@@ -337,7 +354,7 @@ class SpaceTrackerSimple : public SpaceTrackerI {
337354
live_bytes_by_segment.add_device(
338355
sm->get_device_id(),
339356
sm->get_num_segments(),
340-
0);
357+
{0, sm->get_segment_size()});
341358
}
342359
}
343360

@@ -356,14 +373,19 @@ class SpaceTrackerSimple : public SpaceTrackerI {
356373
}
357374

358375
int64_t get_usage(segment_id_t segment) const final {
359-
return live_bytes_by_segment[segment];
376+
return live_bytes_by_segment[segment].live_bytes;
377+
}
378+
379+
double calc_utilization(segment_id_t segment) const final {
380+
auto& seg_bytes = live_bytes_by_segment[segment];
381+
return (double)seg_bytes.live_bytes / (double)seg_bytes.total_bytes;
360382
}
361383

362384
void dump_usage(segment_id_t) const final {}
363385

364386
void reset() final {
365387
for (auto &i : live_bytes_by_segment) {
366-
i.second = 0;
388+
i.second = {0, 0};
367389
}
368390
}
369391

@@ -379,10 +401,15 @@ class SpaceTrackerSimple : public SpaceTrackerI {
379401
class SpaceTrackerDetailed : public SpaceTrackerI {
380402
class SegmentMap {
381403
int64_t used = 0;
404+
seastore_off_t total_bytes = 0;
382405
std::vector<bool> bitmap;
383406

384407
public:
385-
SegmentMap(size_t blocks) : bitmap(blocks, false) {}
408+
SegmentMap(
409+
size_t blocks,
410+
seastore_off_t total_bytes)
411+
: total_bytes(total_bytes),
412+
bitmap(blocks, false) {}
386413

387414
int64_t update_usage(int64_t delta) {
388415
used += delta;
@@ -407,6 +434,10 @@ class SpaceTrackerDetailed : public SpaceTrackerI {
407434

408435
void dump_usage(extent_len_t block_size) const;
409436

437+
double calc_utilization() const {
438+
return (double)used / (double)total_bytes;
439+
}
440+
410441
void reset() {
411442
used = 0;
412443
for (auto &&i: bitmap) {
@@ -435,7 +466,8 @@ class SpaceTrackerDetailed : public SpaceTrackerI {
435466
sm->get_device_id(),
436467
sm->get_num_segments(),
437468
SegmentMap(
438-
sm->get_segment_size() / sm->get_block_size()));
469+
sm->get_segment_size() / sm->get_block_size(),
470+
sm->get_segment_size()));
439471
block_size_by_segment_manager[sm->get_device_id()] = sm->get_block_size();
440472
}
441473
}
@@ -466,6 +498,10 @@ class SpaceTrackerDetailed : public SpaceTrackerI {
466498
return segment_usage[segment].get_usage();
467499
}
468500

501+
double calc_utilization(segment_id_t segment) const final {
502+
return segment_usage[segment].calc_utilization();
503+
}
504+
469505
void dump_usage(segment_id_t seg) const final;
470506

471507
void reset() final {
@@ -647,6 +683,7 @@ class SegmentCleaner : public SegmentProvider {
647683
uint64_t accumulated_blocked_ios = 0;
648684
uint64_t empty_segments = 0;
649685
int64_t ios_blocking = 0;
686+
seastar::metrics::histogram segment_util;
650687
} stats;
651688
seastar::metrics::metric_group metrics;
652689
void register_metrics();
@@ -717,6 +754,12 @@ class SegmentCleaner : public SegmentProvider {
717754
return mark_empty(segment);
718755
}
719756

757+
void adjust_segment_util(double old_usage, double new_usage) {
758+
assert(stats.segment_util.buckets[std::floor(old_usage * 10)].count > 0);
759+
stats.segment_util.buckets[std::floor(old_usage * 10)].count--;
760+
stats.segment_util.buckets[std::floor(new_usage * 10)].count++;
761+
}
762+
720763
void mark_space_used(
721764
paddr_t addr,
722765
extent_len_t len,
@@ -731,10 +774,14 @@ class SegmentCleaner : public SegmentProvider {
731774
return;
732775

733776
stats.used_bytes += len;
777+
auto old_usage = space_tracker->calc_utilization(seg_addr.get_segment_id());
734778
[[maybe_unused]] auto ret = space_tracker->allocate(
735779
seg_addr.get_segment_id(),
736780
seg_addr.get_segment_off(),
737781
len);
782+
auto new_usage = space_tracker->calc_utilization(seg_addr.get_segment_id());
783+
adjust_segment_util(old_usage, new_usage);
784+
738785
gc_process.maybe_wake_on_space_used();
739786
assert(ret > 0);
740787
}
@@ -748,15 +795,18 @@ class SegmentCleaner : public SegmentProvider {
748795
ceph_assert(stats.used_bytes >= len);
749796
stats.used_bytes -= len;
750797
auto& seg_addr = addr.as_seg_paddr();
751-
assert(addr.get_device_id() ==
798+
assert(seg_addr.get_segment_id().device_id() ==
752799
segments[seg_addr.get_segment_id().device_id()]->device_id);
753800
assert(seg_addr.get_segment_id().device_segment_id() <
754801
segments[seg_addr.get_segment_id().device_id()]->num_segments);
755802

803+
auto old_usage = space_tracker->calc_utilization(seg_addr.get_segment_id());
756804
[[maybe_unused]] auto ret = space_tracker->release(
757805
seg_addr.get_segment_id(),
758806
seg_addr.get_segment_off(),
759807
len);
808+
auto new_usage = space_tracker->calc_utilization(seg_addr.get_segment_id());
809+
adjust_segment_util(old_usage, new_usage);
760810
maybe_wake_gc_blocked_io();
761811
assert(ret >= 0);
762812
}

0 commit comments

Comments
 (0)