mirror of
https://github.com/scylladb/scylladb.git
synced 2026-05-29 11:10:40 +00:00
managed_bytes: add small string optimization
This commit is contained in:
@@ -30,9 +30,21 @@ struct blob_storage {
|
||||
} __attribute__((packed));
|
||||
|
||||
// A managed version of "bytes" (can be used with LSA).
|
||||
// FIXME: Add small managed_bytes optimization
|
||||
class managed_bytes {
|
||||
blob_storage* _ptr;
|
||||
static constexpr size_t max_inline_size = 15;
|
||||
struct small_blob {
|
||||
bytes_view::value_type data[max_inline_size];
|
||||
int8_t size; // -1 -> use blob_storage
|
||||
};
|
||||
union {
|
||||
blob_storage* ptr;
|
||||
small_blob small;
|
||||
} _u;
|
||||
static_assert(sizeof(small_blob) > sizeof(blob_storage*), "inline size too small");
|
||||
private:
|
||||
bool external() const {
|
||||
return _u.small.size < 0;
|
||||
}
|
||||
public:
|
||||
using size_type = blob_storage::size_type;
|
||||
struct initialized_later {};
|
||||
@@ -45,30 +57,37 @@ public:
|
||||
managed_bytes(const bytes& b) : managed_bytes(static_cast<bytes_view>(b)) {}
|
||||
|
||||
managed_bytes(initialized_later, size_type size) {
|
||||
void* p = current_allocator().alloc(standard_migrator<blob_storage>,
|
||||
sizeof(blob_storage) + size, alignof(blob_storage));
|
||||
new (p) blob_storage(&_ptr, size);
|
||||
if (size <= max_inline_size) {
|
||||
_u.small.size = size;
|
||||
} else {
|
||||
_u.small.size = -1;
|
||||
void* p = current_allocator().alloc(standard_migrator<blob_storage>,
|
||||
sizeof(blob_storage) + size, alignof(blob_storage));
|
||||
new (p) blob_storage(&_u.ptr, size);
|
||||
}
|
||||
}
|
||||
|
||||
managed_bytes(bytes_view v) : managed_bytes(initialized_later(), v.size()) {
|
||||
memcpy(_ptr->data, v.data(), v.size());
|
||||
memcpy(data(), v.data(), v.size());
|
||||
}
|
||||
|
||||
~managed_bytes() {
|
||||
if (_ptr) {
|
||||
current_allocator().destroy(_ptr);
|
||||
if (external()) {
|
||||
current_allocator().destroy(_u.ptr);
|
||||
}
|
||||
}
|
||||
|
||||
managed_bytes(const managed_bytes& o) : managed_bytes(static_cast<bytes_view>(o)) {}
|
||||
|
||||
managed_bytes(managed_bytes&& o) noexcept
|
||||
: _ptr(o._ptr)
|
||||
: _u(o._u)
|
||||
{
|
||||
o._ptr = nullptr;
|
||||
if (_ptr) {
|
||||
_ptr->backref = &_ptr;
|
||||
if (external()) {
|
||||
if (_u.ptr) {
|
||||
_u.ptr->backref = &_u.ptr;
|
||||
}
|
||||
}
|
||||
o._u.small.size = 0;
|
||||
}
|
||||
|
||||
managed_bytes& operator=(managed_bytes&& o) {
|
||||
@@ -92,40 +111,56 @@ public:
|
||||
}
|
||||
|
||||
operator bytes_view() const {
|
||||
return { _ptr->data, _ptr->size };
|
||||
return { data(), size() };
|
||||
}
|
||||
|
||||
bytes_view::value_type& operator[](size_type index) {
|
||||
return _ptr->data[index];
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
const bytes_view::value_type& operator[](size_type index) const {
|
||||
return _ptr->data[index];
|
||||
return data()[index];
|
||||
}
|
||||
|
||||
size_type size() const {
|
||||
return _ptr->size;
|
||||
if (external()) {
|
||||
return _u.ptr->size;
|
||||
} else {
|
||||
return _u.small.size;
|
||||
}
|
||||
}
|
||||
|
||||
const blob_storage::char_type* begin() const {
|
||||
return _ptr->data;
|
||||
return data();
|
||||
}
|
||||
|
||||
const blob_storage::char_type* end() const {
|
||||
return _ptr->data + _ptr->size;
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
blob_storage::char_type* begin() {
|
||||
return _ptr->data;
|
||||
return data();
|
||||
}
|
||||
|
||||
blob_storage::char_type* end() {
|
||||
return _ptr->data + _ptr->size;
|
||||
return data() + size();
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
blob_storage::char_type* data() {
|
||||
if (external()) {
|
||||
return _u.ptr->data;
|
||||
} else {
|
||||
return _u.small.data;
|
||||
}
|
||||
}
|
||||
|
||||
const blob_storage::char_type* data() const {
|
||||
return const_cast<managed_bytes*>(this)->data();
|
||||
}
|
||||
};
|
||||
|
||||
namespace std {
|
||||
|
||||
Reference in New Issue
Block a user