In the CF, the status becomes "Needs Review". Let's continue our discussion
of makeArrayResult* behavior if subcontext=false and release=true (more
below):
2014-12-22 8:08 GMT+07:00 Ali Akbar <the.ap...@gmail.com>:

>
> With this API, i think we should make it clear if we call initArrayResult
> with subcontext=false, we can't call makeArrayResult, but we must use
> makeMdArrayResult directly.
>
> Or better, we can modify makeArrayResult to release according to
> astate->private_cxt:
>
>> @@ -4742,7 +4742,7 @@ makeArrayResult(ArrayBuildState *astate,
>>     dims[0] = astate->nelems;
>>     lbs[0] = 1;
>>
>> -   return makeMdArrayResult(astate, ndims, dims, lbs, rcontext, true);
>> +   return makeMdArrayResult(astate, ndims, dims, lbs, rcontext,
>> astate->private_cxt);
>>
>
> Or else we implement what you suggest below (more comments below):
>
> Thinking about the 'release' flag a bit more - maybe we could do this
>> instead:
>>
>>     if (release && astate->private_cxt)
>>         MemoryContextDelete(astate->mcontext);
>>     else if (release)
>>     {
>>         pfree(astate->dvalues);
>>         pfree(astate->dnulls);
>>         pfree(astate);
>>     }
>>
>> i.e. either destroy the whole context if possible, and just free the
>> memory when using a shared memory context. But I'm afraid this would
>> penalize the shared memory context, because that's intended for cases
>> where all the build states coexist in parallel and then at some point
>> are all converted into a result and thrown away. Adding pfree() calls is
>> no improvement here, and just wastes cycles.
>>
>
> As per Tom's comment, i'm using "parent memory context" instead of "shared
> memory context" below.
>
> In the future, if some code writer decided to use subcontext=false, to
> save memory in cases where there are many array accumulation, and the
> parent memory context is long-living, current code can cause memory leak.
> So i think we should implement your suggestion (pfreeing astate), and warn
> the implication in the API comment. The API user must choose between
> release=true, wasting cycles but preventing memory leak, or managing memory
> from the parent memory context.
>
> In one possible use case, for efficiency maybe the caller will create a
> special parent memory context for all array accumulation. Then uses
> makeArrayResult* with release=false, and in the end releasing the parent
> memory context once for all.
>

As for the v6 patch:
- the patch applies cleanly to master
- make check is successfull
- memory benefit is still there
- performance benefit i think is negligible

Reviewing the code, found this:

> @@ -573,7 +578,22 @@ array_agg_array_transfn(PG_FUNCTION_ARGS)
>          elog(ERROR, "array_agg_array_transfn called in non-aggregate
> context");
>      }
>
> -    state = PG_ARGISNULL(0) ? NULL : (ArrayBuildStateArr *)
> PG_GETARG_POINTER(0);
> +
> +    if (PG_ARGISNULL(0))
> +    {
> +        Oid            element_type = get_element_type(arg1_typeid);
> +
> +        if (!OidIsValid(element_type))
> +            ereport(ERROR,
> +                    (errcode(ERRCODE_DATATYPE_MISMATCH),
> +                     errmsg("data type %s is not an array type",
> +                            format_type_be(arg1_typeid))));
>

digging more, it looks like those code required because accumArrayResultArr
checks the element type:

>         /* First time through --- initialize */
>         Oid            element_type = get_element_type(array_type);
>
>         if (!OidIsValid(element_type))
>             ereport(ERROR,
>                     (errcode(ERRCODE_DATATYPE_MISMATCH),
>                      errmsg("data type %s is not an array type",
>                             format_type_be(array_type))));
>         astate = initArrayResultArr(array_type, element_type, rcontext,
> true);
>

I think it should be in initArrayResultArr, because it is an
initialization-only check, shouldn't it?

Regards,
-- 
Ali Akbar

Reply via email to