Commit 72fc4f3f authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-22841 ut_new_get_key_by_file is unnecessarily expensive, followup

Make ut_new_get_key_by_file event less expensive
remove binary search, compute auto_event_keys offset at compile time.
parent 7803601d
...@@ -148,6 +148,8 @@ with (), thus: ...@@ -148,6 +148,8 @@ with (), thus:
/** Maximum number of retries to allocate memory. */ /** Maximum number of retries to allocate memory. */
extern const size_t alloc_max_retries; extern const size_t alloc_max_retries;
constexpr uint32_t INVALID_AUTOEVENT_IDX = 0xFFFFFFFFU;
/** Keys for registering allocations with performance schema. /** Keys for registering allocations with performance schema.
Pointers to these variables are supplied to PFS code via the pfs_info[] Pointers to these variables are supplied to PFS code via the pfs_info[]
array and the PFS code initializes them via PSI_MEMORY_CALL(register_memory)(). array and the PFS code initializes them via PSI_MEMORY_CALL(register_memory)().
...@@ -180,11 +182,11 @@ ut_new_boot(); ...@@ -180,11 +182,11 @@ ut_new_boot();
/** /**
Retrieve a memory key (registered with PFS), Retrieve a memory key (registered with PFS),
given filename hash of the caller given AUTOEVENT_IDX of the caller
@param[in] filename_hash - FILENAME_HASH value of the caller @param[in] autoevent_idx - AUTOEVENT_IDX value of the caller
@return registered memory key or PSI_NOT_INSTRUMENTED */ @return registered memory key or PSI_NOT_INSTRUMENTED */
PSI_memory_key ut_new_get_key_by_file(uint32_t filename_hash); PSI_memory_key ut_new_get_key_by_file(uint32_t autoevent_idx);
#endif /* UNIV_PFS_MEMORY */ #endif /* UNIV_PFS_MEMORY */
...@@ -293,7 +295,7 @@ class ut_allocator { ...@@ -293,7 +295,7 @@ class ut_allocator {
) )
{ {
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
const PSI_memory_key other_key = other.get_mem_key(0); const PSI_memory_key other_key = other.get_mem_key();
m_key = (other_key != mem_key_std) m_key = (other_key != mem_key_std)
? other_key ? other_key
...@@ -315,7 +317,7 @@ class ut_allocator { ...@@ -315,7 +317,7 @@ class ut_allocator {
#endif /* UNIV_PFS_MEMORY */ #endif /* UNIV_PFS_MEMORY */
} }
pointer allocate(size_type n) { return allocate(n, NULL, 0); } pointer allocate(size_type n) { return allocate(n, NULL, INVALID_AUTOEVENT_IDX); }
/** Allocate a chunk of memory that can hold 'n_elements' objects of /** Allocate a chunk of memory that can hold 'n_elements' objects of
type 'T' and trace the allocation. type 'T' and trace the allocation.
...@@ -335,7 +337,7 @@ class ut_allocator { ...@@ -335,7 +337,7 @@ class ut_allocator {
const_pointer, const_pointer,
uint32_t uint32_t
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
filename_hash /* filename hash of the caller */ autoevent_idx /* AUTOEVENT_IDX of the caller */
#endif #endif
, ,
bool set_to_zero = false, bool set_to_zero = false,
...@@ -397,7 +399,7 @@ class ut_allocator { ...@@ -397,7 +399,7 @@ class ut_allocator {
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
ut_new_pfx_t* pfx = static_cast<ut_new_pfx_t*>(ptr); ut_new_pfx_t* pfx = static_cast<ut_new_pfx_t*>(ptr);
allocate_trace(total_bytes, filename_hash, pfx); allocate_trace(total_bytes, autoevent_idx, pfx);
return(reinterpret_cast<pointer>(pfx + 1)); return(reinterpret_cast<pointer>(pfx + 1));
#else #else
...@@ -479,7 +481,7 @@ class ut_allocator { ...@@ -479,7 +481,7 @@ class ut_allocator {
reallocate( reallocate(
void* ptr, void* ptr,
size_type n_elements, size_type n_elements,
uint32_t filename_hash) uint32_t autoevent_idx)
{ {
if (n_elements == 0) { if (n_elements == 0) {
deallocate(static_cast<pointer>(ptr)); deallocate(static_cast<pointer>(ptr));
...@@ -487,7 +489,7 @@ class ut_allocator { ...@@ -487,7 +489,7 @@ class ut_allocator {
} }
if (ptr == NULL) { if (ptr == NULL) {
return(allocate(n_elements, NULL, filename_hash, false, false)); return(allocate(n_elements, NULL, autoevent_idx, false, false));
} }
if (n_elements > max_size()) { if (n_elements > max_size()) {
...@@ -530,7 +532,7 @@ class ut_allocator { ...@@ -530,7 +532,7 @@ class ut_allocator {
deallocate_trace(pfx_new); deallocate_trace(pfx_new);
/* pfx_new is set here to describe the new block. */ /* pfx_new is set here to describe the new block. */
allocate_trace(total_bytes, filename_hash, pfx_new); allocate_trace(total_bytes, autoevent_idx, pfx_new);
return(reinterpret_cast<pointer>(pfx_new + 1)); return(reinterpret_cast<pointer>(pfx_new + 1));
} }
...@@ -546,10 +548,10 @@ class ut_allocator { ...@@ -546,10 +548,10 @@ class ut_allocator {
pointer pointer
new_array( new_array(
size_type n_elements, size_type n_elements,
uint32_t filename_hash uint32_t autoevent_idx
) )
{ {
T* p = allocate(n_elements, NULL, filename_hash, false, false); T* p = allocate(n_elements, NULL, autoevent_idx, false, false);
if (p == NULL) { if (p == NULL) {
return(NULL); return(NULL);
...@@ -688,16 +690,16 @@ class ut_allocator { ...@@ -688,16 +690,16 @@ class ut_allocator {
@return performance schema key */ @return performance schema key */
PSI_memory_key PSI_memory_key
get_mem_key( get_mem_key(
uint32_t filename_hash) const uint32_t autoevent_idx = INVALID_AUTOEVENT_IDX) const
{ {
if (m_key != PSI_NOT_INSTRUMENTED) { if (m_key != PSI_NOT_INSTRUMENTED) {
return(m_key); return(m_key);
} }
if (filename_hash == 0) { if (autoevent_idx == INVALID_AUTOEVENT_IDX) {
return(mem_key_std); return(mem_key_std);
} }
const PSI_memory_key key = ut_new_get_key_by_file(filename_hash); const PSI_memory_key key = ut_new_get_key_by_file(autoevent_idx);
if (key != PSI_NOT_INSTRUMENTED) { if (key != PSI_NOT_INSTRUMENTED) {
return(key); return(key);
...@@ -739,16 +741,16 @@ class ut_allocator { ...@@ -739,16 +741,16 @@ class ut_allocator {
corresponds to "file", that will be used (see ut_new_boot()) corresponds to "file", that will be used (see ut_new_boot())
4. Otherwise, the name associated with mem_key_other will be used. 4. Otherwise, the name associated with mem_key_other will be used.
@param[in] size number of bytes that were allocated @param[in] size number of bytes that were allocated
@param[in] filename_hash FILENAME_HASH of the caller @param[in] autoevent_idx autoevent_idx of the caller
@param[out] pfx placeholder to store the info which will be @param[out] pfx placeholder to store the info which will be
needed when freeing the memory */ needed when freeing the memory */
void void
allocate_trace( allocate_trace(
size_t size, size_t size,
const uint32_t filename_hash, const uint32_t autoevent_idx,
ut_new_pfx_t* pfx) ut_new_pfx_t* pfx)
{ {
const PSI_memory_key key = get_mem_key(filename_hash); const PSI_memory_key key = get_mem_key(autoevent_idx);
pfx->m_key = PSI_MEMORY_CALL(memory_alloc)(key, size, & pfx->m_owner); pfx->m_key = PSI_MEMORY_CALL(memory_alloc)(key, size, & pfx->m_owner);
pfx->m_size = size; pfx->m_size = size;
...@@ -801,36 +803,124 @@ operator!=( ...@@ -801,36 +803,124 @@ operator!=(
/* /*
constexpr trickery ahead. constexpr trickery ahead.
Retrieve the FILENAME_HASH = djb2(basename_noext(__FILE__)) at the compile time. Compute AUTOEVENT_IDX at compile time.
We use the number rather than __FILE__ because integers is better to deal with (index in the auto_event_names array, corresponding to basename of __FILE__)
(hashing, searching) that C style strings.
The tricks are necessary to reduce the cost of lookup the
PSI_memory_key for auto event.
*/ */
static constexpr const char * basename_helper(const char* s, const char * last_slash) static constexpr const char* cexpr_basename_helper(const char* s, const char* last_slash)
{ {
return return
*s == '\0' ? last_slash : *s == '\0' ? last_slash :
*s == '/' || *s == '\\' ? basename_helper(s + 1, s + 1) : *s == '/' || *s == '\\' ? cexpr_basename_helper(s + 1, s + 1) :
basename_helper(s + 1, last_slash); cexpr_basename_helper(s + 1, last_slash);
}
static constexpr const char* cexpr_basename(const char* filename)
{
return cexpr_basename_helper(filename, filename);
} }
static constexpr const char* ut_basename(const char *filename) static constexpr bool cexpr_strequal_ignore_dot(const char* a, const char* b)
{ {
return basename_helper(filename, filename); return *a == 0 || *a == '.' ? (*b == 0 || *b == '.')
: *a == *b ? cexpr_strequal_ignore_dot(a + 1, b + 1) : false;
} }
/** Compute djb2 hash for a string. Stop at '.' , or '\0' */ constexpr const char* const auto_event_names[] =
constexpr uint32_t ut_filename_hash(const char *s, uint32_t h= 5381) {
"btr0btr",
"btr0buf",
"btr0bulk",
"btr0cur",
"btr0pcur",
"btr0sea",
"buf0buf",
"buf0dblwr",
"buf0dump",
"dict0dict",
"dict0mem",
"dict0stats",
"eval0eval",
"fil0crypt",
"fil0fil",
"fsp0file",
"fts0ast",
"fts0blex",
"fts0config",
"fts0file",
"fts0fts",
"fts0opt",
"fts0pars",
"fts0que",
"fts0sql",
"fts0tlex",
"gis0sea",
"ha_innodb",
"ha0ha",
"handler0alter",
"hash0hash",
"i_s",
"lexyy",
"lock0lock",
"mem0mem",
"os0event",
"os0file",
"pars0lex",
"rem0rec",
"row0ftsort",
"row0import",
"row0log",
"row0merge",
"row0mysql",
"row0sel",
"srv0start",
"sync0arr",
"sync0debug",
"sync0rw",
"sync0start",
"sync0types",
"trx0i_s",
"trx0i_s",
"trx0roll",
"trx0rseg",
"trx0seg",
"trx0trx",
"trx0undo",
"ut0list",
"ut0mem",
"ut0new",
"ut0pool",
"ut0rbt",
"ut0wqueue",
"xtrabackup",
nullptr
};
constexpr uint32_t cexpr_lookup_auto_event_name(const char* name, uint32_t idx = 0)
{ {
return *s == 0 || *s == '.' ? h : return !auto_event_names[idx] ? INVALID_AUTOEVENT_IDX :
ut_filename_hash(s + 1, static_cast<uint32_t>(uint64_t{33} * h + *s)); cexpr_strequal_ignore_dot(name, auto_event_names[idx]) ? idx :
cexpr_lookup_auto_event_name(name, idx + 1);
} }
/* Force constexpr to be evaluated at compile time.*/ /*
#define FORCE_CONSTEXPR(expr)[&]() \ The AUTOEVENT_IDX macro.
{ static constexpr auto x = (expr); return x; }()
Note, that there is a static_assert that checks whether
basename of the __FILE is not registered in the auto_event_names array.
If you run into this assert, add the basename to the array.
#define FILENAME_HASH FORCE_CONSTEXPR(ut_filename_hash(ut_basename(__FILE__))) Weird looking lambda is used to force the evaluation at the compile time.
*/
#define AUTOEVENT_IDX []()\
{\
constexpr auto idx = cexpr_lookup_auto_event_name(cexpr_basename(__FILE__)); \
static_assert(idx != INVALID_AUTOEVENT_IDX, "auto_event_names contains no entry for " __FILE__);\
return idx; \
}()
/** Allocate, trace the allocation and construct an object. /** Allocate, trace the allocation and construct an object.
...@@ -850,7 +940,7 @@ pointer must be passed to UT_DELETE() when no longer needed. ...@@ -850,7 +940,7 @@ pointer must be passed to UT_DELETE() when no longer needed.
object if the passed in pointer is NULL, e.g. if allocate() has object if the passed in pointer is NULL, e.g. if allocate() has
failed to allocate memory and has returned NULL. */ \ failed to allocate memory and has returned NULL. */ \
::new(ut_allocator<byte>(key).allocate( \ ::new(ut_allocator<byte>(key).allocate( \
sizeof expr, NULL, FILENAME_HASH, false, false)) expr sizeof expr, NULL, AUTOEVENT_IDX, false, false)) expr
/** Allocate, trace the allocation and construct an object. /** Allocate, trace the allocation and construct an object.
Use this macro instead of 'new' within InnoDB and instead of UT_NEW() Use this macro instead of 'new' within InnoDB and instead of UT_NEW()
...@@ -872,6 +962,7 @@ We can't instantiate ut_allocator without having the type of the object, thus ...@@ -872,6 +962,7 @@ We can't instantiate ut_allocator without having the type of the object, thus
we redirect this to a templated function. */ we redirect this to a templated function. */
#define UT_DELETE(ptr) ut_delete(ptr) #define UT_DELETE(ptr) ut_delete(ptr)
/** Destroy and account object created by UT_NEW() or UT_NEW_NOKEY(). /** Destroy and account object created by UT_NEW() or UT_NEW_NOKEY().
@param[in,out] ptr pointer to the object */ @param[in,out] ptr pointer to the object */
template <typename T> template <typename T>
...@@ -898,7 +989,7 @@ The returned pointer must be passed to UT_DELETE_ARRAY(). ...@@ -898,7 +989,7 @@ The returned pointer must be passed to UT_DELETE_ARRAY().
@param[in] key performance schema memory tracing key @param[in] key performance schema memory tracing key
@return pointer to the first allocated object or NULL */ @return pointer to the first allocated object or NULL */
#define UT_NEW_ARRAY(type, n_elements, key) \ #define UT_NEW_ARRAY(type, n_elements, key) \
ut_allocator<type>(key).new_array(n_elements, FILENAME_HASH) ut_allocator<type>(key).new_array(n_elements, AUTOEVENT_IDX)
/** Allocate and account 'n_elements' objects of type 'type'. /** Allocate and account 'n_elements' objects of type 'type'.
Use this macro to allocate memory within InnoDB instead of 'new[]' and Use this macro to allocate memory within InnoDB instead of 'new[]' and
...@@ -929,7 +1020,7 @@ ut_delete_array( ...@@ -929,7 +1020,7 @@ ut_delete_array(
#define ut_malloc(n_bytes, key) static_cast<void*>( \ #define ut_malloc(n_bytes, key) static_cast<void*>( \
ut_allocator<byte>(key).allocate( \ ut_allocator<byte>(key).allocate( \
n_bytes, NULL, FILENAME_HASH, false, false)) n_bytes, NULL, AUTOEVENT_IDX, false, false))
#define ut_malloc_dontdump(n_bytes, key) static_cast<void*>( \ #define ut_malloc_dontdump(n_bytes, key) static_cast<void*>( \
ut_allocator<byte>(key).allocate_large( \ ut_allocator<byte>(key).allocate_large( \
...@@ -937,23 +1028,23 @@ ut_delete_array( ...@@ -937,23 +1028,23 @@ ut_delete_array(
#define ut_zalloc(n_bytes, key) static_cast<void*>( \ #define ut_zalloc(n_bytes, key) static_cast<void*>( \
ut_allocator<byte>(key).allocate( \ ut_allocator<byte>(key).allocate( \
n_bytes, NULL, FILENAME_HASH, true, false)) n_bytes, NULL, AUTOEVENT_IDX, true, false))
#define ut_malloc_nokey(n_bytes) static_cast<void*>( \ #define ut_malloc_nokey(n_bytes) static_cast<void*>( \
ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \ ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \
n_bytes, NULL, FILENAME_HASH, false, false)) n_bytes, NULL, AUTOEVENT_IDX, false, false))
#define ut_zalloc_nokey(n_bytes) static_cast<void*>( \ #define ut_zalloc_nokey(n_bytes) static_cast<void*>( \
ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \ ut_allocator<byte>(PSI_NOT_INSTRUMENTED).allocate( \
n_bytes, NULL, FILENAME_HASH, true, false)) n_bytes, NULL, AUTOEVENT_IDX, true, false))
#define ut_zalloc_nokey_nofatal(n_bytes) static_cast<void*>( \ #define ut_zalloc_nokey_nofatal(n_bytes) static_cast<void*>( \
ut_allocator<byte, false>(PSI_NOT_INSTRUMENTED).allocate( \ ut_allocator<byte, false>(PSI_NOT_INSTRUMENTED).allocate( \
n_bytes, NULL, FILENAME_HASH, true, false)) n_bytes, NULL, AUTOEVENT_IDX, true, false))
#define ut_realloc(ptr, n_bytes) static_cast<void*>( \ #define ut_realloc(ptr, n_bytes) static_cast<void*>( \
ut_allocator<byte>(PSI_NOT_INSTRUMENTED).reallocate( \ ut_allocator<byte>(PSI_NOT_INSTRUMENTED).reallocate( \
ptr, n_bytes, FILENAME_HASH)) ptr, n_bytes, AUTOEVENT_IDX))
#define ut_free(ptr) ut_allocator<byte>(PSI_NOT_INSTRUMENTED).deallocate( \ #define ut_free(ptr) ut_allocator<byte>(PSI_NOT_INSTRUMENTED).deallocate( \
reinterpret_cast<byte*>(ptr)) reinterpret_cast<byte*>(ptr))
......
...@@ -44,175 +44,6 @@ PSI_memory_key mem_key_row_merge_sort; ...@@ -44,175 +44,6 @@ PSI_memory_key mem_key_row_merge_sort;
PSI_memory_key mem_key_std; PSI_memory_key mem_key_std;
#ifdef UNIV_PFS_MEMORY #ifdef UNIV_PFS_MEMORY
static const char* auto_event_names[] =
{
"btr0btr",
"btr0bulk",
"btr0cur",
"btr0defragment",
"btr0pcur",
"btr0sea",
"btr0types",
"buf0buddy",
"buf0buf",
"buf0checksum",
"buf0dblwr",
"buf0dump",
"buf0flu",
"buf0lru",
"buf0rea",
"buf0types",
"data0data",
"data0type",
"data0types",
"db0err",
"dict0boot",
"dict0crea",
"dict0defrag_bg",
"dict0dict",
"dict0load",
"dict0mem",
"dict0pagecompress",
"dict0priv",
"dict0stats",
"dict0stats_bg",
"dict0types",
"dyn0buf",
"dyn0types",
"eval0eval",
"eval0proc",
"fil0crypt",
"fil0fil",
"fil0pagecompress",
"fsp0file",
"fsp0fsp",
"fsp0space",
"fsp0sysspace",
"fsp0types",
"fts0ast",
"fts0blex",
"fts0config",
"fts0fts",
"fts0opt",
"fts0pars",
"fts0plugin",
"fts0priv",
"fts0que",
"fts0sql",
"fts0tlex",
"fts0tokenize",
"fts0types",
"fts0vlc",
"fut0fut",
"fut0lst",
"gis0geo",
"gis0rtree",
"gis0sea",
"gis0type",
"ha0ha",
"ha0storage",
"ha_innodb",
"ha_prototypes",
"handler0alter",
"hash0hash",
"i_s",
"ib0mutex",
"ibuf0ibuf",
"ibuf0types",
"lexyy",
"lock0iter",
"lock0lock",
"lock0prdt",
"lock0priv",
"lock0types",
"lock0wait",
"log0crypt",
"log0log",
"log0recv",
"log0sync",
"log0types",
"mach0data",
"mem0mem",
"mtr0log",
"mtr0mtr",
"mtr0types",
"os0api",
"os0event",
"os0file",
"os0proc",
"os0thread",
"page0cur",
"page0page",
"page0types",
"page0zip",
"pars0grm",
"pars0lex",
"pars0opt",
"pars0pars",
"pars0sym",
"pars0types",
"que0que",
"que0types",
"read0read",
"read0types",
"rem0cmp",
"rem0rec",
"rem0types",
"row0ext",
"row0ftsort",
"row0import",
"row0ins",
"row0log",
"row0merge",
"row0mysql",
"row0purge",
"row0quiesce",
"row0row",
"row0sel",
"row0types",
"row0uins",
"row0umod",
"row0undo",
"row0upd",
"row0vers",
"srv0conc",
"srv0mon",
"srv0srv",
"srv0start",
"sync0arr",
"sync0debug",
"sync0policy",
"sync0rw",
"sync0sync",
"sync0types",
"trx0i_s",
"trx0purge",
"trx0rec",
"trx0roll",
"trx0rseg",
"trx0sys",
"trx0trx",
"trx0types",
"trx0undo",
"trx0xa",
"ut0byte",
"ut0counter",
"ut0crc32",
"ut0dbg",
"ut0list",
"ut0lst",
"ut0mem",
"ut0mutex",
"ut0new",
"ut0pool",
"ut0rbt",
"ut0rnd",
"ut0sort",
"ut0stage",
"ut0ut",
"ut0vec",
"ut0wqueue"
};
/** Auxiliary array of performance schema 'PSI_memory_info'. /** Auxiliary array of performance schema 'PSI_memory_info'.
Each allocation appears in Each allocation appears in
...@@ -240,8 +71,8 @@ static PSI_memory_info pfs_info[] = { ...@@ -240,8 +71,8 @@ static PSI_memory_info pfs_info[] = {
{&mem_key_std, "std", 0}, {&mem_key_std, "std", 0},
}; };
constexpr int NKEYS= static_cast<int>UT_ARR_SIZE(auto_event_names); static const int NKEYS = static_cast<int>UT_ARR_SIZE(auto_event_names)-1;
std::pair<uint32_t, PSI_memory_key> search_array[NKEYS]; static PSI_memory_key auto_event_keys[NKEYS];
/** Setup the internal objects needed for UT_NEW() to operate. /** Setup the internal objects needed for UT_NEW() to operate.
This must be called before the first call to UT_NEW(). */ This must be called before the first call to UT_NEW(). */
...@@ -250,66 +81,26 @@ void ut_new_boot() ...@@ -250,66 +81,26 @@ void ut_new_boot()
PSI_MEMORY_CALL(register_memory)("innodb", pfs_info, static_cast<int> PSI_MEMORY_CALL(register_memory)("innodb", pfs_info, static_cast<int>
UT_ARR_SIZE(pfs_info)); UT_ARR_SIZE(pfs_info));
static PSI_memory_key auto_event_keys[NKEYS]; PSI_memory_info pfs_info_auto[NKEYS];
static PSI_memory_info pfs_info_auto[NKEYS];
for (int i= 0; i < NKEYS; i++) for (int i= 0; i < NKEYS; i++)
{ {
pfs_info_auto[i]= {&auto_event_keys[i], auto_event_names[i], 0}; pfs_info_auto[i]= {&auto_event_keys[i], auto_event_names[i], 0};
} }
PSI_MEMORY_CALL(register_memory)("innodb", pfs_info_auto,NKEYS); PSI_MEMORY_CALL(register_memory)("innodb", pfs_info_auto,NKEYS);
if (auto_event_keys[0] == PSI_NOT_INSTRUMENTED)
return; // PSI is off
for (int i= 0; i < NKEYS; i++)
{
search_array[i]= {ut_filename_hash(auto_event_names[i]), auto_event_keys[i]};
}
std::sort(search_array, std::end(search_array));
#ifdef UNIV_DEBUG
/* assumption that hash value is not 0 in ut0new.h, get_mem_key() */
ut_ad(search_array[0].first);
/* Check for hash duplicates */
for(int i= 0; i < NKEYS-1; i++)
{
if (search_array[i].first == search_array[i + 1].first)
{
// This can only happen if autoevent_names was updated
// previously, or the hash function changed
ib::fatal() << __FILE__ "Duplicates found in filename hashes";
}
}
#endif
} }
/** Retrieve a memory key (registered with PFS), corresponding to source file hash. /** Retrieve a memory key (registered with PFS), corresponding to source file .
@param[in] autoevent_idx - offset to the auto_event_names corresponding to the
file name of the caller.
@param[in] filename_hash - hash value (computed at compile time) of a ut_filename_hash
for a one of the auto_event_names.
@return registered memory key or PSI_NOT_INSTRUMENTED @return registered memory key or PSI_NOT_INSTRUMENTED
*/ */
PSI_memory_key ut_new_get_key_by_file(uint32_t filename_hash) PSI_memory_key ut_new_get_key_by_file(uint32_t autoevent_idx)
{ {
if(search_array[0].second == PSI_NOT_INSTRUMENTED) ut_ad(autoevent_idx < NKEYS);
{ return auto_event_keys[autoevent_idx];
// PSI is off.
return PSI_NOT_INSTRUMENTED;
}
std::pair<uint32, PSI_memory_key> e{ filename_hash, 0 };
auto result= std::lower_bound(search_array, std::end(search_array), e);
if (result != std::end(search_array) && result->first == filename_hash)
return result->second;
#ifdef UNIV_DEBUG
ib::fatal() << __FILE__ " ut_new_get_key_by_file : hash not found";
#endif
return PSI_NOT_INSTRUMENTED;
} }
#else /* UNIV_PFS_MEMORY */ #else /* UNIV_PFS_MEMORY */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment