Re: Misc. consequences of backend memory management changes

From: Karel Zak <zakkr(at)zf(dot)jcu(dot)cz>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-hackers(at)postgreSQL(dot)org
Subject: Re: Misc. consequences of backend memory management changes
Date: 2000-06-29 16:14:00
Message-ID: Pine.LNX.3.96.1000629163857.2120F-100000@ara.zf.jcu.cz
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers


On Thu, 29 Jun 2000, Tom Lane wrote:

> Karel Zak <zakkr(at)zf(dot)jcu(dot)cz> writes:
> >>>> Or skip for this specific variant context type independent
> >>>> MemoryContextCreate and init this common part itself? - (I vote for
> >>>> this)
> >>
> >> No, certainly not. Just pass a NULL for parent if you don't want to
> >> connect it up to the local context tree.
>
> > Well, the query cache shared memory pool and qCache_TopContext (parent of
> > all cache entry) are init during postmarter start up. In this time not exist
> > TopMemoryContext and 'node' for this context will alloc via malloc().
>
> Look again ;-). TopMemoryContext is created as the first or second step
> in postmaster startup, long before we attach to shared mem.

I looking :-), I don't say that here is a problem. I create master
qCache_TopContext like standard memory context, but only alloc method will
non-AllocSet. No problem.

>
> > *But* if I add entry to query cache I create for each entry separate memory
> > context and it must be in shared memory, but in shared memory must be not
> > only data allocated via this context, in shmem must be _all_ for context
> > relevant data --- so, context independent data too (bacause context must
> > overlive backend end). A problem is that common MemoryContextCreate() expects
> > that context 'node' is allocated in the TopMemoryContext or by force of
> > malloc(). Not is possible allocate context node in a parent context.
>
> Good point.
>
> > I read your comment "since the node must survive resets of its parent
> > context", but how resolve this?
>
> Well, there's a fundamental problem with keeping memory contexts that
> meet this API in shared memory anyway: the contexts have to contain
> parent/child pointers pointing at other contexts, and the contexts
> have to contain pointers to context-management function pointer structs.
> Neither of these are very safe for shared memory.

First I must say that _all_ with shmem/local query cache _works_ now
for me in current (7.0) memory design (I can send it). And I hope it must
works in 7.1 too.

For better understanding I a little describe this cache (qcache).
In postmaster startup and shmem init qcache create shmem pool. This pool
is split to blocks (now 1024b) these blocks are used in qcache contexts.
All free blocks are in freeblock list. During initialization is created
hash table (in shmem pool) for cached entry and qCache_TopContext (and
alloc methods) too. All it is in postmaster.
If user (PREPARE command) or SPI (by_key interface) add a plan to qcache
it create new memory context in shmem pool and as parent is used master
qCache_TopContext. New plan is copy to shmem via copyObject().
If user (EXECUTE) or SPI needs a plan in hash table is found relevant
pointer with plan and from this is copy to executor (or ..etc) context.
To the shared qcache pool has access only qcache's routines and all
access are "dress" in spin locks. For real work in backend is always used
some plan copy from qcache. --- It query cache.

> You've probably noticed that we keep cross-pointers in shared memory in
> the form of offsets from the start of the shmem block, not as absolute
> pointers. This is to support the possibility that the shmem block is
> mapped at different addresses in different backends. (It's possible
> that we could give up that flexibility now that all the backends are
> forked from a postmaster that's already attached the shmem block.
> But I'd rather not wire such an assumption into the contents of shmem.)
>
> Similarly, it would be risky to assume that the functions all appear
> at the same address in every backend connected to the shmem block.

All work with shmem must be assure via locks.

>
> What I think you probably want to do is create "placeholder" context
> nodes in backend local memory to represent the shared-memory contexts.
> The placeholder would contain the MemoryContext fields and a shmem
> offset to a struct in shared memory that is the "real" control info
> for the context.

I not sure if backend already needs information about shmem pool. Now
I have all meta-information about shmem pool in one struct (in shmem)
that is at for all backend known pointer. If I need some information
about my pool I see this meta-data or scan hash table.

I mean: we can create separate memory context tree based on some
qCache_TopContext and init in postmaster. Standard backend memory routines
not will know and access to this tree. Only query cache will the bridge
between shmem and standard contexts, but shmem contexts are compatible and
is possible use it in palloc()/pfree().

But I will think about your "placeholder" idea :-) I still a little not
understand who will need placeholder information - debug? The qcache
knows all from own structs.

> If every backend has a placeholder node for every context in shmem
> then you have a bit of a problem deleting shmem contexts, but I
> think you probably don't need to do that. There should be a permanent

It must be possible destroy context. If query cache is full, it itself
remove a oldest plan that is mark as "removeable" (an example plans from
SPI).

> placeholder for the top-level shmem context (create this during
> backend startup), but placeholder context nodes for per-plan contexts
> only need to live for as long as you are copying nodetrees into the
> context. They don't have to stick around longer than that.
>
>
> A few minutes later:

I always have "a few minutes later" after mail sending :-)

> Now that I think about it, this whole notion of copying nodetrees
> into shared memory has got a pointer problem, because the constructed
> tree is going to be full of pointers that will only be valid for a
> backend that has shmem attached at the same address that the creating
> backend had.

I don't understand,

test=# PREPARE aaa AS SELECT relname FROM pg_class
WHERE relname ~~ $1 USING text;
PREPARE
test=# \c test
You are now connected to database test. <---------- new backend
test=# EXECUTE aaa USING 'pg_c%';
relname
------------------------
pg_class
pg_class_oid_index
pg_class_relname_index

it is in 7.0

> Before you say "we will never again care about flexibility of attach
> address", consider these two scenarios:
> 1. Examining shmem using a debugging process started independently
> of the postmaster.
> 2. "Hot swapping" a new compilation of the postmaster/backend without
> service interruption. This is possible (for changes that don't
> change the layout of shmem, of course) by killing and restarting
> the postmaster without killing extant backends. But you couldn't
> assume that the new incarnation of the postmaster would attach to
> the existing shmem blocks at the exact same addresses the previous
> incarnation had been assigned.

Ops, now I understand, you want on-the-fly change backend.

I still mean "we will never again care about...." (I'm hard-headed :-)

(!) All Data in the query cache must be dispensable. User's SPI routines must
allows rebuild query and user (PREPARE) must knows that prepared planns are
not VIEW (!)

BTW. - if we want really "Hot swapping" for qcache too, we can (also)
save native not parsed query strings into query cache and rebuild it after
on-the-fly backend change.

I have some scenario too:

- PostgreSQL is backend for web application and this application very
often send to PG same query and PG has feature that allows save 95%
time of query parsing :-)

- or user has trigger (RI?) and this trigger always run only
SPI_execp_by_key()...

Well, I prepare it with '#ifdef HAVE_QCACHE'.

Karel

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Bruce Momjian 2000-06-29 16:17:19 psql use of 'volatile'
Previous Message Peter Eisentraut 2000-06-29 15:31:19 Automatic dependency generation