summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2023-01-19 16:10:29 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2023-01-19 16:10:29 +0200
commit67dc8af2a75a70df50f76119ed4bfafcf60548c4 (patch)
treec94c9f005bfb50f17e450066f0f3ee5082e8f96f
parent7fa5cce305df0fd4d938c047a80b998bb261f956 (diff)
downloadmariadb-git-67dc8af2a75a70df50f76119ed4bfafcf60548c4.tar.gz
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.
-rw-r--r--storage/innobase/CMakeLists.txt2
-rw-r--r--storage/innobase/include/mtr0mtr.h6
-rw-r--r--storage/innobase/include/small_vector.h97
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc20
4 files changed, 120 insertions, 5 deletions
diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt
index d655cf81231..c250f17147f 100644
--- a/storage/innobase/CMakeLists.txt
+++ b/storage/innobase/CMakeLists.txt
@@ -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
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 84e78ffc083..41f9b473856 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.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;
diff --git a/storage/innobase/include/small_vector.h b/storage/innobase/include/small_vector.h
new file mode 100644
index 00000000000..76069cfc168
--- /dev/null
+++ b/storage/innobase/include/small_vector.h
@@ -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);
+ }
+};
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 834d425a73d..730914b2892 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -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;
+}