mirror of
https://github.com/ceph/ceph
synced 2025-01-20 01:51:34 +00:00
denc: do not always copy before decoding
before this change, if the caller calls into ::decode_nohead(), we will try to copy the memory chunk to be decoded before decoding it, but if the buffer in the buffer list is not the last one, we will *deep* copy the remaining part in the buffer list into a new contiguous memory chunk and decode it instead. if we are decoding a map<int, buffer::ptr> with lots of items in it, and the buffer::ptrs in it are very small, we will end up suffering from a serious internal fragmentation. we could use the same strategy of decode(), where we compare the size of remaining part with CEPH_PAGE_SIZE, and only copy it if it's small enough. this requires that the decoded type supports both variant of decoding contiguous and non-contiguous. quite a few MDS types do not support both of them. for instance, snapid_t only supports contiguous decoding. so, instead of conditioning on size, in this change, we condition on the traits::need_contiguous. probably we can condition on both of them in a follow-up change. Signed-off-by: Kefu Chai <kchai@redhat.com>
This commit is contained in:
parent
c4544d1514
commit
719758a0d4
@ -1585,12 +1585,16 @@ inline std::enable_if_t<traits::supported && !traits::featured> decode_nohead(
|
||||
return;
|
||||
if (p.end())
|
||||
throw buffer::end_of_buffer();
|
||||
bufferptr tmp;
|
||||
auto t = p;
|
||||
t.copy_shallow(p.get_bl().length() - p.get_off(), tmp);
|
||||
auto cp = std::cbegin(tmp);
|
||||
traits::decode_nohead(num, o, cp);
|
||||
p.advance(cp.get_offset());
|
||||
if constexpr (traits::need_contiguous) {
|
||||
bufferptr tmp;
|
||||
auto t = p;
|
||||
t.copy_shallow(p.get_bl().length() - p.get_off(), tmp);
|
||||
auto cp = std::cbegin(tmp);
|
||||
traits::decode_nohead(num, o, cp);
|
||||
p.advance(cp.get_offset());
|
||||
} else {
|
||||
traits::decode_nohead(num, o, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user