Commit 67dc8af2 authored by Marko Mäkelä's avatar Marko Mäkelä

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.
parent 7fa5cce3
...@@ -344,12 +344,14 @@ SET(INNOBASE_SOURCES ...@@ -344,12 +344,14 @@ SET(INNOBASE_SOURCES
include/row0upd.inl include/row0upd.inl
include/row0vers.h include/row0vers.h
include/rw_lock.h include/rw_lock.h
include/small_vector.h
include/srv0mon.h include/srv0mon.h
include/srv0mon.inl include/srv0mon.inl
include/srv0srv.h include/srv0srv.h
include/srv0start.h include/srv0start.h
include/srw_lock.h include/srw_lock.h
include/sux_lock.h include/sux_lock.h
include/transactional_lock_guard.h
include/trx0i_s.h include/trx0i_s.h
include/trx0purge.h include/trx0purge.h
include/trx0rec.h include/trx0rec.h
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -29,7 +29,7 @@ Created 11/26/1995 Heikki Tuuri ...@@ -29,7 +29,7 @@ Created 11/26/1995 Heikki Tuuri
#include "fil0fil.h" #include "fil0fil.h"
#include "dyn0buf.h" #include "dyn0buf.h"
#include "buf0buf.h" #include "buf0buf.h"
#include <vector> #include "small_vector.h"
/** Start a mini-transaction. */ /** Start a mini-transaction. */
#define mtr_start(m) (m)->start() #define mtr_start(m) (m)->start()
...@@ -790,7 +790,7 @@ struct mtr_t { ...@@ -790,7 +790,7 @@ struct mtr_t {
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/** acquired dict_index_t::lock, fil_space_t::latch, buf_block_t */ /** 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 */ /** mini-transaction log */
mtr_buf_t m_log; mtr_buf_t m_log;
......
/*****************************************************************************
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);
}
};
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. 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 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 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) ...@@ -542,7 +542,7 @@ void mtr_t::release(const void *object)
ut_ad(it != m_memo.end()); ut_ad(it != m_memo.end());
ut_ad(!(it->type & MTR_MEMO_MODIFY)); ut_ad(!(it->type & MTR_MEMO_MODIFY));
it->release(); it->release();
m_memo.erase(it); m_memo.erase(it, it + 1);
ut_ad(std::find_if(m_memo.begin(), m_memo.end(), ut_ad(std::find_if(m_memo.begin(), m_memo.end(),
[object](const mtr_memo_slot_t& slot) [object](const mtr_memo_slot_t& slot)
{ return slot.object == &object; }) == m_memo.end()); { return slot.object == &object; }) == m_memo.end());
...@@ -1235,3 +1235,19 @@ void mtr_t::free(const fil_space_t &space, uint32_t offset) ...@@ -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)); 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;
}
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