From 719758a0d4a52950aac6148b78a65ffd9e234268 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Tue, 27 Nov 2018 00:00:43 +0800 Subject: [PATCH] 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 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 --- src/include/denc.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/include/denc.h b/src/include/denc.h index d56bf93d861..de74e41faad 100644 --- a/src/include/denc.h +++ b/src/include/denc.h @@ -1585,12 +1585,16 @@ inline std::enable_if_t 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); + } } }