Skip to content

Commit 7f301a8

Browse files
committed
Bug#18846682: REPLACE MALLOC+MEMSET WITH CALLOC
Use calloc() rather than malloc() + memset(..., 0, ...). Microbenchmark shows this is faster for both glibc malloc and jemalloc.
1 parent 0a1edf4 commit 7f301a8

File tree

12 files changed

+143
-33
lines changed

12 files changed

+143
-33
lines changed

mysys/my_malloc.c

+6-3
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,11 @@ void *my_raw_malloc(size_t size, myf my_flags)
154154
if (!size)
155155
size=1;
156156

157-
point= malloc(size);
157+
if (my_flags & MY_ZEROFILL)
158+
point= calloc(size, 1);
159+
else
160+
point= malloc(size);
161+
158162
DBUG_EXECUTE_IF("simulate_out_of_memory",
159163
{
160164
free(point);
@@ -179,8 +183,7 @@ void *my_raw_malloc(size_t size, myf my_flags)
179183
if (my_flags & MY_FAE)
180184
exit(1);
181185
}
182-
else if (my_flags & MY_ZEROFILL)
183-
memset(point, 0, size);
186+
184187
DBUG_PRINT("exit",("ptr: %p", point));
185188
DBUG_RETURN(point);
186189
}

storage/innobase/fts/fts0ast.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@ fts_ast_node_create(void)
5050
{
5151
fts_ast_node_t* node;
5252

53-
node = (fts_ast_node_t*) ut_malloc(sizeof(*node));
54-
memset(node, 0x0, sizeof(*node));
53+
node = (fts_ast_node_t*) ut_zalloc(sizeof(*node));
5554

5655
return(node);
5756
}

storage/innobase/fts/fts0que.cc

+3-7
Original file line numberDiff line numberDiff line change
@@ -3675,9 +3675,7 @@ fts_query_prepare_result(
36753675
bool result_is_null = false;
36763676

36773677
if (result == NULL) {
3678-
result = static_cast<fts_result_t*>(ut_malloc(sizeof(*result)));
3679-
3680-
memset(result, 0x0, sizeof(*result));
3678+
result = static_cast<fts_result_t*>(ut_zalloc(sizeof(*result)));
36813679

36823680
result->rankings_by_id = rbt_create(
36833681
sizeof(fts_ranking_t), fts_ranking_doc_id_cmp);
@@ -3781,8 +3779,7 @@ fts_query_get_result(
37813779
result = fts_query_prepare_result(query, result);
37823780
} else {
37833781
/* Create an empty result instance. */
3784-
result = static_cast<fts_result_t*>(ut_malloc(sizeof(*result)));
3785-
memset(result, 0, sizeof(*result));
3782+
result = static_cast<fts_result_t*>(ut_zalloc(sizeof(*result)));
37863783
}
37873784

37883785
return(result);
@@ -4185,8 +4182,7 @@ fts_query(
41854182
} else {
41864183
/* still return an empty result set */
41874184
*result = static_cast<fts_result_t*>(
4188-
ut_malloc(sizeof(**result)));
4189-
memset(*result, 0, sizeof(**result));
4185+
ut_zalloc(sizeof(**result)));
41904186
}
41914187

41924188
ut_free(lc_query_str);

storage/innobase/gis/gis0sea.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -905,8 +905,7 @@ rtr_create_rtr_info(
905905
index = index ? index : cursor->index;
906906
ut_ad(index);
907907

908-
rtr_info = static_cast<rtr_info_t*>(ut_malloc(sizeof(*rtr_info)));
909-
memset(rtr_info, 0, sizeof(*rtr_info));
908+
rtr_info = static_cast<rtr_info_t*>(ut_zalloc(sizeof(*rtr_info)));
910909

911910
rtr_info->allocated = true;
912911
rtr_info->cursor = cursor;

storage/innobase/include/buf0buf.ic

+2-2
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,8 @@ buf_page_alloc_descriptor(void)
778778
{
779779
buf_page_t* bpage;
780780

781-
bpage = (buf_page_t*) ut_malloc(sizeof *bpage);
782-
ut_d(memset(bpage, 0, sizeof *bpage));
781+
bpage = (buf_page_t*) ut_zalloc(sizeof *bpage);
782+
ut_ad(bpage);
783783
UNIV_MEM_ALLOC(bpage, sizeof *bpage);
784784

785785
return(bpage);

storage/innobase/log/log0recv.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -3509,8 +3509,7 @@ recv_reset_log_files_for_backup(
35093509
*/
35103510
ut_a(log_dir_len + strlen(ib_logfile_basename) + 11 < sizeof(name));
35113511

3512-
buf = ut_malloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
3513-
memset(buf, '\0', LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
3512+
buf = ut_zalloc(LOG_FILE_HDR_SIZE + OS_FILE_LOG_BLOCK_SIZE);
35143513

35153514
for (i = 0; i < n_log_files; i++) {
35163515

storage/innobase/os/os0file.cc

+3-6
Original file line numberDiff line numberDiff line change
@@ -3663,8 +3663,7 @@ os_aio_array_create(
36633663
ut_a(n > 0);
36643664
ut_a(n_segments > 0);
36653665

3666-
array = static_cast<os_aio_array_t*>(ut_malloc(sizeof(*array)));
3667-
memset(array, 0x0, sizeof(*array));
3666+
array = static_cast<os_aio_array_t*>(ut_zalloc(sizeof(*array)));
36683667

36693668
mutex_create("os_aio_mutex", &array->mutex);
36703669

@@ -3677,9 +3676,8 @@ os_aio_array_create(
36773676
array->n_segments = n_segments;
36783677

36793678
array->slots = static_cast<os_aio_slot_t*>(
3680-
ut_malloc(n * sizeof(*array->slots)));
3679+
ut_zalloc(n * sizeof(*array->slots)));
36813680

3682-
memset(array->slots, 0x0, sizeof(n * sizeof(*array->slots)));
36833681
#ifdef _WIN32
36843682
array->handles = static_cast<HANDLE*>(ut_malloc(n * sizeof(HANDLE)));
36853683
#endif /* _WIN32 */
@@ -3715,9 +3713,8 @@ os_aio_array_create(
37153713

37163714
/* Initialize the event array. One event per slot. */
37173715
io_event = static_cast<struct io_event*>(
3718-
ut_malloc(n * sizeof(*io_event)));
3716+
ut_zalloc(n * sizeof(*io_event)));
37193717

3720-
memset(io_event, 0x0, sizeof(*io_event) * n);
37213718
array->aio_events = io_event;
37223719

37233720
skip_native_aio:

storage/innobase/ut/ut0bh.cc

+1-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ ib_bh_create(
4646

4747
sz = sizeof(*ib_bh) + (sizeof_elem * max_elems);
4848

49-
ib_bh = (ib_bh_t*) ut_malloc(sz);
50-
memset(ib_bh, 0x0, sz);
49+
ib_bh = (ib_bh_t*) ut_zalloc(sz);
5150

5251
ib_bh->compare = compare;
5352
ib_bh->max_elems = max_elems;

storage/innobase/ut/ut0mem.cc

+25-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,31 @@ void*
8888
ut_zalloc(
8989
ulint size)
9090
{
91-
return(memset(ut_malloc(size), 0, size));
91+
void* ptr = calloc(size, 1);
92+
93+
for (int retry = 1; ; retry++) {
94+
if (ptr != NULL) {
95+
return(ptr);
96+
}
97+
if (retry > max_attempts) {
98+
break;
99+
}
100+
101+
/* Sleep for a second and retry the allocation;
102+
maybe this is just a temporary shortage of memory */
103+
104+
os_thread_sleep(1000000);
105+
106+
ptr = calloc(size, 1);
107+
}
108+
109+
ib_logf(IB_LOG_LEVEL_FATAL,
110+
"Cannot allocate " ULINTPF " bytes of memory after %d"
111+
" tries over %d seconds. OS error: %d-%s. %s",
112+
size, max_attempts, max_attempts,
113+
errno, strerror(errno), OUT_OF_MEMORY_MSG);
114+
115+
return(NULL);
92116
}
93117

94118
/**********************************************************************//**

storage/innobase/ut/ut0rbt.cc

+3-6
Original file line numberDiff line numberDiff line change
@@ -799,22 +799,19 @@ rbt_create(
799799
ib_rbt_t* tree;
800800
ib_rbt_node_t* node;
801801

802-
tree = (ib_rbt_t*) ut_malloc(sizeof(*tree));
803-
memset(tree, 0, sizeof(*tree));
802+
tree = (ib_rbt_t*) ut_zalloc(sizeof(*tree));
804803

805804
tree->sizeof_value = sizeof_value;
806805

807806
/* Create the sentinel (NIL) node. */
808-
node = tree->nil = (ib_rbt_node_t*) ut_malloc(sizeof(*node));
809-
memset(node, 0, sizeof(*node));
807+
node = tree->nil = (ib_rbt_node_t*) ut_zalloc(sizeof(*node));
810808

811809
node->color = IB_RBT_BLACK;
812810
node->parent = node->left = node->right = node;
813811

814812
/* Create the "fake" root, the real root node will be the
815813
left child of this node. */
816-
node = tree->root = (ib_rbt_node_t*) ut_malloc(sizeof(*node));
817-
memset(node, 0, sizeof(*node));
814+
node = tree->root = (ib_rbt_node_t*) ut_zalloc(sizeof(*node));
818815

819816
node->color = IB_RBT_BLACK;
820817
node->parent = node->left = node->right = tree->nil;

unittest/gunit/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ SET(TESTS
232232
bounds_checked_array
233233
bitmap
234234
byteorder
235+
calloc
235236
cost_estimate
236237
dbug
237238
decimal

unittest/gunit/calloc-t.cc

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
2+
3+
This program is free software; you can redistribute it and/or modify
4+
it under the terms of the GNU General Public License as published by
5+
the Free Software Foundation; version 2 of the License.
6+
7+
This program is distributed in the hope that it will be useful,
8+
but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
GNU General Public License for more details.
11+
12+
You should have received a copy of the GNU General Public License
13+
along with this program; if not, write to the Free Software
14+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15+
16+
// First include (the generated) my_config.h, to get correct platform defines.
17+
#include "my_config.h"
18+
#include <gtest/gtest.h>
19+
20+
#include <stdlib.h>
21+
#include <string.h>
22+
23+
namespace calloc_unittest {
24+
25+
/*
26+
Set num_iterations to a reasonable value (e.g. 200000), build release
27+
and run with 'calloc-t --disable-tap-output' to see the time taken.
28+
*/
29+
#if !defined(DBUG_OFF)
30+
// There is no point in benchmarking anything in debug mode.
31+
static int num_iterations= 2;
32+
#else
33+
// Set this so that each test case takes a few seconds.
34+
// And set it back to a small value before pushing!!
35+
static int num_iterations= 2000;
36+
#endif
37+
38+
39+
class CallocTest : public ::testing::Test
40+
{
41+
protected:
42+
CallocTest() { };
43+
44+
void malloc_test(int count);
45+
void calloc_test(int count);
46+
};
47+
48+
49+
void CallocTest::malloc_test(int count)
50+
{
51+
for (int i= 1; i <= count; i++)
52+
{
53+
size_t size= i * 10;
54+
void *rawmem1= malloc(size);
55+
memset(rawmem1, 0, size);
56+
void *rawmem2= malloc(size);
57+
memset(rawmem2, 0, size);
58+
// We need to prevent the optimizer from removing the whole loop.
59+
EXPECT_FALSE(memcmp(rawmem1, rawmem2, 1));
60+
free(rawmem1);
61+
free(rawmem2);
62+
}
63+
}
64+
65+
66+
void CallocTest::calloc_test(int count)
67+
{
68+
for (int i= 1; i <= count; i++)
69+
{
70+
size_t size= i * 10;
71+
void *rawmem1= calloc(size, 1);
72+
void *rawmem2= calloc(size, 1);
73+
// We need to prevent the optimizer from removing the whole loop.
74+
EXPECT_FALSE(memcmp(rawmem1, rawmem2, 1));
75+
free(rawmem1);
76+
free(rawmem2);
77+
}
78+
}
79+
80+
81+
TEST_F(CallocTest, WarmupTest)
82+
{
83+
calloc_test(num_iterations);
84+
}
85+
86+
TEST_F(CallocTest, MallocTest)
87+
{
88+
malloc_test(num_iterations);
89+
}
90+
91+
TEST_F(CallocTest, CallocTest)
92+
{
93+
calloc_test(num_iterations);
94+
}
95+
96+
}

0 commit comments

Comments
 (0)