[Mesa-dev] [PATCH v3] gallium/util: Break recursion in pipe_resource_reference
Nicolai Hähnle
nhaehnle at gmail.com
Wed Jun 14 08:42:49 UTC 2017
On 14.06.2017 10:05, Michel Dänzer wrote:
> On 14/06/17 04:42 PM, Nicolai Hähnle wrote:
>> On 14.06.2017 05:39, Michel Dänzer wrote:
>>> From: Michel Dänzer <michel.daenzer at amd.com>
>>>
>>> It calling itself recursively prevented it from being inlined, resulting
>>> in a copy being generated in every compilation unit referencing it. This
>>> bloated the text segment of the Gallium mega-driver *_dri.so by ~4%,
>>> and might also have impacted performance.
>>
>> Did you update the size measurement?
>
> Yes, since I measured ~4.3%, I figured it's better to go for
> understatement than exaggeration after all. :)
>
>
>>> diff --git a/src/gallium/auxiliary/util/u_inlines.h
>>> b/src/gallium/auxiliary/util/u_inlines.h
>>> index 6a3d5043cf..08326da03d 100644
>>> --- a/src/gallium/auxiliary/util/u_inlines.h
>>> +++ b/src/gallium/auxiliary/util/u_inlines.h
>>> @@ -137,8 +137,19 @@ pipe_resource_reference(struct pipe_resource
>>> **ptr, struct pipe_resource *tex)
>>> if (pipe_reference_described(&(*ptr)->reference, &tex->reference,
>>>
>>> (debug_reference_descriptor)debug_describe_resource)) {
>>> - pipe_resource_reference(&old_tex->next, NULL);
>>> + struct pipe_resource *next = old_tex->next;
>>> +
>>> old_tex->screen->resource_destroy(old_tex->screen, old_tex);
>>> +
>>> + /* Avoid recursion, which would prevent inlining this function */
>>> + while (next) {
>>> + old_tex = next;
>>> + next = old_tex->next;
>>> + old_tex->next = NULL;
>>
>> Is this really necessary? I don't think so, but if it is, it's probably
>> necessary above as well.
>
> The old_tex->next = NULL assignment is necessary here to complement the
> pipe_reference_described call below it. It's not necessary above,
> because the ->next chain only needs to be unreferenced when the "master"
> resource is destroyed.
>
> The behaviour is basically the same as with the recursive
> pipe_resource_reference(&old_tex->next, NULL) call before: the next
> pointers are left untouched unless the "master" resource is destroyed,
> in which case the next pointers are set to NULL and the reference counts
> of the corresponding sub-resources decremented (and the sub-resource
> destroyed if it goes to 0). The only slight change is that the next
> member of the "master" resource isn't set to NULL, but that doesn't
> matter because it's getting destroyed anyway.
Well, if (*ptr)->next is _not_ destroyed, then the new code will set
(*ptr)->next->next to NULL anyway, while the old code would not have
modified it.
Come to think of it, the new code should really break out of the loop
once pipe_reference_described returns false. Maybe:
do {
struct pipe_resource *next = old_tex->next;
old_tex->screen->resource_destroy(old_tex->screen, old_tex);
old_tex = next;
} while (old_tex && pipe_reference_described(&old_tex->reference, NULL,
...));
How does that sound?
Cheers,
Nicolai
> Let me know of you spot another difference in behaviour before and after
> the patch.
>
>
--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
More information about the mesa-dev
mailing list