}
}
+ uint64_t buffer::list::get_wasted_space() const
+ {
+ if (_buffers.size() == 1)
+ return _buffers.back().wasted();
+
+ std::vector<const raw*> 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) {
#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<<n)
+#define BUFFER_MEMORY_WEIGHT CEPH_PAGE_SHIFT // memory usage of BufferHead, count in (1<<n)
using std::chrono::seconds;
/// while holding the lock
++p;
if (p != data.end() && can_merge_bh(bh, p->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();
}
/*
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 {
// 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);
// split bh at truncation point?
if (bh->start() < s) {
split(bh, s);
+ maybe_rebuild_buffer(bh);
continue;
}
// 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;