summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2020-11-05 05:52:20 +0300
committerAleksey Midenkov <midenok@gmail.com>2021-04-23 12:17:53 +0300
commit7946754f2c6265d69d0cc59afb11db3fe60b7e88 (patch)
treec7e15f60d7545c8fc305b2dc98e88ee1251ed549
parent40fec7c81600b20bd3fc0487cd77a18feca6f286 (diff)
downloadmariadb-git-bb-10.2-midenok-MDEV-18734.tar.gz
MDEV-18734 malloc optimization for m_ordered_rootbb-10.2-midenok-MDEV-18734
- Does 1 malloc when allocating from m_ordered_root; - init_prealloc_root() interface with user-friendly block_size/prealloc_size parameters.
-rw-r--r--include/my_sys.h2
-rw-r--r--mysys/my_alloc.c19
-rw-r--r--sql/ha_partition.cc27
3 files changed, 44 insertions, 4 deletions
diff --git a/include/my_sys.h b/include/my_sys.h
index ac1730eeaff..6a4a321162f 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -900,6 +900,8 @@ extern void my_free_lock(void *ptr);
#define clear_alloc_root(A) do { (A)->free= (A)->used= (A)->pre_alloc= 0; (A)->min_malloc=0;} while(0)
extern void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
size_t pre_alloc_size, myf my_flags);
+extern void init_prealloc_root(MEM_ROOT *mem_root, size_t block_size,
+ size_t prealloc_size, myf my_flags);
extern void *alloc_root(MEM_ROOT *mem_root, size_t Size);
extern void *multi_alloc_root(MEM_ROOT *mem_root, ...);
extern void free_root(MEM_ROOT *root, myf MyFLAGS);
diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c
index d67b8be9bb8..a20f2969c46 100644
--- a/mysys/my_alloc.c
+++ b/mysys/my_alloc.c
@@ -89,6 +89,25 @@ void init_alloc_root(MEM_ROOT *mem_root, size_t block_size,
DBUG_VOID_RETURN;
}
+void init_prealloc_root(MEM_ROOT *mem_root, size_t block_size,
+ size_t prealloc_size, myf my_flags)
+{
+ size_t pre_alloc;
+ init_alloc_root(mem_root, block_size + ALLOC_ROOT_MIN_BLOCK_SIZE, 0, my_flags);
+ if (!prealloc_size)
+ return;
+ pre_alloc= prealloc_size + (prealloc_size / block_size + 1) * ALLOC_ROOT_MIN_BLOCK_SIZE;
+ if ((mem_root->free= mem_root->pre_alloc=
+ (USED_MEM*) my_malloc(pre_alloc + ALIGN_SIZE(sizeof(USED_MEM)),
+ MYF(my_flags))))
+ {
+ mem_root->free->size= pre_alloc + ALIGN_SIZE(sizeof(USED_MEM));
+ mem_root->free->left= pre_alloc;
+ mem_root->free->next= 0;
+ TRASH_MEM(mem_root->free);
+ }
+}
+
/*
SYNOPSIS
reset_root_defaults()
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index cdd17efaa20..fe9c0033262 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5132,7 +5132,20 @@ bool ha_partition::init_record_priority_queue()
/* Allocate a key for temporary use when setting up the scan. */
alloc_len+= table_share->max_key_length;
- init_alloc_root(&m_ordered_root, 512, 0, MYF(MY_WME));
+ size_t storage_size;
+ if (table->s->blob_fields)
+ {
+ size_t block_size, prealloc_size;
+ storage_size= table->s->blob_fields * sizeof(Ordered_blob_storage *);
+ block_size= storage_size < sizeof(Ordered_blob_storage) ?
+ storage_size : sizeof(Ordered_blob_storage);
+ prealloc_size= alloc_len + used_parts * (storage_size +
+ table->s->blob_fields * sizeof(Ordered_blob_storage));
+ DBUG_ASSERT(block_size > 0);
+ init_prealloc_root(&m_ordered_root, block_size, prealloc_size, MYF(MY_WME));
+ }
+ else
+ init_prealloc_root(&m_ordered_root, alloc_len, 0, MYF(MY_WME));
if (!(m_ordered_rec_buffer= (uchar*) alloc_root(&m_ordered_root, alloc_len)))
DBUG_RETURN(true);
@@ -5154,9 +5167,15 @@ bool ha_partition::init_record_priority_queue()
if (table->s->blob_fields)
{
Ordered_blob_storage **blob_storage= (Ordered_blob_storage **)
- alloc_root(&m_ordered_root, table->s->blob_fields * sizeof(Ordered_blob_storage *));
- for (uint i= 0; i < table->s->blob_fields; ++i)
- blob_storage[i]= new (&m_ordered_root) Ordered_blob_storage;
+ alloc_root(&m_ordered_root, storage_size);
+ if (!blob_storage)
+ DBUG_RETURN(true);
+ for (uint j= 0; j < table->s->blob_fields; ++j)
+ {
+ blob_storage[j]= new (&m_ordered_root) Ordered_blob_storage;
+ if (!blob_storage[j])
+ DBUG_RETURN(true);
+ }
*((Ordered_blob_storage ***) ptr)= blob_storage;
}
int2store(ptr + sizeof(String **), i);