Обсуждение: Progress report: intraquery memory recovery in executor

Поиск
Список
Период
Сортировка

Progress report: intraquery memory recovery in executor

От
Tom Lane
Дата:
My original idea for using the new "memory context" mechanisms for
recovering memory in the executor went like this: in each Plan node,
create a "per tuple" context that would be reset at the start of each
ExecProcNode call, thereby recovering memory allocated in the previous
tuple cycle.  I envisioned resetting and switching into this context at
the start of each call of the node's ExecProcNode routine.

This idea has pretty much crashed and burned on takeoff :-(.  It turns
out there are way too many plan-level routines that assume they can
do palloc() to allocate memory that will still be there the next time
they are called.  An example is that rtree index scans use a stack of
palloc'd nodes to keep track of where they are ... and that stack had
better still be there when you ask for the next tuple.

We could possibly teach all these places to use something other than
CurrentMemoryContext for their allocations, but it doesn't look like an
appetizing prospect.  It looks tedious and highly error-prone, both of
which are adjectives I'd hoped to avoid for this project.

What I'm currently considering instead is to still create a per-tuple
context for each plan node, but use it only for expression evaluation,
ie, we switch into it on entry to ExecQual(), ExecTargetList(),
ExecProject(), maybe a few other places.  The majority of our leakage
problems are associated with expression evaluation, so this should allow
fixing the leakage problems.  It will mean that routines associated with
plan nodes (basically, executor/node*.c) will still need to be careful
to avoid leaks.  For the most part they are already, but I had hoped to
make that care less necessary.

Comments, better ideas?
        regards, tom lane


Re: Progress report: intraquery memory recovery in executor

От
Philip Warner
Дата:
At 02:31 10/07/00 -0400, Tom Lane wrote:
>
>What I'm currently considering instead is to still create a per-tuple
>context for each plan node, but use it only for expression evaluation,
>ie, we switch into it on entry to ExecQual(), ExecTargetList(),
>ExecProject(), maybe a few other places.  The majority of our leakage
>problems are associated with expression evaluation, so this should allow
>fixing the leakage problems.  It will mean that routines associated with
>plan nodes (basically, executor/node*.c) will still need to be careful
>to avoid leaks.  For the most part they are already, but I had hoped to
>make that care less necessary.
>

Is it simple for the person writing the low level routines to choose
(easily) to allocate 'temporary' memory vs. 'permanent' memory? If some
mechanism were in place for this, then the code could slowly be
migrated...at least reducing the tedium.


----------------------------------------------------------------
Philip Warner                    |     __---_____
Albatross Consulting Pty. Ltd.   |----/       -  \
(A.C.N. 008 659 498)             |          /(@)   ______---_
Tel: (+61) 0500 83 82 81         |                 _________  \
Fax: (+61) 0500 83 82 82         |                 ___________ |
Http://www.rhyme.com.au          |                /           \|                                |    --________--
PGP key available upon request,  |  /
and from pgp5.ai.mit.edu:11371   |/


Re: Progress report: intraquery memory recovery in executor

От
Bruce Momjian
Дата:
> What I'm currently considering instead is to still create a per-tuple
> context for each plan node, but use it only for expression evaluation,
> ie, we switch into it on entry to ExecQual(), ExecTargetList(),
> ExecProject(), maybe a few other places.  The majority of our leakage
> problems are associated with expression evaluation, so this should allow
> fixing the leakage problems.  It will mean that routines associated with
> plan nodes (basically, executor/node*.c) will still need to be careful
> to avoid leaks.  For the most part they are already, but I had hoped to
> make that care less necessary.

I was wondering how you were going to pull this off.  It seems doing
something on entry to the expression routines is best.

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
853-3000+  If your life is a hard drive,     |  830 Blythe Avenue +  Christ can be your backup.        |  Drexel Hill,
Pennsylvania19026
 


Re: Progress report: intraquery memory recovery in executor

От
Tom Lane
Дата:
Philip Warner <pjw@rhyme.com.au> writes:
> Is it simple for the person writing the low level routines to choose
> (easily) to allocate 'temporary' memory vs. 'permanent' memory?

One of the main problems is that a low-level routine doesn't necessarily
know which is appropriate --- the answer may vary depending on where it
was called from.  To do it that way, I think we'd end up decorating a
large number of internal APIs with extra MemoryContext arguments.
(This is exactly why we have a global CurrentMemoryContext in the first
place...)

That's why I wanted to do the management at the level of the Plan node
executor routines, which are high-level enough that they have some clue
what's going on.
        regards, tom lane


Re: Progress report: intraquery memory recovery in executor

От
Philip Warner
Дата:
At 10:08 10/07/00 -0400, Tom Lane wrote:
>Philip Warner <pjw@rhyme.com.au> writes:
>> Is it simple for the person writing the low level routines to choose
>> (easily) to allocate 'temporary' memory vs. 'permanent' memory?
>
>One of the main problems is that a low-level routine doesn't necessarily
>know which is appropriate --- the answer may vary depending on where it
>was called from.  
...
>That's why I wanted to do the management at the level of the Plan node
>executor routines, which are high-level enough that they have some clue
>what's going on.

ISTM (with, perhaps, no basis (ISTMWPNB?)) that when allocating memory
there are a couple of cases:

You want it to be available:

1. until the end of the current call
2. at least until the next call
3. until TX end
4. forever
...etc.

If there are still cases where the called routine can't tell what sort of
memory it wants, then my method won't work (and I'd be interested to know
what they are).

But if a relatively short list of allocation types can be created, then the
palloc replacement can be passed an extra parameter (the 'allocation
type'), and handle memory contexts appropriately.

Feel free to tell me if this is so way off the mark that there is no
purpose in pursuing the discussion...


----------------------------------------------------------------
Philip Warner                    |     __---_____
Albatross Consulting Pty. Ltd.   |----/       -  \
(A.C.N. 008 659 498)             |          /(@)   ______---_
Tel: (+61) 0500 83 82 81         |                 _________  \
Fax: (+61) 0500 83 82 82         |                 ___________ |
Http://www.rhyme.com.au          |                /           \|                                |    --________--
PGP key available upon request,  |  /
and from pgp5.ai.mit.edu:11371   |/


Re: Progress report: intraquery memory recovery in executor

От
Tom Lane
Дата:
Bruce Momjian <pgman@candle.pha.pa.us> writes:
> I was wondering how you were going to pull this off.  It seems doing
> something on entry to the expression routines is best.

Yeah, associating a short-term memory context with each ExprContext
is looking like the way to proceed.
        regards, tom lane


Re: Progress report: intraquery memory recovery in executor

От
Tom Lane
Дата:
Philip Warner <pjw@rhyme.com.au> writes:
> ISTM (with, perhaps, no basis (ISTMWPNB?)) that when allocating memory
> there are a couple of cases:

> You want it to be available:

> 1. until the end of the current call
> 2. at least until the next call
> 3. until TX end
> 4. forever
> ...etc.

Right, that's essentially what the various MemoryContexts are for.

> But if a relatively short list of allocation types can be created, then the
> palloc replacement can be passed an extra parameter (the 'allocation
> type'), and handle memory contexts appropriately.

I don't think that's a superior solution to passing a target
MemoryContext around.  An allocation-type parameter would just mean an
extra lookup in some global array to find the appropriate MemoryContext.
That means even more global state, rather than less, and it's not as
extensible.  Right now, if you have a need for a context with some
weird lifetime, you just make one and then delete it again later ---
the knowledge of the context's very existence, as well as lifetime,
is localized.  In an allocation-type world you'd need to either add
a new allocation type code or figure out which existing category to
force-fit your context into.

In any case, this doesn't address the real practical problem, which is
going around and changing hundreds of routines and thousands of calls
thereto... I really *don't* want to add a memory management parameter
to everything in sight.  Doesn't matter how the parameter is defined.
        regards, tom lane