[Tarantool-patches] [PATCH v4 4/6] sql: use parser's region of "index" array

Roman Khabibov roman.habibov at tarantool.org
Tue Sep 29 02:29:26 MSK 2020


Hi! Thanks for the review.

> On Sep 16, 2020, at 16:30, Nikita Pettik <korablev at tarantool.org> wrote:
> 
> On 12 Sep 00:51, Roman Khabibov wrote:
>> Allocate memory for the "index" array of ephemeral space on the
>> parser's region instead of a heap as it was before. Fixed a memory
>> leak that realloc() generated.
>> 
>> Needed for #3075
> 
> Why it is related to 3075??
Fixed to -> 2349. Due to this patch, I avoid malloc inside sql_space_shallow_copy.

>> ---
>> src/box/sql/build.c | 42 +++++++++++++++++++++++++++++++-----------
>> 1 file changed, 31 insertions(+), 11 deletions(-)
>> 
>> diff --git a/src/box/sql/build.c b/src/box/sql/build.c
>> index 6cc76bb77..d1d240315 100644
>> --- a/src/box/sql/build.c
>> +++ b/src/box/sql/build.c
>> @@ -2226,29 +2226,49 @@ vdbe_emit_new_sec_index_id(struct Parse *parse, uint32_t space_id,
>> }
>> 
>> /**
>> - * Add new index to table's indexes list.
>> + * Add new index to ephemeral @a space's "index" array. Reallocate
>> + * memory on @a region if needed.
>> + *
>>  * We follow convention that PK comes first in list.
>>  *
>> + * @param region Region (on parser).
>>  * @param space Space to which belongs given index.
>>  * @param index Index to be added to list.
>>  */
>> static void
>> -table_add_index(struct space *space, struct index *index)
>> +sql_space_add_index(struct region *region, struct space *space,
>> +		    struct index *index)
>> {
>> 	uint32_t idx_count = space->index_count;
>> -	size_t indexes_sz = sizeof(struct index *) * (idx_count + 1);
>> -	struct index **idx = (struct index **) realloc(space->index,
>> -						       indexes_sz);
>> -	if (idx == NULL) {
>> -		diag_set(OutOfMemory, indexes_sz, "realloc", "idx");
>> -		return;
>> -	}
>> -	space->index = idx;
>> +	size_t size = 0;
>> +	struct index **idx = NULL;
>> +	if (idx_count == 0) {
>> +		idx = region_alloc_array(region, typeof(struct index *), 1,
>> +					 &size);
>> +		if (idx == NULL)
>> +			goto alloc_error;
>> +	/*
>> +	 * Reallocate each time the idx_count becomes equal to the
>> +	 * power of two.
>> +	 */
>> +	} else if ((idx_count & (idx_count - 1)) == 0) {
>> +		idx = region_alloc_array(region, typeof(struct index *),
>> +					 idx_count * 2, &size);
>> +		if (idx == NULL)
>> +			goto alloc_error;
>> +		memcpy(idx, space->index, idx_count * sizeof(struct index *));
>> +	}
>> +	if (idx != NULL)
>> +		space->index = idx;
> 
> DOes it make any sense? Why not simply call ::free (in case there really
> was memleak)?
It was a memleak, really. I checked it by valgrind.

This is the main reason. So that when destroying the parser, you don't have
to check whether it was CREATE or ALTER, whether malloc or realloc was called
inside build.c, and don't call free. The parser region is well suited for
this task.

>> 	/* Make sure that PK always comes as first member. */
>> 	if (index->def->iid == 0 && idx_count != 0)
>> 		SWAP(space->index[0], index);
>> 	space->index[space->index_count++] = index;
>> 	space->index_id_max =  MAX(space->index_id_max, index->def->iid);;
>> +	return;
>> +
>> +alloc_error:
>> +	diag_set(OutOfMemory, size, "region_alloc_array", "idx");
>> }
>> 
>> int
>> @@ -2717,7 +2737,7 @@ sql_create_index(struct Parse *parse) {
>> 
>> 	if (tbl_name != NULL)
>> 		goto exit_create_index;
>> -	table_add_index(space, index);
>> +	sql_space_add_index(&parse->region, space, index);
>> 	index = NULL;
>> 
>> 	/* Clean up before exiting. */
>> -- 
>> 2.24.3 (Apple Git-128)
>> 


commit 177c4389af647677afcce9fa58b12f00e398fbe9
Author: Roman Khabibov <roman.habibov at tarantool.org>
Date:   Thu Sep 3 14:26:47 2020 +0300

    sql: use parser's region of "index" array
    
    Allocate memory for the "index" array of ephemeral space on the
    parser's region instead of a heap as it was before. Fixed a memory
    leak that realloc() generated.
    
    Needed for #2349

diff --git a/src/box/sql/build.c b/src/box/sql/build.c
index 6cc76bb77..d1d240315 100644
--- a/src/box/sql/build.c
+++ b/src/box/sql/build.c
@@ -2226,29 +2226,49 @@ vdbe_emit_new_sec_index_id(struct Parse *parse, uint32_t space_id,
 }
 
 /**
- * Add new index to table's indexes list.
+ * Add new index to ephemeral @a space's "index" array. Reallocate
+ * memory on @a region if needed.
+ *
  * We follow convention that PK comes first in list.
  *
+ * @param region Region (on parser).
  * @param space Space to which belongs given index.
  * @param index Index to be added to list.
  */
 static void
-table_add_index(struct space *space, struct index *index)
+sql_space_add_index(struct region *region, struct space *space,
+		    struct index *index)
 {
 	uint32_t idx_count = space->index_count;
-	size_t indexes_sz = sizeof(struct index *) * (idx_count + 1);
-	struct index **idx = (struct index **) realloc(space->index,
-						       indexes_sz);
-	if (idx == NULL) {
-		diag_set(OutOfMemory, indexes_sz, "realloc", "idx");
-		return;
-	}
-	space->index = idx;
+	size_t size = 0;
+	struct index **idx = NULL;
+	if (idx_count == 0) {
+		idx = region_alloc_array(region, typeof(struct index *), 1,
+					 &size);
+		if (idx == NULL)
+			goto alloc_error;
+	/*
+	 * Reallocate each time the idx_count becomes equal to the
+	 * power of two.
+	 */
+	} else if ((idx_count & (idx_count - 1)) == 0) {
+		idx = region_alloc_array(region, typeof(struct index *),
+					 idx_count * 2, &size);
+		if (idx == NULL)
+			goto alloc_error;
+		memcpy(idx, space->index, idx_count * sizeof(struct index *));
+	}
+	if (idx != NULL)
+		space->index = idx;
 	/* Make sure that PK always comes as first member. */
 	if (index->def->iid == 0 && idx_count != 0)
 		SWAP(space->index[0], index);
 	space->index[space->index_count++] = index;
 	space->index_id_max =  MAX(space->index_id_max, index->def->iid);;
+	return;
+
+alloc_error:
+	diag_set(OutOfMemory, size, "region_alloc_array", "idx");
 }
 
 int
@@ -2717,7 +2737,7 @@ sql_create_index(struct Parse *parse) {
 
 	if (tbl_name != NULL)
 		goto exit_create_index;
-	table_add_index(space, index);
+	sql_space_add_index(&parse->region, space, index);
 	index = NULL;
 
 	/* Clean up before exiting. */


More information about the Tarantool-patches mailing list