Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qgUvY-00G2dt-7n for pgsql-docs@arkaria.postgresql.org; Wed, 13 Sep 2023 18:49:28 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1qgUvW-001cx7-MU for pgsql-docs@arkaria.postgresql.org; Wed, 13 Sep 2023 18:49:26 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qgUvV-001cwr-T5 for pgsql-docs@lists.postgresql.org; Wed, 13 Sep 2023 18:49:26 +0000 Received: from wout3-smtp.messagingengine.com ([64.147.123.19]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1qgUvQ-004tBO-O8 for pgsql-docs@lists.postgresql.org; Wed, 13 Sep 2023 18:49:25 +0000 Received: from compute6.internal (compute6.nyi.internal [10.202.2.47]) by mailout.west.internal (Postfix) with ESMTP id 5B8DB320097A; Wed, 13 Sep 2023 14:49:17 -0400 (EDT) Received: from imap49 ([10.202.2.99]) by compute6.internal (MEProxy); Wed, 13 Sep 2023 14:49:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=eulerto.com; h= cc:content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:sender :subject:subject:to:to; s=fm3; t=1694630956; x=1694717356; bh=58 K/Kz4jCSHsdaUO/f4hMrf1BF/zwRnodSW2Xy3XxAQ=; b=i3QWLTS4XpDf/pv4Id AdDCIH3N4iECo98MLpagHBcQebwfrIrlDg9xgArZZ/wWoDooNittZqMcYP8S9ONQ fumIpXBTADAHKHhLBWCTC2Qt5Ie3cmnDLKPmLP1NznlsMD5WFv+a7aLH+5Q7i5y5 u03OyYRSVZzmNK210iiYcVW6qJkoO2JkIaXwFKZkejBToM3iAY0mslSYCnxvOkpa Yx4WC3nA9MyYfbbkv27MCL9vXwzQGyJlM6hs+e0JupaF5JPU6e1KGaGkzLSxU+hT wC0wG+gLzJARYG4gnV+7q+dV0DaMvKcGkSlSQ42/nSUPlf55WANJZ2eOpcyvn+ir NVjw== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm2; t=1694630956; x=1694717356; bh=58K/Kz4jCSHsd aUO/f4hMrf1BF/zwRnodSW2Xy3XxAQ=; b=L7dDvf10fYtx4PxAELjWQ4ckun7XP uLbB7HQ5kSAKzGkvrt2ZNiOcx0hyXuKgvRHATqk8GjxOEY6tr2fHd0/CxC8Sd68i KgIHqrm3X24Jk5NfbqnlOsWOMg/iDMftpXCfJDXtdFGHCjsLR4YVBrLl79/6XFjA esoUUNwjMOzNC1Dozy4OGod1WGin4c9U4RNUecqOdKD4e/TRm/y0YqLjNQF7xNDn o3vJZDRYfguDElPznIMtfhyq7KzpCuQ2ZI8Y/8vWuYbCjVh74gz9lcARKu19kpgR ZxtGiLbPUFASUFQvC201WkmqNdvteKS15OI2oaP00I9Qg8J67rQtlB3zw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedviedrudeikedguddvlecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecunecujfgurhepofgfggfkjghffffhvffutgesrg dtreerreertdenucfhrhhomhepfdfguhhlvghrucfvrghvvghirhgrfdcuoegvuhhlvghr segvuhhlvghrthhordgtohhmqeenucggtffrrghtthgvrhhnpedtjeffieeuieeggeehie eutdevleetteejiedtgfehheefueekvefftedujefhffenucffohhmrghinhepphhoshht ghhrvghsqhhlrdhorhhgpdgvnhhtvghrphhrihhsvggusgdrtghomhenucevlhhushhtvg hrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpegvuhhlvghrsegvuhhlvghr thhordgtohhm X-ME-Proxy: Feedback-ID: i0c21471d:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id 827D315A0092; Wed, 13 Sep 2023 14:49:16 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.9.0-alpha0-745-g95dd7bea33-fm-20230905.001-g95dd7bea Mime-Version: 1.0 Message-Id: In-Reply-To: <169454016225.2433963.11433530945607791340@wrigleys.postgresql.org> References: <169454016225.2433963.11433530945607791340@wrigleys.postgresql.org> Date: Wed, 13 Sep 2023 15:48:41 -0300 From: "Euler Taveira" To: postgresql@seebs.net, pgsql-docs@lists.postgresql.org Subject: Re: index access method documentation light on details on ii_AmCache Content-Type: multipart/alternative; boundary=7940dd648e284bf1996fe76b24946d34 List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --7940dd648e284bf1996fe76b24946d34 Content-Type: text/plain On Tue, Sep 12, 2023, at 2:36 PM, PG Doc comments form wrote: > The following documentation comment has been logged on the website: > > Page: https://www.postgresql.org/docs/15/index-functions.html > Description: > > So, if I cache something in ii_AmCache during a call to my aminsert > callback... > > When, if ever, does it get freed? > > Having looked at example code, I don't actually see anything doing this in > insert paths, so presumably there's some point at which this happens > automatically, possibly as part of the Memory Context thing, maybe related > to the ii_Context which seems to be getting used, but I can't find anything > anywhere documenting that. This may well be completely obvious, or intended > to be implied by "it can allocate space in indexInfo->ii_Context", but it's > not exceptionally obvious to me as a newcomer to the code. (By contrast, the > ambuild docs say to palloc a data structure, but don't mention a context for > it; no idea whether it should be in a particular context.) > Maybe it is not clear by the comment in the IndexInfo struct but ii_AmCache is a pointer to the AM state information that is stored into ii_Context memory context (see gistinsert, gininsert or brininsert to understand how ii_Context and ii_AmCache are used). The document that you shared also has a sentence with this information. Unless you change it, ii_Context is CurrentMemoryContext (see makeIndexInfo). Hence, your AM state information is freed when the current memory context is freed. You can use gdb to figure out what's the memory context you are in. Start a session, create a table and an index on it. Attach gdb to this current session and add a breakpoint into one of the AM insert function that I mentioned in the previous paragraph. Insert a row and continue: (gdb) b initGinState Breakpoint 1 at 0x55a47b179d80: file ginutil.c, line 98. (gdb) c Continuing. Breakpoint 1, initGinState (state=state@entry=0x55a47d40cd58, index=index@entry=0x7f1970352d40) at ginutil.c:98 (gdb) bt #0 initGinState (state=state@entry=0x55a47d40cd58, index=index@entry=0x7f1970352d40) at ginutil.c:98 #1 0x000055a47b178255 in gininsert (index=0x7f1970352d40, values=0x7fff31d04a80, isnull=0x7fff31d04a60, ht_ctid=0x55a47d415ef8, heapRel=, checkUnique=, indexUnchanged=false, indexInfo=0x55a47d4164f8) at gininsert.c:502 #2 0x000055a47b3100f6 in ExecInsertIndexTuples (resultRelInfo=resultRelInfo@entry=0x55a47d415328, slot=slot@entry=0x55a47d415ec8, estate=estate@entry=0x55a47d414e98, update=update@entry=false, noDupErr=noDupErr@entry=false, specConflict=specConflict@entry=0x0, arbiterIndexes=0x0, onlySummarizing=false) at execIndexing.c:432 . . . (gdb) f 1 #1 0x000055a47b178255 in gininsert (index=0x7f1970352d40, values=0x7fff31d04a80, isnull=0x7fff31d04a60, ht_ctid=0x55a47d415ef8, heapRel=, checkUnique=, indexUnchanged=false, indexInfo=0x55a47d4164f8) at gininsert.c:502 (gdb) p *indexInfo->ii_Context $3 = {type = T_AllocSetContext, isReset = false, allowInCritSection = false, mem_allocated = 17912, methods = 0x55a47b9302f0 , parent = 0x55a47d3fdda0, firstchild = 0x55a47d408cd0, prevchild = 0x0, nextchild = 0x0, name = 0x55a47b751813 "ExecutorState", ident = 0x0, reset_cbs = 0x0} The "ExecutorState" is a per query memory context so it is deallocated when the query ends. > Actually, in full generality, I have not been able to find a section of the > documentation which explains the memory-context stuff at all. I found a blog > post elsewhere suggesting that it's just "the memory context will be freed > and thus everything associated with it". This implies that there's no > straightforward way for an index to do end-of-insert maintenance after all > the inserts from a given query are complete, except to do it after every > tuple just in case it's the last tuple, I guess? > Check src/backend/utils/mmgr/README. -- Euler Taveira EDB https://www.enterprisedb.com/ --7940dd648e284bf1996fe76b24946d34 Content-Type: text/html Content-Transfer-Encoding: quoted-printable
On Tue, Sep 12,= 2023, at 2:36 PM, PG Doc comments form wrote:
The following documentation comment = has been logged on the website:

De= scription:

So, if I cache something in ii_A= mCache during a call to my aminsert
callback...
<= div>
When, if ever, does it get freed?

<= /div>
Having looked at example code, I don't actually see anything d= oing this in
insert paths, so presumably there's some poin= t at which this happens
automatically, possibly as part of= the Memory Context thing, maybe related
to the ii_Context= which seems to be getting used, but I can't find anything
anywhere documenting that. This may well be completely obvious, or inte= nded
to be implied by "it can allocate space in indexInfo-= >ii_Context", but it's
not exceptionally obvious to me = as a newcomer to the code. (By contrast, the
ambuild docs = say to palloc a data structure, but don't mention a context for
it; no idea whether it should be in a particular context.)


Maybe it is not clear = by the comment in the IndexInfo struct but ii_AmCache is
a= pointer to the AM state information that is stored into ii_Context memo= ry
context (see gistinsert, gininsert or brininsert to und= erstand how ii_Context
and ii_AmCache are used). The docum= ent that you shared also has a sentence with
this informat= ion.

Unless you change it, ii_Context is Cu= rrentMemoryContext (see makeIndexInfo).
Hence, your AM sta= te information is freed when the current memory context is
freed. You can use gdb to figure out what's the memory context you are = in.
Start a session, create a table and an index on it. At= tach gdb to this current
session and add a breakpoint into= one of the AM insert function that I
mentioned in the pre= vious paragraph. Insert a row and continue:

(gdb) b initGinState
Breakpoint 1 at 0x55a47b179d80: file= ginutil.c, line 98.
(gdb) c
Continuing.
=

Breakpoint 1, initGinState (state=3Dstate@entr= y=3D0x55a47d40cd58, index=3Dindex@entry=3D0x7f1970352d40)
=     at ginutil.c:98
(gdb) bt
= #0  initGinState (state=3Dstate@entry=3D0x55a47d40cd58, index=3Dind= ex@entry=3D0x7f1970352d40) at ginutil.c:98
#1  0x0000= 55a47b178255 in gininsert (index=3D0x7f1970352d40, values=3D0x7fff31d04a= 80, isnull=3D0x7fff31d04a60, 
    ht_c= tid=3D0x55a47d415ef8, heapRel=3D<optimized out>, checkUnique=3D<= ;optimized out>, indexUnchanged=3Dfalse, 
 &n= bsp;  indexInfo=3D0x55a47d4164f8) at gininsert.c:502
= #2  0x000055a47b3100f6 in ExecInsertIndexTuples (resultRelInfo=3Dre= sultRelInfo@entry=3D0x55a47d415328, 
  &nbs= p; slot=3Dslot@entry=3D0x55a47d415ec8, estate=3Destate@entry=3D0x55a47d4= 14e98, update=3Dupdate@entry=3Dfalse, 
  &n= bsp; noDupErr=3DnoDupErr@entry=3Dfalse, specConflict=3DspecConflict@entr= y=3D0x0, arbiterIndexes=3D0x0, 
    on= lySummarizing=3Dfalse) at execIndexing.c:432
.
.
.
(gdb) f 1
#1  0x00= 0055a47b178255 in gininsert (index=3D0x7f1970352d40, values=3D0x7fff31d0= 4a80, isnull=3D0x7fff31d04a60,
    ht_ctid=3D= 0x55a47d415ef8, heapRel=3D<optimized out>, checkUnique=3D<optim= ized out>, indexUnchanged=3Dfalse,
    i= ndexInfo=3D0x55a47d4164f8) at gininsert.c:502
(gdb) p *ind= exInfo->ii_Context
$3 =3D {type =3D T_AllocSetContext, = isReset =3D false, allowInCritSection =3D false, mem_allocated =3D 17912= , 
  methods =3D 0x55a47b9302f0 <mcxt_methods= +240>, parent =3D 0x55a47d3fdda0, firstchild =3D 0x55a47d408cd0, = ;
  prevchild =3D 0x0, nextchild =3D 0x0, name =3D 0x= 55a47b751813 "ExecutorState", ident =3D 0x0, reset_cbs =3D 0x0}

The "ExecutorState" is a per query memory context s= o it is deallocated when the
query ends.
Actually, in = full generality, I have not been able to find a section of the
=
documentation which explains the memory-context stuff at all. I fou= nd a blog
post elsewhere suggesting that it's just "the me= mory context will be freed
and thus everything associated = with it". This implies that there's no
straightforward way= for an index to do end-of-insert maintenance after all
th= e inserts from a given query are complete, except to do it after every
tuple just in case it's the last tuple, I guess?
<= div>

Check src/backend/utils/m= mgr/README.


--
Euler = Taveira
<= /div>

--7940dd648e284bf1996fe76b24946d34--