From 0cd2e6c61478baf91235a66f0357974a26f02ece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Thu, 14 Apr 2022 10:06:34 +0300 Subject: MDEV-28313: InnoDB transactions are not aligned at cache lines trx_lock_t: Remove byte pad[256] and use alignas(CPU_LEVEL1_DCACHE_LINESIZE) instead. trx_t: Declare n_ref (the first member) aligned at cache line. Pool: Assert that the sizes are multiples of CPU_LEVEL1_DCACHE_LINESIZE, and invoke an aligned allocator. --- storage/innobase/include/trx0sys.h | 2 +- storage/innobase/include/trx0trx.h | 15 ++++++++------- storage/innobase/include/ut0pool.h | 25 ++++++++++++++++++------- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index cbac3fd3a94..aa3cdd6a24b 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2021, MariaDB Corporation. +Copyright (c) 2017, 2022, 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 diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 6b9ffdc6374..2fd04353a2b 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -387,13 +387,13 @@ struct trx_lock_t only be modified by the thread that is serving the running transaction. */ - /** Pre-allocated record locks */ - struct { - ib_lock_t lock; byte pad[256]; - } rec_pool[8]; + /** Pre-allocated record locks */ + struct { + alignas(CPU_LEVEL1_DCACHE_LINESIZE) ib_lock_t lock; + } rec_pool[8]; - /** Pre-allocated table locks */ - ib_lock_t table_pool[8]; + /** Pre-allocated table locks */ + ib_lock_t table_pool[8]; /** Memory heap for trx_locks. Protected by lock_sys.assert_locked() and lock_sys.is_writer() || trx->mutex_is_owner(). */ @@ -583,6 +583,7 @@ private: that it is no longer "active". */ + alignas(CPU_LEVEL1_DCACHE_LINESIZE) Atomic_counter n_ref; @@ -698,7 +699,7 @@ public: /** The locks of the transaction. Protected by lock_sys.latch (insertions also by trx_t::mutex). */ - trx_lock_t lock; + alignas(CPU_LEVEL1_DCACHE_LINESIZE) trx_lock_t lock; #ifdef WITH_WSREP /** whether wsrep_on(mysql_thd) held at the start of transaction */ diff --git a/storage/innobase/include/ut0pool.h b/storage/innobase/include/ut0pool.h index 41b02e0a985..ccea69fe549 100644 --- a/storage/innobase/include/ut0pool.h +++ b/storage/innobase/include/ut0pool.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2018, 2020, MariaDB Corporation. +Copyright (c) 2018, 2022, 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 @@ -31,7 +31,7 @@ Created 2012-Feb-26 Sunny Bains #include #include -#include "ut0new.h" +#include /** Allocate the memory for the object in blocks. We keep the objects sorted on pointer so that they are closer together in case they have to be iterated @@ -41,8 +41,6 @@ struct Pool { typedef Type value_type; - // FIXME: Add an assertion to check alignment and offset is - // as we expect it. Also, sizeof(void*) can be 8, can we impove on this. struct Element { Pool* m_pool; value_type m_type; @@ -57,17 +55,30 @@ struct Pool { m_size(size), m_last() { + ut_ad(ut_is_2pow(size)); ut_a(size >= sizeof(Element)); + static_assert(!(sizeof(Element) % CPU_LEVEL1_DCACHE_LINESIZE), + "alignment"); m_lock_strategy.create(); ut_a(m_start == 0); - m_start = reinterpret_cast(ut_zalloc_nokey(m_size)); +#ifdef _MSC_VER + m_start = static_cast( + _aligned_malloc(m_size, CPU_LEVEL1_DCACHE_LINESIZE)); +#else + void* start; + ut_a(!posix_memalign(&start, CPU_LEVEL1_DCACHE_LINESIZE, + m_size)); + m_start = static_cast(start); +#endif + memset_aligned( + m_start, 0, m_size); m_last = m_start; - m_end = &m_start[m_size / sizeof(*m_start)]; + m_end = &m_start[m_size / sizeof *m_start]; /* Note: Initialise only a small subset, even though we have allocated all the memory. This is required only because PFS @@ -90,7 +101,7 @@ struct Pool { Factory::destroy(&elem->m_type); } - ut_free(m_start); + IF_WIN(_aligned_free,free)(m_start); m_end = m_last = m_start = 0; m_size = 0; } -- cgit v1.2.1