mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
MDEV-30289: Implement small_vector for mtr_t::m_memo
To avoid heap memory allocation overhead for mtr_t::m_memo, we will allocate a small number of elements statically in mtr_t::m_memo::small. Only if that preallocated data is insufficient, we will invoke my_alloc() or my_realloc() for more storage. The implementation of the data structure is inspired by llvm::SmallVector.
This commit is contained in:
parent
7fa5cce305
commit
67dc8af2a7
4 changed files with 120 additions and 5 deletions
|
@ -344,12 +344,14 @@ SET(INNOBASE_SOURCES
|
|||
include/row0upd.inl
|
||||
include/row0vers.h
|
||||
include/rw_lock.h
|
||||
include/small_vector.h
|
||||
include/srv0mon.h
|
||||
include/srv0mon.inl
|
||||
include/srv0srv.h
|
||||
include/srv0start.h
|
||||
include/srw_lock.h
|
||||
include/sux_lock.h
|
||||
include/transactional_lock_guard.h
|
||||
include/trx0i_s.h
|
||||
include/trx0purge.h
|
||||
include/trx0rec.h
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2013, 2022, MariaDB Corporation.
|
||||
Copyright (c) 2013, 2023, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -29,7 +29,7 @@ Created 11/26/1995 Heikki Tuuri
|
|||
#include "fil0fil.h"
|
||||
#include "dyn0buf.h"
|
||||
#include "buf0buf.h"
|
||||
#include <vector>
|
||||
#include "small_vector.h"
|
||||
|
||||
/** Start a mini-transaction. */
|
||||
#define mtr_start(m) (m)->start()
|
||||
|
@ -790,7 +790,7 @@ private:
|
|||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */
|
||||
std::vector<mtr_memo_slot_t> m_memo;
|
||||
small_vector<mtr_memo_slot_t, 16> m_memo;
|
||||
|
||||
/** mini-transaction log */
|
||||
mtr_buf_t m_log;
|
||||
|
|
97
storage/innobase/include/small_vector.h
Normal file
97
storage/innobase/include/small_vector.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2023, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
/* A normally small vector, inspired by llvm::SmallVector */
|
||||
#include "my_global.h"
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
class small_vector_base
|
||||
{
|
||||
protected:
|
||||
typedef uint32_t Size_T;
|
||||
void *BeginX;
|
||||
Size_T Size= 0, Capacity;
|
||||
small_vector_base()= delete;
|
||||
small_vector_base(void *small, size_t small_size)
|
||||
: BeginX(small), Capacity(Size_T(small_size)) {}
|
||||
ATTRIBUTE_COLD void grow_by_1(void *small, size_t element_size);
|
||||
public:
|
||||
size_t size() const { return Size; }
|
||||
size_t capacity() const { return Capacity; }
|
||||
bool empty() const { return !Size; }
|
||||
void clear() { Size= 0; }
|
||||
protected:
|
||||
void set_size(size_t N) { Size= Size_T(N); }
|
||||
};
|
||||
|
||||
template <typename T, unsigned N>
|
||||
class small_vector : public small_vector_base
|
||||
{
|
||||
/** The fixed storage allocation */
|
||||
T small[N];
|
||||
|
||||
using small_vector_base::set_size;
|
||||
|
||||
void grow_if_needed()
|
||||
{
|
||||
if (unlikely(size() >= capacity()))
|
||||
grow_by_1(small, sizeof *small);
|
||||
}
|
||||
|
||||
public:
|
||||
small_vector() : small_vector_base(small, N)
|
||||
{
|
||||
TRASH_ALLOC(small, sizeof small);
|
||||
}
|
||||
~small_vector()
|
||||
{
|
||||
if (small != begin())
|
||||
my_free(begin());
|
||||
MEM_MAKE_ADDRESSABLE(small, sizeof small);
|
||||
}
|
||||
|
||||
using iterator= T *;
|
||||
using const_iterator= const T *;
|
||||
using reverse_iterator= std::reverse_iterator<iterator>;
|
||||
using reference= T &;
|
||||
|
||||
iterator begin() { return static_cast<iterator>(BeginX); }
|
||||
const_iterator begin() const { return static_cast<const_iterator>(BeginX); }
|
||||
iterator end() { return begin() + size(); }
|
||||
const_iterator end() const { return begin() + size(); }
|
||||
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
|
||||
reference operator[](size_t i) { assert(i < size()); return begin()[i]; }
|
||||
|
||||
void erase(const_iterator S, const_iterator E)
|
||||
{
|
||||
set_size(std::move(const_cast<iterator>(E), end(),
|
||||
const_cast<iterator>(S)) - begin());
|
||||
}
|
||||
|
||||
void emplace_back(T &&arg)
|
||||
{
|
||||
grow_if_needed();
|
||||
::new (end()) T(arg);
|
||||
set_size(size() + 1);
|
||||
}
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2017, 2022, MariaDB Corporation.
|
||||
Copyright (c) 2017, 2023, MariaDB Corporation.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free Software
|
||||
|
@ -542,7 +542,7 @@ void mtr_t::release(const void *object)
|
|||
ut_ad(it != m_memo.end());
|
||||
ut_ad(!(it->type & MTR_MEMO_MODIFY));
|
||||
it->release();
|
||||
m_memo.erase(it);
|
||||
m_memo.erase(it, it + 1);
|
||||
ut_ad(std::find_if(m_memo.begin(), m_memo.end(),
|
||||
[object](const mtr_memo_slot_t& slot)
|
||||
{ return slot.object == &object; }) == m_memo.end());
|
||||
|
@ -1235,3 +1235,19 @@ void mtr_t::free(const fil_space_t &space, uint32_t offset)
|
|||
m_log.close(log_write<FREE_PAGE>(id, nullptr));
|
||||
}
|
||||
}
|
||||
|
||||
void small_vector_base::grow_by_1(void *small, size_t element_size)
|
||||
{
|
||||
const size_t cap= Capacity*= 2, s= cap * element_size;
|
||||
void *new_begin;
|
||||
if (BeginX == small)
|
||||
{
|
||||
new_begin= my_malloc(PSI_NOT_INSTRUMENTED, s, MYF(0));
|
||||
memcpy(new_begin, BeginX, size() * element_size);
|
||||
TRASH_FREE(small, size() * element_size);
|
||||
}
|
||||
else
|
||||
new_begin= my_realloc(PSI_NOT_INSTRUMENTED, BeginX, s, MYF(0));
|
||||
|
||||
BeginX= new_begin;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue