From 2b3761d7a247eaba12bbdb8e0fee4bd9cfc89041 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 27 Sep 2018 13:10:55 +0800 Subject: [PATCH] osdc: reduce ObjectCacher's memory fragments Fixes: http://tracker.ceph.com/issues/36192 Signed-off-by: "Yan, Zheng" (cherry picked from commit 5d4f82117ed20f7a40259c3f5471e7a96a4c456f) Conflicts: src/osdc/ObjectCacher.cc: trivial --- src/common/buffer.cc | 26 ++++++++++++++++++++++++++ src/include/buffer.h | 1 + src/osdc/ObjectCacher.cc | 29 +++++++++++++++++++++++++---- src/osdc/ObjectCacher.h | 1 + 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/common/buffer.cc b/src/common/buffer.cc index 1a8e9123b6c95..6449b4d04e669 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -1719,6 +1719,32 @@ public: } } + uint64_t buffer::list::get_wasted_space() const + { + if (_buffers.size() == 1) + return _buffers.back().wasted(); + + std::vector raw_vec; + raw_vec.reserve(_buffers.size()); + for (const auto& p : _buffers) + raw_vec.push_back(p.get_raw()); + std::sort(raw_vec.begin(), raw_vec.end()); + + uint64_t total = 0; + const raw *last = nullptr; + for (const auto r : raw_vec) { + if (r == last) + continue; + last = r; + total += r->len; + } + // If multiple buffers are sharing the same raw buffer and they overlap + // with each other, the wasted space will be underestimated. + if (total <= length()) + return 0; + return total - length(); + } + void buffer::list::rebuild() { if (_len == 0) { diff --git a/src/include/buffer.h b/src/include/buffer.h index e110b74b2c0c0..473e69ff17b83 100644 --- a/src/include/buffer.h +++ b/src/include/buffer.h @@ -700,6 +700,7 @@ namespace buffer CEPH_BUFFER_API { return *this; } + uint64_t get_wasted_space() const; unsigned get_num_buffers() const { return _buffers.size(); } const ptr& front() const { return _buffers.front(); } const ptr& back() const { return _buffers.back(); } diff --git a/src/osdc/ObjectCacher.cc b/src/osdc/ObjectCacher.cc index 249f24636f680..cb1b0ca0cbfc9 100644 --- a/src/osdc/ObjectCacher.cc +++ b/src/osdc/ObjectCacher.cc @@ -12,7 +12,7 @@ #include "include/assert.h" #define MAX_FLUSH_UNDER_LOCK 20 ///< max bh's we start writeback on -#define BUFFER_MEMORY_WEIGHT 12 // memory usage of BufferHead, count in (1<second)) merge_left(bh, p->second); + + maybe_rebuild_buffer(bh); +} + +void ObjectCacher::Object::maybe_rebuild_buffer(BufferHead *bh) +{ + auto& bl = bh->bl; + if (bl.get_num_buffers() <= 1) + return; + + auto wasted = bl.get_wasted_space(); + if (wasted * 2 > bl.length() && + wasted > (1U << BUFFER_MEMORY_WEIGHT)) + bl.rebuild(); } /* @@ -454,15 +468,18 @@ ObjectCacher::BufferHead *ObjectCacher::Object::map_write(ObjectExtent &ex, if (cur + max >= bh->end()) { // we want right bit (one splice) final = split(bh, cur); // just split it, take right half. + maybe_rebuild_buffer(bh); replace_journal_tid(final, tid); ++p; assert(p->second == final); } else { // we want middle bit (two splices) final = split(bh, cur); + maybe_rebuild_buffer(bh); ++p; assert(p->second == final); - split(final, cur+max); + auto right = split(final, cur+max); + maybe_rebuild_buffer(right); replace_journal_tid(final, tid); } } else { @@ -471,7 +488,8 @@ ObjectCacher::BufferHead *ObjectCacher::Object::map_write(ObjectExtent &ex, // whole bufferhead, piece of cake. } else { // we want left bit (one splice) - split(bh, cur + max); // just split + auto right = split(bh, cur + max); // just split + maybe_rebuild_buffer(right); } if (final) { oc->mark_dirty(bh); @@ -549,6 +567,7 @@ void ObjectCacher::Object::truncate(loff_t s) // split bh at truncation point? if (bh->start() < s) { split(bh, s); + maybe_rebuild_buffer(bh); continue; } @@ -586,13 +605,15 @@ void ObjectCacher::Object::discard(loff_t off, loff_t len, // split bh at truncation point? if (bh->start() < off) { split(bh, off); + maybe_rebuild_buffer(bh); ++p; continue; } assert(bh->start() >= off); if (bh->end() > off + len) { - split(bh, off + len); + auto right = split(bh, off + len); + maybe_rebuild_buffer(right); } ++p; diff --git a/src/osdc/ObjectCacher.h b/src/osdc/ObjectCacher.h index 60f049ef55d5b..81abb214c0737 100644 --- a/src/osdc/ObjectCacher.h +++ b/src/osdc/ObjectCacher.h @@ -343,6 +343,7 @@ class ObjectCacher { void merge_left(BufferHead *left, BufferHead *right); bool can_merge_bh(BufferHead *left, BufferHead *right); void try_merge_bh(BufferHead *bh); + void maybe_rebuild_buffer(BufferHead *bh); bool is_cached(loff_t off, loff_t len) const; bool include_all_cached_data(loff_t off, loff_t len); -- 2.47.3