summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYingxin Cheng <yingxin.cheng@intel.com>2024-08-14 07:22:10 +0200
committerYingxin Cheng <yingxin.cheng@intel.com>2024-08-15 07:45:27 +0200
commit243360880786c5f101d50e077d7cc0c2adf815b9 (patch)
treeec7b2f0f76ba587ba28a0723a3f6a248e2560c8b /src
parentcrimson/os/seastore: cleanup periodical reporting (diff)
downloadceph-243360880786c5f101d50e077d7cc0c2adf815b9.tar.xz
ceph-243360880786c5f101d50e077d7cc0c2adf815b9.zip
crimson/os/seastore/cache: report lru usage/in/out with trans and extent type
Signed-off-by: Yingxin Cheng <yingxin.cheng@intel.com>
Diffstat (limited to 'src')
-rw-r--r--src/crimson/os/seastore/cache.cc106
-rw-r--r--src/crimson/os/seastore/cache.h61
-rw-r--r--src/crimson/os/seastore/seastore.cc28
-rw-r--r--src/crimson/os/seastore/seastore.h3
-rw-r--r--src/crimson/os/seastore/seastore_types.cc32
-rw-r--r--src/crimson/os/seastore/seastore_types.h108
-rw-r--r--src/crimson/os/seastore/transaction_manager.h4
7 files changed, 332 insertions, 10 deletions
diff --git a/src/crimson/os/seastore/cache.cc b/src/crimson/os/seastore/cache.cc
index 0f519b28888..8c388c3d3cc 100644
--- a/src/crimson/os/seastore/cache.cc
+++ b/src/crimson/os/seastore/cache.cc
@@ -2159,4 +2159,110 @@ Cache::do_get_caching_extent_by_type(
});
}
+cache_stats_t Cache::get_stats(
+ bool report_detail, double seconds) const
+{
+ cache_stats_t ret;
+ lru.get_stats(ret, report_detail, seconds);
+ return ret;
+}
+
+void Cache::LRU::get_stats(
+ cache_stats_t &stats,
+ bool report_detail,
+ double seconds) const
+{
+ LOG_PREFIX(Cache::LRU::get_stats);
+
+ stats.lru_sizes = cache_size_stats_t{current_size, lru.size()};
+ stats.lru_io = overall_io;
+ stats.lru_io.minus(last_overall_io);
+
+ if (report_detail && seconds != 0) {
+ cache_io_stats_t _trans_io = trans_io;
+ _trans_io.minus(last_trans_io);
+
+ cache_io_stats_t other_io = stats.lru_io;
+ other_io.minus(_trans_io);
+
+ counter_by_src_t<counter_by_extent_t<cache_io_stats_t> >
+ _trans_io_by_src_ext = trans_io_by_src_ext;
+ counter_by_src_t<cache_io_stats_t> trans_io_by_src;
+ for (uint8_t _src=0; _src<TRANSACTION_TYPE_MAX; ++_src) {
+ auto src = static_cast<transaction_type_t>(_src);
+ auto& io_by_ext = get_by_src(_trans_io_by_src_ext, src);
+ const auto& last_io_by_ext = get_by_src(last_trans_io_by_src_ext, src);
+ auto& trans_io_per_src = get_by_src(trans_io_by_src, src);
+ for (uint8_t _ext=0; _ext<EXTENT_TYPES_MAX; ++_ext) {
+ auto ext = static_cast<extent_types_t>(_ext);
+ auto& extent_io = get_by_ext(io_by_ext, ext);
+ const auto& last_extent_io = get_by_ext(last_io_by_ext, ext);
+ extent_io.minus(last_extent_io);
+ trans_io_per_src.add(extent_io);
+ }
+ }
+
+ std::ostringstream oss;
+ oss << "\nlru total" << stats.lru_sizes;
+ cache_size_stats_t data_sizes;
+ cache_size_stats_t mdat_sizes;
+ cache_size_stats_t phys_sizes;
+ for (uint8_t _ext=0; _ext<EXTENT_TYPES_MAX; ++_ext) {
+ auto ext = static_cast<extent_types_t>(_ext);
+ const auto extent_sizes = get_by_ext(sizes_by_ext, ext);
+ if (is_data_type(ext)) {
+ data_sizes.add(extent_sizes);
+ } else if (is_logical_metadata_type(ext)) {
+ mdat_sizes.add(extent_sizes);
+ } else if (is_physical_type(ext)) {
+ phys_sizes.add(extent_sizes);
+ }
+ }
+ oss << "\n data" << data_sizes
+ << "\n mdat" << mdat_sizes
+ << "\n phys" << phys_sizes;
+
+ oss << "\nlru io: trans-"
+ << cache_io_stats_printer_t{seconds, _trans_io}
+ << "; other-"
+ << cache_io_stats_printer_t{seconds, other_io};
+ for (uint8_t _src=0; _src<TRANSACTION_TYPE_MAX; ++_src) {
+ auto src = static_cast<transaction_type_t>(_src);
+ const auto& trans_io_per_src = get_by_src(trans_io_by_src, src);
+ if (trans_io_per_src.is_empty()) {
+ continue;
+ }
+ cache_io_stats_t data_io;
+ cache_io_stats_t mdat_io;
+ cache_io_stats_t phys_io;
+ const auto& io_by_ext = get_by_src(_trans_io_by_src_ext, src);
+ for (uint8_t _ext=0; _ext<EXTENT_TYPES_MAX; ++_ext) {
+ auto ext = static_cast<extent_types_t>(_ext);
+ const auto extent_io = get_by_ext(io_by_ext, ext);
+ if (is_data_type(ext)) {
+ data_io.add(extent_io);
+ } else if (is_logical_metadata_type(ext)) {
+ mdat_io.add(extent_io);
+ } else if (is_physical_type(ext)) {
+ phys_io.add(extent_io);
+ }
+ }
+ oss << "\n " << src << ": "
+ << cache_io_stats_printer_t{seconds, trans_io_per_src}
+ << "\n data: "
+ << cache_io_stats_printer_t{seconds, data_io}
+ << "\n mdat: "
+ << cache_io_stats_printer_t{seconds, mdat_io}
+ << "\n phys: "
+ << cache_io_stats_printer_t{seconds, phys_io};
+ }
+
+ INFO("{}", oss.str());
+ }
+
+ last_overall_io = overall_io;
+ last_trans_io = trans_io;
+ last_trans_io_by_src_ext = trans_io_by_src_ext;
+}
+
}
diff --git a/src/crimson/os/seastore/cache.h b/src/crimson/os/seastore/cache.h
index 9139bcdff94..7c5802ae9ea 100644
--- a/src/crimson/os/seastore/cache.h
+++ b/src/crimson/os/seastore/cache.h
@@ -198,6 +198,8 @@ public:
Cache(ExtentPlacementManager &epm);
~Cache();
+ cache_stats_t get_stats(bool report_detail, double seconds) const;
+
/// Creates empty transaction by source
TransactionRef create_transaction(
Transaction::src_t src,
@@ -1363,7 +1365,7 @@ private:
return;
}
if (ext.is_stable_clean() && !ext.is_placeholder()) {
- lru.move_to_top(ext);
+ lru.move_to_top(ext, p_src);
}
}
@@ -1419,6 +1421,7 @@ private:
friend class crimson::os::seastore::backref::BtreeBackrefManager;
friend class crimson::os::seastore::BackrefManager;
+
/**
* lru
*
@@ -1431,16 +1434,38 @@ private:
// current size (bytes)
size_t current_size = 0;
+ counter_by_extent_t<cache_size_stats_t> sizes_by_ext;
+ cache_io_stats_t overall_io;
+ cache_io_stats_t trans_io;
+ counter_by_src_t<counter_by_extent_t<cache_io_stats_t> >
+ trans_io_by_src_ext;
+
+ mutable cache_io_stats_t last_overall_io;
+ mutable cache_io_stats_t last_trans_io;
+ mutable counter_by_src_t<counter_by_extent_t<cache_io_stats_t> >
+ last_trans_io_by_src_ext;
+
CachedExtent::primary_ref_list lru;
- void do_remove_from_lru(CachedExtent &extent) {
+ void do_remove_from_lru(
+ CachedExtent &extent,
+ const Transaction::src_t* p_src) {
assert(extent.is_stable_clean() && !extent.is_placeholder());
assert(extent.primary_ref_list_hook.is_linked());
assert(lru.size() > 0);
- assert(current_size >= extent.get_length());
+ auto extent_length = extent.get_length();
+ assert(current_size >= extent_length);
lru.erase(lru.s_iterator_to(extent));
- current_size -= extent.get_length();
+ current_size -= extent_length;
+ get_by_ext(sizes_by_ext, extent.get_type()).account_out(extent_length);
+ overall_io.account_out(extent_length);
+ if (p_src) {
+ trans_io.account_out(extent_length);
+ get_by_ext(
+ get_by_src(trans_io_by_src_ext, *p_src),
+ extent.get_type()).account_out(extent_length);
+ }
intrusive_ptr_release(&extent);
}
@@ -1459,32 +1484,48 @@ private:
return lru.size();
}
+ void get_stats(
+ cache_stats_t &stats,
+ bool report_detail,
+ double seconds) const;
+
void remove_from_lru(CachedExtent &extent) {
assert(extent.is_stable_clean() && !extent.is_placeholder());
if (extent.primary_ref_list_hook.is_linked()) {
- do_remove_from_lru(extent);
+ do_remove_from_lru(extent, nullptr);
}
}
- void move_to_top(CachedExtent &extent) {
+ void move_to_top(
+ CachedExtent &extent,
+ const Transaction::src_t* p_src) {
assert(extent.is_stable_clean() && !extent.is_placeholder());
+ auto extent_length = extent.get_length();
if (extent.primary_ref_list_hook.is_linked()) {
// present, move to top (back)
assert(lru.size() > 0);
- assert(current_size >= extent.get_length());
+ assert(current_size >= extent_length);
lru.erase(lru.s_iterator_to(extent));
lru.push_back(extent);
} else {
// absent, add to top (back)
- current_size += extent.get_length();
+ current_size += extent_length;
+ get_by_ext(sizes_by_ext, extent.get_type()).account_in(extent_length);
+ overall_io.account_in(extent_length);
+ if (p_src) {
+ trans_io.account_in(extent_length);
+ get_by_ext(
+ get_by_src(trans_io_by_src_ext, *p_src),
+ extent.get_type()).account_in(extent_length);
+ }
intrusive_ptr_add_ref(&extent);
lru.push_back(extent);
// trim to capacity
while (current_size > capacity) {
- do_remove_from_lru(lru.front());
+ do_remove_from_lru(lru.front(), p_src);
}
}
}
@@ -1493,7 +1534,7 @@ private:
LOG_PREFIX(Cache::LRU::clear);
for (auto iter = lru.begin(); iter != lru.end();) {
SUBDEBUG(seastore_cache, "clearing {}", *iter);
- do_remove_from_lru(*(iter++));
+ do_remove_from_lru(*(iter++), nullptr);
}
}
diff --git a/src/crimson/os/seastore/seastore.cc b/src/crimson/os/seastore/seastore.cc
index 6df05eba02f..049d0d70b06 100644
--- a/src/crimson/os/seastore/seastore.cc
+++ b/src/crimson/os/seastore/seastore.cc
@@ -590,6 +590,7 @@ seastar::future<> SeaStore::report_stats()
ceph_assert(seastar::this_shard_id() == primary_core);
shard_device_stats.resize(seastar::smp::count);
shard_io_stats.resize(seastar::smp::count);
+ shard_cache_stats.resize(seastar::smp::count);
return shard_stores.invoke_on_all([this](const Shard &local_store) {
bool report_detail = false;
double seconds = 0;
@@ -602,6 +603,8 @@ seastar::future<> SeaStore::report_stats()
local_store.get_device_stats(report_detail, seconds);
shard_io_stats[seastar::this_shard_id()] =
local_store.get_io_stats(report_detail, seconds);
+ shard_cache_stats[seastar::this_shard_id()] =
+ local_store.get_cache_stats(report_detail, seconds);
}).then([this] {
LOG_PREFIX(SeaStore);
auto now = seastar::lowres_clock::now();
@@ -697,6 +700,24 @@ seastar::future<> SeaStore::report_stats()
<< ") ";
}
INFO("details: {}", oss_pending.str());
+
+ cache_stats_t cache_total = {};
+ for (const auto& s : shard_cache_stats) {
+ cache_total.add(s);
+ }
+ cache_size_stats_t lru_sizes_ps = cache_total.lru_sizes;
+ lru_sizes_ps.size /= seastar::smp::count;
+ lru_sizes_ps.num_extents /= seastar::smp::count;
+ cache_io_stats_t lru_io_ps = cache_total.lru_io;
+ lru_io_ps.in_size /= seastar::smp::count;
+ lru_io_ps.in_num_extents /= seastar::smp::count;
+ lru_io_ps.out_size /= seastar::smp::count;
+ lru_io_ps.out_num_extents /= seastar::smp::count;
+ INFO("cache lru: total{} {}; per-shard: total{} {}",
+ cache_total.lru_sizes,
+ cache_io_stats_printer_t{seconds, cache_total.lru_io},
+ lru_sizes_ps,
+ cache_io_stats_printer_t{seconds, lru_io_ps});
return seastar::now();
});
}
@@ -2599,6 +2620,13 @@ shard_stats_t SeaStore::Shard::get_io_stats(
return ret;
}
+cache_stats_t SeaStore::Shard::get_cache_stats(
+ bool report_detail, double seconds) const
+{
+ return transaction_manager->get_cache_stats(
+ report_detail, seconds);
+}
+
std::unique_ptr<SeaStore> make_seastore(
const std::string &device)
{
diff --git a/src/crimson/os/seastore/seastore.h b/src/crimson/os/seastore/seastore.h
index 11b3f88e0aa..fb495a422f6 100644
--- a/src/crimson/os/seastore/seastore.h
+++ b/src/crimson/os/seastore/seastore.h
@@ -210,6 +210,8 @@ public:
shard_stats_t get_io_stats(bool report_detail, double seconds) const;
+ cache_stats_t get_cache_stats(bool report_detail, double seconds) const;
+
private:
struct internal_context_t {
CollectionRef ch;
@@ -585,6 +587,7 @@ private:
seastar::lowres_clock::time_point::min();
mutable std::vector<device_stats_t> shard_device_stats;
mutable std::vector<shard_stats_t> shard_io_stats;
+ mutable std::vector<cache_stats_t> shard_cache_stats;
};
std::unique_ptr<SeaStore> make_seastore(
diff --git a/src/crimson/os/seastore/seastore_types.cc b/src/crimson/os/seastore/seastore_types.cc
index 58fe134b377..5dc87d2d60b 100644
--- a/src/crimson/os/seastore/seastore_types.cc
+++ b/src/crimson/os/seastore/seastore_types.cc
@@ -980,4 +980,36 @@ std::ostream& operator<<(std::ostream& out, const writer_stats_printer_t& p)
return out;
}
+std::ostream& operator<<(std::ostream& out, const cache_io_stats_printer_t& p)
+{
+ constexpr const char* dfmt = "{:.2f}";
+ out << "in("
+ << fmt::format(dfmt, p.stats.get_in_mbs(p.seconds))
+ << "MiB/s,"
+ << fmt::format(dfmt, p.stats.get_in_avg_kb())
+ << "KiB,"
+ << fmt::format(dfmt, p.stats.in_num_extents/p.seconds)
+ << "ps) out("
+ << fmt::format(dfmt, p.stats.get_out_mbs(p.seconds))
+ << "MiB/s,"
+ << fmt::format(dfmt, p.stats.get_out_avg_kb())
+ << "KiB,"
+ << fmt::format(dfmt, p.stats.out_num_extents/p.seconds)
+ << "ps)";
+ return out;
+}
+
+std::ostream& operator<<(std::ostream& out, const cache_size_stats_t& p)
+{
+ constexpr const char* dfmt = "{:.2f}";
+ out << "("
+ << fmt::format(dfmt, p.get_mb())
+ << "MiB,"
+ << fmt::format(dfmt, p.get_avg_kb())
+ << "KiB,"
+ << p.num_extents
+ << ")";
+ return out;
}
+
+} // namespace crimson::os::seastore
diff --git a/src/crimson/os/seastore/seastore_types.h b/src/crimson/os/seastore/seastore_types.h
index f1334960668..df53bab798f 100644
--- a/src/crimson/os/seastore/seastore_types.h
+++ b/src/crimson/os/seastore/seastore_types.h
@@ -2342,6 +2342,15 @@ CounterT& get_by_ext(
return counters_by_ext[index];
}
+template <typename CounterT>
+const CounterT& get_by_ext(
+ const counter_by_extent_t<CounterT>& counters_by_ext,
+ extent_types_t ext) {
+ auto index = static_cast<uint8_t>(ext);
+ assert(index < EXTENT_TYPES_MAX);
+ return counters_by_ext[index];
+}
+
struct grouped_io_stats {
uint64_t num_io = 0;
uint64_t num_io_grouped = 0;
@@ -2548,6 +2557,103 @@ struct shard_stats_t {
}
};
+struct cache_io_stats_t {
+ uint64_t in_size = 0;
+ uint64_t in_num_extents = 0;
+ uint64_t out_size = 0;
+ uint64_t out_num_extents = 0;
+
+ bool is_empty() const {
+ return in_num_extents == 0 && out_num_extents == 0;
+ }
+
+ double get_in_mbs(double seconds) const {
+ return (in_size>>12)/(seconds*256);
+ }
+
+ double get_in_avg_kb() const {
+ return (in_size>>10)/static_cast<double>(in_num_extents);
+ }
+
+ double get_out_mbs(double seconds) const {
+ return (out_size>>12)/(seconds*256);
+ }
+
+ double get_out_avg_kb() const {
+ return (out_size>>10)/static_cast<double>(out_num_extents);
+ }
+
+ void account_in(extent_len_t size) {
+ in_size += size;
+ ++in_num_extents;
+ }
+
+ void account_out(extent_len_t size) {
+ out_size += size;
+ ++out_num_extents;
+ }
+
+ void minus(const cache_io_stats_t& o) {
+ in_size -= o.in_size;
+ in_num_extents -= o.in_num_extents;
+ out_size -= o.out_size;
+ out_num_extents -= o.out_num_extents;
+ }
+
+ void add(const cache_io_stats_t& o) {
+ in_size += o.in_size;
+ in_num_extents += o.in_num_extents;
+ out_size += o.out_size;
+ out_num_extents += o.out_num_extents;
+ }
+};
+struct cache_io_stats_printer_t {
+ double seconds;
+ const cache_io_stats_t &stats;
+};
+std::ostream& operator<<(std::ostream&, const cache_io_stats_printer_t&);
+
+struct cache_size_stats_t {
+ uint64_t size = 0;
+ uint64_t num_extents = 0;
+
+ double get_mb() const {
+ return (size>>12)/static_cast<double>(256);
+ }
+
+ double get_avg_kb() const {
+ return (size>>10)/static_cast<double>(num_extents);
+ }
+
+ void account_in(extent_len_t sz) {
+ size += sz;
+ ++num_extents;
+ }
+
+ void account_out(extent_len_t sz) {
+ assert(size >= sz);
+ assert(num_extents > 0);
+ size -= sz;
+ --num_extents;
+ }
+
+ void add(const cache_size_stats_t& o) {
+ size += o.size;
+ num_extents += o.num_extents;
+ }
+};
+std::ostream& operator<<(std::ostream&, const cache_size_stats_t&);
+
+struct cache_stats_t {
+ cache_size_stats_t lru_sizes;
+ cache_io_stats_t lru_io;
+
+ void add(const cache_stats_t& o) {
+ lru_sizes.add(o.lru_sizes);
+ lru_io.add(o.lru_io);
+ }
+};
+
}
WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::seastore_meta_t)
@@ -2565,6 +2671,8 @@ WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::alloc_delta_t)
WRITE_CLASS_DENC_BOUNDED(crimson::os::seastore::segment_tail_t)
#if FMT_VERSION >= 90000
+template <> struct fmt::formatter<crimson::os::seastore::cache_io_stats_printer_t> : fmt::ostream_formatter {};
+template <> struct fmt::formatter<crimson::os::seastore::cache_size_stats_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::data_category_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::delta_info_t> : fmt::ostream_formatter {};
template <> struct fmt::formatter<crimson::os::seastore::device_id_printer_t> : fmt::ostream_formatter {};
diff --git a/src/crimson/os/seastore/transaction_manager.h b/src/crimson/os/seastore/transaction_manager.h
index 864bbd68726..1c090196dd4 100644
--- a/src/crimson/os/seastore/transaction_manager.h
+++ b/src/crimson/os/seastore/transaction_manager.h
@@ -86,6 +86,10 @@ public:
return epm->get_device_stats(journal_stats, report_detail, seconds);
}
+ cache_stats_t get_cache_stats(bool report_detail, double seconds) const {
+ return cache->get_stats(report_detail, seconds);
+ }
+
/// Resets transaction
void reset_transaction_preserve_handle(Transaction &t) {
return cache->reset_transaction_preserve_handle(t);