Skip to content

Commit fdf68f7

Browse files
MyRocks: merge the key packing buffer allocation, annotate m_pack_buffer lifetime (#1446)
Summary: All the key packing buffers in the MyRocks handler have exactly the same lifetime between alloc_key_buffers and free_key_buffers. Thus allocate a single large buffer and point the key packing buffers to offsets inside it, reducing number of calls to the heap allocator on table opening/close code path. Annotate the padding bytes for Valgrind as inaccessible. Add additional handling for m_pack_buffer: since its use it's fully contained in Rdb_key_def::pack_record, annotate it as such. Pull Request resolved: #1446 Differential Revision: D56051395 fbshipit-source-id: f503d56
1 parent 65821ca commit fdf68f7

File tree

4 files changed

+86
-40
lines changed

4 files changed

+86
-40
lines changed

include/memory_debugging.h

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,27 @@
4141
#include <valgrind/memcheck.h>
4242

4343
#define MEM_UNDEFINED(a, len) VALGRIND_MAKE_MEM_UNDEFINED(a, len)
44-
#define MEM_DEFINED_IF_ADDRESSABLE(a, len) \
45-
VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(a, len)
44+
// #define MEM_DEFINED_IF_ADDRESSABLE(a, len) \
45+
// VALGRIND_MAKE_MEM_DEFINED_IF_ADDRESSABLE(a, len)
4646
#define MEM_NOACCESS(a, len) VALGRIND_MAKE_MEM_NOACCESS(a, len)
4747
#define MEM_CHECK_ADDRESSABLE(a, len) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a, len)
4848

49+
#elif defined(HAVE_ASAN)
50+
51+
#include <cassert>
52+
#include <sanitizer/asan_interface.h>
53+
54+
#define MEM_MALLOCLIKE_BLOCK(p1, p2, p3, p4) ASAN_UNPOISON_MEMORY_REGION(p1, p2)
55+
#define MEM_FREELIKE_BLOCK(p1, p2, p3, p4) ASAN_POISON_MEMORY_REGION(p1, p2)
56+
57+
#define MEM_UNDEFINED(a, len) ASAN_UNPOISON_MEMORY_REGION(a, len)
58+
#define MEM_NOACCESS(a, len) ASAN_POISON_MEMORY_REGION(a, len)
59+
60+
// In the case of error, this will immediatelly terminate the process instead of
61+
// printing an error and continuing, which is more common for ASan errors.
62+
// Change it to log and continue if that becomes an issue.
63+
#define MEM_CHECK_ADDRESSABLE(a, len) assert(!__asan_region_is_poisoned(a, len))
64+
4965
#else /* HAVE_VALGRIND */
5066

5167
#define MEM_MALLOCLIKE_BLOCK(p1, p2, p3, p4) \
@@ -55,13 +71,18 @@
5571
do { \
5672
} while (0)
5773
#define MEM_UNDEFINED(a, len) ((void)0)
58-
#define MEM_DEFINED_IF_ADDRESSABLE(a, len) ((void)0)
74+
// #define MEM_DEFINED_IF_ADDRESSABLE(a, len) ((void)0)
5975
#define MEM_NOACCESS(a, len) ((void)0)
6076
#define MEM_CHECK_ADDRESSABLE(a, len) ((void)0)
6177

62-
#endif
78+
#endif /* HAVE_VALGRIND */
79+
80+
// Not used in the current sources. If it starts being used after a rebase,
81+
// somehow implement it (could be an unconditional unpoison?) for the HAVE_ASAN
82+
// case above.
83+
#pragma GCC poison MEM_DEFINED_IF_ADDRESSABLE
6384

64-
#if !defined(NDEBUG) || defined(HAVE_VALGRIND)
85+
#if !defined(NDEBUG) || defined(HAVE_VALGRIND) || defined(HAVE_ASAN)
6586

6687
/**
6788
Put bad content in memory to be sure it will segfault if dereferenced.

storage/rocksdb/ha_rocksdb.cc

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9364,15 +9364,22 @@ int ha_rocksdb::convert_record_from_storage_format(
93649364
: rc;
93659365
}
93669366

9367+
static constexpr std::size_t get_next_aligned(std::size_t &offset) {
9368+
constexpr auto bits_below_alignment = alignof(std::max_align_t) - 1;
9369+
constexpr auto bits_above_alignment = ~bits_below_alignment;
9370+
9371+
const auto padding =
9372+
((offset + bits_below_alignment) & bits_above_alignment) - offset;
9373+
offset += padding;
9374+
9375+
return padding;
9376+
}
9377+
93679378
int ha_rocksdb::alloc_key_buffers(const TABLE &table_arg,
93689379
const Rdb_tbl_def &tbl_def_arg) {
93699380
DBUG_ENTER_FUNC();
93709381

93719382
std::shared_ptr<Rdb_key_def> *const kd_arr = tbl_def_arg.m_key_descr_arr;
9372-
9373-
uint max_packed_sk_len = 0;
9374-
uint pack_key_len = 0;
9375-
93769383
m_pk_descr = kd_arr[pk_index(table_arg, tbl_def_arg)];
93779384

93789385
// move this into get_table_handler() ??
@@ -9381,12 +9388,11 @@ int ha_rocksdb::alloc_key_buffers(const TABLE &table_arg,
93819388
return rtn;
93829389
}
93839390

9384-
pack_key_len = m_pk_descr->max_storage_fmt_length();
9385-
m_pk_packed_tuple = reinterpret_cast<uchar *>(
9386-
my_malloc(PSI_NOT_INSTRUMENTED, pack_key_len, MYF(0)));
9391+
const auto pack_key_len = m_pk_descr->max_storage_fmt_length();
9392+
auto buf_size = static_cast<std::size_t>(pack_key_len);
93879393

93889394
/* Sometimes, we may use m_sk_packed_tuple for storing packed PK */
9389-
max_packed_sk_len = pack_key_len;
9395+
auto max_packed_sk_len = pack_key_len;
93909396
for (uint i = 0; i < table_arg.s->keys; i++) {
93919397
/* Primary key was processed above */
93929398
if (i == table_arg.s->primary_key) continue;
@@ -9403,48 +9409,57 @@ int ha_rocksdb::alloc_key_buffers(const TABLE &table_arg,
94039409
}
94049410
}
94059411

9406-
m_sk_packed_tuple = reinterpret_cast<uchar *>(
9407-
my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0)));
9408-
m_sk_packed_tuple_old = reinterpret_cast<uchar *>(
9409-
my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0)));
9410-
m_sk_packed_tuple_updated = reinterpret_cast<uchar *>(
9411-
my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0)));
9412-
m_end_key_packed_tuple = reinterpret_cast<uchar *>(
9413-
my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0)));
9414-
m_pack_buffer = reinterpret_cast<uchar *>(
9415-
my_malloc(PSI_NOT_INSTRUMENTED, max_packed_sk_len, MYF(0)));
9412+
const auto pad1 [[maybe_unused]] = get_next_aligned(buf_size);
9413+
const auto m_sk_packed_tuple_offset = buf_size;
9414+
buf_size += max_packed_sk_len;
9415+
9416+
const auto pad2 [[maybe_unused]] = get_next_aligned(buf_size);
9417+
const auto m_sk_packed_tuple_old_offset = buf_size;
9418+
buf_size += max_packed_sk_len;
9419+
9420+
const auto pad3 [[maybe_unused]] = get_next_aligned(buf_size);
9421+
const auto m_sk_packed_tuple_updated_offset = buf_size;
9422+
buf_size += max_packed_sk_len;
94169423

9417-
if (m_pk_packed_tuple == nullptr || m_sk_packed_tuple == nullptr ||
9418-
m_sk_packed_tuple_old == nullptr ||
9419-
m_sk_packed_tuple_updated == nullptr ||
9420-
m_end_key_packed_tuple == nullptr || m_pack_buffer == nullptr) {
9421-
// One or more of the above allocations failed. Clean up and exit
9424+
const auto pad4 [[maybe_unused]] = get_next_aligned(buf_size);
9425+
const auto m_end_key_packed_tuple_offset = buf_size;
9426+
buf_size += max_packed_sk_len;
9427+
9428+
const auto pad5 [[maybe_unused]] = get_next_aligned(buf_size);
9429+
const auto m_pack_buffer_offset = buf_size;
9430+
buf_size += max_packed_sk_len;
9431+
9432+
buffers.reset(static_cast<uchar *>(
9433+
my_malloc(PSI_NOT_INSTRUMENTED, buf_size, MYF(0))));
9434+
if (buffers == nullptr) {
94229435
free_key_buffers();
94239436

94249437
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
94259438
}
94269439

9440+
m_pk_packed_tuple = buffers.get();
9441+
MEM_NOACCESS(m_pk_packed_tuple + pack_key_len, pad1);
9442+
m_sk_packed_tuple = buffers.get() + m_sk_packed_tuple_offset;
9443+
MEM_NOACCESS(m_sk_packed_tuple + max_packed_sk_len, pad2);
9444+
m_sk_packed_tuple_old = buffers.get() + m_sk_packed_tuple_old_offset;
9445+
MEM_NOACCESS(m_sk_packed_tuple_old + max_packed_sk_len, pad3);
9446+
m_sk_packed_tuple_updated = buffers.get() + m_sk_packed_tuple_updated_offset;
9447+
MEM_NOACCESS(m_sk_packed_tuple_updated + max_packed_sk_len, pad4);
9448+
m_end_key_packed_tuple = buffers.get() + m_end_key_packed_tuple_offset;
9449+
MEM_NOACCESS(m_end_key_packed_tuple + max_packed_sk_len, pad5);
9450+
m_pack_buffer = buffers.get() + m_pack_buffer_offset;
9451+
94279452
DBUG_RETURN(HA_EXIT_SUCCESS);
94289453
}
94299454

94309455
void ha_rocksdb::free_key_buffers() {
9431-
my_free(m_pk_packed_tuple);
94329456
m_pk_packed_tuple = nullptr;
9433-
9434-
my_free(m_sk_packed_tuple);
94359457
m_sk_packed_tuple = nullptr;
9436-
9437-
my_free(m_sk_packed_tuple_old);
94389458
m_sk_packed_tuple_old = nullptr;
9439-
9440-
my_free(m_sk_packed_tuple_updated);
94419459
m_sk_packed_tuple_updated = nullptr;
9442-
9443-
my_free(m_end_key_packed_tuple);
94449460
m_end_key_packed_tuple = nullptr;
9445-
9446-
my_free(m_pack_buffer);
94479461
m_pack_buffer = nullptr;
9462+
buffers.reset();
94489463

94499464
release_blob_buffer();
94509465
}

storage/rocksdb/ha_rocksdb.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,14 @@ class ha_rocksdb : public my_core::handler, public blob_buffer {
194194
*/
195195
mutable bool m_pk_can_be_decoded;
196196

197+
// The common buffer for m_pk_packed_tuple, m_sk_packed_tuple,
198+
// m_sk_packed_tuple_old, m_sk_packed_tuple_updated, m_end_key_packed_tuple,
199+
// & m_pack_buffer.
200+
unique_ptr_my_free<uchar[]> buffers;
201+
197202
uchar *m_pk_packed_tuple; /* Buffer for storing PK in StorageFormat */
198-
// ^^ todo: change it to 'char*'? TODO: ^ can we join this with last_rowkey?
203+
// TODO: ^ can we join this with last_rowkey?
204+
// ^^ todo: change it to 'char[]'?
199205

200206
/*
201207
Temporary buffers for storing the key part of the Key/Value pair

storage/rocksdb/rdb_datadic.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,8 @@ uint Rdb_key_def::pack_record(const TABLE *const tbl, uchar *const pack_buffer,
13201320
assert_IMP(should_store_row_debug_checksums,
13211321
(m_index_type == INDEX_TYPE_SECONDARY));
13221322

1323+
MEM_UNDEFINED(pack_buffer, max_storage_fmt_length());
1324+
13231325
uchar *tuple = packed_tuple;
13241326
size_t unpack_start_pos = size_t(-1);
13251327
size_t unpack_len_pos = size_t(-1);
@@ -1471,6 +1473,8 @@ uint Rdb_key_def::pack_record(const TABLE *const tbl, uchar *const pack_buffer,
14711473

14721474
assert(is_storage_available(tuple - packed_tuple, 0));
14731475

1476+
MEM_NOACCESS(pack_buffer, max_storage_fmt_length());
1477+
14741478
return tuple - packed_tuple;
14751479
}
14761480

0 commit comments

Comments
 (0)