andrey          Mon Oct 27 15:13:42 2008 UTC

  Modified files:              
    /php-src/ext/mysqlnd        mysqlnd_result.c 
  Log:
  Fix overusage of memory when the result set is empty. Then no memory will be
  allocated compared to before. Also grow (realloc) the rset with 10% instead
  of 33% - more reallocs but better memory usage. Of course later theres is a
  realloc to shrink the rset t ofree it from unused rows but its better to
  to eat too much at once.
  
  
http://cvs.php.net/viewvc.cgi/php-src/ext/mysqlnd/mysqlnd_result.c?r1=1.24&r2=1.25&diff_format=u
Index: php-src/ext/mysqlnd/mysqlnd_result.c
diff -u php-src/ext/mysqlnd/mysqlnd_result.c:1.24 
php-src/ext/mysqlnd/mysqlnd_result.c:1.25
--- php-src/ext/mysqlnd/mysqlnd_result.c:1.24   Thu May 29 15:50:10 2008
+++ php-src/ext/mysqlnd/mysqlnd_result.c        Mon Oct 27 15:13:42 2008
@@ -18,7 +18,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: mysqlnd_result.c,v 1.24 2008/05/29 15:50:10 andrey Exp $ */
+/* $Id: mysqlnd_result.c,v 1.25 2008/10/27 15:13:42 andrey Exp $ */
 #include "php.h"
 #include "mysqlnd.h"
 #include "mysqlnd_wireprotocol.h"
@@ -214,11 +214,15 @@
                current_buffer->free_chunk(current_buffer, TRUE TSRMLS_CC);
        }
        DBG_INF("Freeing data & row_buffer");
-       pefree(set->data, set->persistent);
-       pefree(set->row_buffers, set->persistent);
-       set->data                       = NULL;
-       set->row_buffers        = NULL;
-       set->data_cursor        = NULL;
+       if (set->data) {
+               pefree(set->data, set->persistent);
+               set->data = NULL;
+       }
+       if (set->row_buffers) {
+               pefree(set->row_buffers, set->persistent);
+               set->row_buffers        = NULL;
+       }
+       set->data_cursor = NULL;
        set->row_count  = 0;
        if (set->qcache) {
                mysqlnd_qcache_free_cache_reference(&set->qcache);
@@ -1175,7 +1179,7 @@
 /* }}} */
 
 
-#define STORE_RESULT_PREALLOCATED_SET 10
+#define STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY 2
 
 /* {{{ mysqlnd_store_result_fetch_data */
 enum_func_status
@@ -1186,21 +1190,24 @@
 {
        enum_func_status ret;
        php_mysql_packet_row *row_packet;
-       unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET, free_rows;
+       unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, 
free_rows = 1;
        MYSQLND_RES_BUFFERED *set;
 
        DBG_ENTER("mysqlnd_store_result_fetch_data");
        DBG_INF_FMT("conn=%llu binary_proto=%d to_cache=%d",
                                conn->thread_id, binary_protocol, to_cache);
 
-       free_rows = next_extend;
-
        result->stored_data     = set = mnd_pecalloc(1, 
sizeof(MYSQLND_RES_BUFFERED), to_cache);
-       set->row_buffers= mnd_pemalloc(STORE_RESULT_PREALLOCATED_SET * 
sizeof(MYSQLND_MEMORY_POOL_CHUNK *), to_cache);
+       if (free_rows) {
+               set->row_buffers = mnd_pemalloc(free_rows * 
sizeof(MYSQLND_MEMORY_POOL_CHUNK *), to_cache);
+       }
        set->persistent = to_cache;
        set->qcache             = to_cache? 
mysqlnd_qcache_get_cache_reference(conn->qcache):NULL;
        set->references = 1;
 
+       result->m.row_decoder = binary_protocol? 
php_mysqlnd_rowp_read_binary_protocol:
+                                                                               
         php_mysqlnd_rowp_read_text_protocol;
+
        /* non-persistent */
        PACKET_INIT(row_packet, PROT_ROW_PACKET, php_mysql_packet_row *, FALSE);
        row_packet->field_count = meta->field_count;
@@ -1213,18 +1220,15 @@
 
        while (FAIL != (ret = PACKET_READ(row_packet, conn)) && 
!row_packet->eof) {
                if (!free_rows) {
-                       uint64 total_rows = free_rows = next_extend = 
next_extend * 5 / 3; /* extend with 33% */
-                       total_rows += set->row_count;
+                       uint64 total_allocated_rows = free_rows = next_extend = 
next_extend * 11 / 10; /* extend with 10% */
+                       total_allocated_rows += set->row_count;
                        set->row_buffers = mnd_perealloc(set->row_buffers,
-                                                                               
         total_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *),
+                                                                               
         total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *),
                                                                                
         set->persistent);
                }
                free_rows--;
                set->row_buffers[set->row_count] = row_packet->row_buffer;
 
-               result->m.row_decoder = binary_protocol? 
php_mysqlnd_rowp_read_binary_protocol:
-                                                                               
                 php_mysqlnd_rowp_read_text_protocol;
-
                set->row_count++;
 
                /* So row_packet's destructor function won't efree() it */
@@ -1239,7 +1243,12 @@
                */
        }
        /* Overflow ? */
-       set->data = mnd_pecalloc(set->row_count * meta->field_count, 
sizeof(zval *), to_cache);
+       if (set->row_count) {
+               /* if pecalloc is used valgrind barks gcc version 4.3.1 
20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
+               set->data = mnd_pemalloc(set->row_count * meta->field_count * 
sizeof(zval *), to_cache);
+               memset(set->data, 0, set->row_count * meta->field_count * 
sizeof(zval *));
+       }
+
        MYSQLND_INC_CONN_STATISTIC_W_VALUE(&conn->stats,
                                                                           
binary_protocol? STAT_ROWS_BUFFERED_FROM_CLIENT_PS:
                                                                                
                                STAT_ROWS_BUFFERED_FROM_CLIENT_NORMAL,



-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to