Skip to content

Commit de5cc90

Browse files
committed
Use better buffer reallocation strategy
1 parent e4a7d31 commit de5cc90

File tree

1 file changed

+23
-13
lines changed

1 file changed

+23
-13
lines changed

ext/mysqlnd/mysqlnd_result.c

+23-13
Original file line numberDiff line numberDiff line change
@@ -1237,8 +1237,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, const
12371237
/* }}} */
12381238

12391239

1240-
#define STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY 2
1241-
12421240
/* {{{ mysqlnd_res::store_result_fetch_data */
12431241
enum_func_status
12441242
MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result,
@@ -1247,7 +1245,8 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
12471245
zend_bool binary_protocol)
12481246
{
12491247
enum_func_status ret;
1250-
unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1;
1248+
uint64_t total_allocated_rows = 0;
1249+
unsigned int free_rows = 0;
12511250
MYSQLND_RES_BUFFERED * set = result->stored_data;
12521251
MYSQLND_PACKET_ROW row_packet;
12531252

@@ -1256,14 +1255,8 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
12561255
ret = FAIL;
12571256
goto end;
12581257
}
1259-
if (free_rows) {
1260-
*row_buffers = mnd_emalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
1261-
if (!*row_buffers) {
1262-
SET_OOM_ERROR(conn->error_info);
1263-
ret = FAIL;
1264-
goto end;
1265-
}
1266-
}
1258+
1259+
*row_buffers = NULL;
12671260

12681261
conn->payload_decoder_factory->m.init_row_packet(&row_packet);
12691262
set->references = 1;
@@ -1277,17 +1270,33 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
12771270

12781271
while (FAIL != (ret = PACKET_READ(conn, &row_packet)) && !row_packet.eof) {
12791272
if (!free_rows) {
1280-
uint64_t total_allocated_rows = free_rows = next_extend = next_extend * 11 / 10; /* extend with 10% */
12811273
MYSQLND_MEMORY_POOL_CHUNK ** new_row_buffers;
12821274
total_allocated_rows += set->row_count;
12831275

1276+
if (total_allocated_rows < 1024) {
1277+
if (total_allocated_rows == 0) {
1278+
free_rows = 1;
1279+
total_allocated_rows = 1;
1280+
} else {
1281+
free_rows = total_allocated_rows;
1282+
total_allocated_rows *= 2;
1283+
}
1284+
} else {
1285+
free_rows = 1024;
1286+
total_allocated_rows += 1024;
1287+
}
1288+
12841289
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
12851290
if (total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
12861291
SET_OOM_ERROR(conn->error_info);
12871292
ret = FAIL;
12881293
goto free_end;
12891294
}
1290-
new_row_buffers = mnd_erealloc(*row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
1295+
if (*row_buffers) {
1296+
new_row_buffers = mnd_erealloc(*row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
1297+
} else {
1298+
new_row_buffers = mnd_emalloc((size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
1299+
}
12911300
if (!new_row_buffers) {
12921301
SET_OOM_ERROR(conn->error_info);
12931302
ret = FAIL;
@@ -1323,6 +1332,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
13231332
UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet.warning_count);
13241333
UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet.server_status);
13251334
}
1335+
13261336
/* save some memory */
13271337
if (free_rows) {
13281338
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */

0 commit comments

Comments
 (0)