Re: How to make ResourceOwnerForgetBuffer() O(1), instead of O(N^2) scale - Mailing list pgsql-hackers

From Kouhei Kaigai
Subject Re: How to make ResourceOwnerForgetBuffer() O(1), instead of O(N^2) scale
Date
Msg-id 9A28C8860F777E439AA12E8AEA7694F801047785@BPXM15GP.gisp.nec.co.jp
Whole thread Raw
In response to Re: How to make ResourceOwnerForgetBuffer() O(1), instead of O(N^2) scale  (Heikki Linnakangas <hlinnakangas@vmware.com>)
Responses Re: How to make ResourceOwnerForgetBuffer() O(1), instead of O(N^2) scale
List pgsql-hackers
> On 10/03/2014 07:08 AM, Kouhei Kaigai wrote:
> > Hello,
> >
> > I recently got a trouble on development of my extension that utilizes
> > the shared buffer when it released each buffer page.
> >
> > This extension transfers contents of the shared buffers to GPU device
> > using DMA feature, then kicks a device kernel code.
>
> Wow, that sounds crazy.
>
> > Once backend/extension calls ReadBuffer(), resowner.c tracks which
> > buffer was referenced by the current resource owner, to ensure these
> > buffers being released at end of the transaction.
> > However, it seems to me implementation of resowner.c didn't assume
> > many buffers are referenced by a particular resource owner simultaneously.
> > It manages the buffer index using an expandable array, then looks up
> > the target buffer by sequential walk but from the tail because
> > recently pinned buffer tends to be released first.
> > It made a trouble in my case. My extension pinned multiple thousands
> > buffers, so owner->buffers[] were enlarged and takes expensive cost to
> > walk on.
> > In my measurement, ResourceOwnerForgetBuffer() takes 36 seconds in
> > total during hash-joining 2M rows; even though hash-joining itself
> > takes less than 16 seconds.
> >
> > What is the best way to solve the problem?
>
> How about creating a separate ResourceOwner for these buffer pins, and doing
> a wholesale ResourceOwnerRelease() on it when you're done?
>
Let me clarify your idea.

1. Create a separate ResourceOwner under the CurrentResourceOwner.
2. Switch CurrentResourceOwner to the self-constructed resource owner  during ReadBuffer() on thousands buffers.
3. Switch back to the original CurrentResourceOwner.
4. Kick DMA and run GPU device kernel (actual job running...)
5. Switch CurrentResourceOwner to the self-constructed resource owner  again, during ReleaseBuffer() in reverse order.
6. Switch back to the original CurrentResourceOwner, then calls  ResourceOwnerDelete().

Hmm... at this moment, I cannot find something not easy to implement.
I'd like to try this idea, then report it later.

Thanks,
--
NEC OSS Promotion Center / PG-Strom Project
KaiGai Kohei <kaigai@ak.jp.nec.com>




pgsql-hackers by date:

Previous
From: Heikki Linnakangas
Date:
Subject: Re: Promise index tuples for UPSERT
Next
From: Kouhei Kaigai
Date:
Subject: Re: How to make ResourceOwnerForgetBuffer() O(1), instead of O(N^2) scale