From 724a493adc3375952739926dc01f8e485b663a1e Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 10 Feb 2016 17:42:07 -0500 Subject: [PATCH] buffer: combine data and buffer::raw into single allocation Signed-off-by: Sage Weil --- src/common/buffer.cc | 53 ++++++++++++++++++++++++++++++++++++++++++++ src/include/buffer.h | 2 ++ 2 files changed, 55 insertions(+) diff --git a/src/common/buffer.cc b/src/common/buffer.cc index 3c090e4c29499..80a5d513d43d3 100644 --- a/src/common/buffer.cc +++ b/src/common/buffer.cc @@ -235,6 +235,34 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; } }; + /* + * raw_combined is always placed within a single allocation along + * with the data buffer. the data goes at the beginning, and + * raw_combined at the end. see create_combined. + */ + class buffer::raw_combined : public buffer::raw { + size_t alignment; + public: + raw_combined(char *dataptr, unsigned l, unsigned align=0) + : raw(dataptr, l), + alignment(align) { + inc_total_alloc(len); + } + ~raw_combined() { + dec_total_alloc(len); + } + raw* clone_empty() { + if (alignment) + return create_aligned(len, alignment); + return create(len); + } + + static void operator delete(void *ptr) { + raw_combined *raw = (raw_combined *)ptr; + ::free((void *)raw->data); + } + }; + class buffer::raw_malloc : public buffer::raw { public: explicit raw_malloc(unsigned l) : raw(l) { @@ -654,6 +682,31 @@ static simple_spinlock_t buffer_debug_lock = SIMPLE_SPINLOCK_INITIALIZER; buffer::raw* buffer::create_static(unsigned len, char *buf) { return new raw_static(buf, len); } + + buffer::raw* buffer::create_combined(unsigned len, unsigned align) { + if (!align) + align = sizeof(size_t); + size_t rawlen = ROUND_UP_TO(sizeof(buffer::raw_combined), sizeof(size_t)); + size_t datalen = ROUND_UP_TO(len, sizeof(size_t)); + +#ifdef DARWIN + char *ptr = (char *) valloc(rawlen + datalen); +#else + char *ptr = 0; + int r = ::posix_memalign((void**)(void*)&ptr, align, rawlen + datalen); + if (r) + throw bad_alloc(); +#endif /* DARWIN */ + if (!ptr) + throw bad_alloc(); + + // actual data first, since it has presumably larger alignment restriction + // then put the raw_combined at the end + raw *ret = new (ptr + datalen) raw_combined(ptr, len, align); + assert((char *)ret == ptr + datalen); + return ret; + } + buffer::raw* buffer::create_aligned(unsigned len, unsigned align) { #ifndef __CYGWIN__ //return new raw_mmap_pages(len); diff --git a/src/include/buffer.h b/src/include/buffer.h index c07a82cc26504..81ce336c05a19 100644 --- a/src/include/buffer.h +++ b/src/include/buffer.h @@ -136,6 +136,7 @@ namespace buffer CEPH_BUFFER_API { class raw_char; class raw_pipe; class raw_unshareable; // diagnostic, unshareable char buffer + class raw_combined; class xio_mempool; @@ -150,6 +151,7 @@ namespace buffer CEPH_BUFFER_API { raw* create_malloc(unsigned len); raw* claim_malloc(unsigned len, char *buf); raw* create_static(unsigned len, char *buf); + raw* create_combined(unsigned len, unsigned align=0); raw* create_aligned(unsigned len, unsigned align); raw* create_page_aligned(unsigned len); raw* create_zero_copy(unsigned len, int fd, int64_t *offset); -- 2.39.5