summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2017-11-15 02:44:34 +0300
committerDmitry Stogov <dmitry@zend.com>2017-11-15 02:44:34 +0300
commitde5cc9017efee667f00d11ec6886c45801294a90 (patch)
tree28d430f402880eb3d53ae05fe0b6497d61e1f2b1 /ext
parente4a7d31b092d63030a12c793276f7e1a42d05456 (diff)
downloadphp-git-de5cc9017efee667f00d11ec6886c45801294a90.tar.gz
Use better buffer reallocation strategy
Diffstat (limited to 'ext')
-rw-r--r--ext/mysqlnd/mysqlnd_result.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index 6ca6ca979d..4dffdad80c 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -1237,8 +1237,6 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row)(MYSQLND_RES * result, void * param, const
/* }}} */
-#define STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY 2
-
/* {{{ mysqlnd_res::store_result_fetch_data */
enum_func_status
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
zend_bool binary_protocol)
{
enum_func_status ret;
- unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1;
+ uint64_t total_allocated_rows = 0;
+ unsigned int free_rows = 0;
MYSQLND_RES_BUFFERED * set = result->stored_data;
MYSQLND_PACKET_ROW row_packet;
@@ -1256,14 +1255,8 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
ret = FAIL;
goto end;
}
- if (free_rows) {
- *row_buffers = mnd_emalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
- if (!*row_buffers) {
- SET_OOM_ERROR(conn->error_info);
- ret = FAIL;
- goto end;
- }
- }
+
+ *row_buffers = NULL;
conn->payload_decoder_factory->m.init_row_packet(&row_packet);
set->references = 1;
@@ -1277,17 +1270,33 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
while (FAIL != (ret = PACKET_READ(conn, &row_packet)) && !row_packet.eof) {
if (!free_rows) {
- uint64_t total_allocated_rows = free_rows = next_extend = next_extend * 11 / 10; /* extend with 10% */
MYSQLND_MEMORY_POOL_CHUNK ** new_row_buffers;
total_allocated_rows += set->row_count;
+ if (total_allocated_rows < 1024) {
+ if (total_allocated_rows == 0) {
+ free_rows = 1;
+ total_allocated_rows = 1;
+ } else {
+ free_rows = total_allocated_rows;
+ total_allocated_rows *= 2;
+ }
+ } else {
+ free_rows = 1024;
+ total_allocated_rows += 1024;
+ }
+
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
SET_OOM_ERROR(conn->error_info);
ret = FAIL;
goto free_end;
}
- new_row_buffers = mnd_erealloc(*row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
+ if (*row_buffers) {
+ new_row_buffers = mnd_erealloc(*row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
+ } else {
+ new_row_buffers = mnd_emalloc((size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)));
+ }
if (!new_row_buffers) {
SET_OOM_ERROR(conn->error_info);
ret = FAIL;
@@ -1323,6 +1332,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet.warning_count);
UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet.server_status);
}
+
/* save some memory */
if (free_rows) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */