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 1u23vc-00CKTk-Bi for pgsql-hackers@arkaria.postgresql.org; Tue, 08 Apr 2025 08:03:29 +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 1u23va-0078Pp-3x for pgsql-hackers@arkaria.postgresql.org; Tue, 08 Apr 2025 08:03: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 1u23vZ-0078Pf-GK for pgsql-hackers@lists.postgresql.org; Tue, 08 Apr 2025 08:03:26 +0000 Received: from smtp.outgoing.loopia.se ([93.188.3.37]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1u23vX-0045qH-0N for pgsql-hackers@postgresql.org; Tue, 08 Apr 2025 08:03:25 +0000 Received: from s807.loopia.se (localhost [127.0.0.1]) by s807.loopia.se (Postfix) with ESMTP id 1B90D331999 for ; Tue, 08 Apr 2025 10:03:21 +0200 (CEST) Received: from s980.loopia.se (unknown [172.22.191.5]) by s807.loopia.se (Postfix) with ESMTP id 05C4B331666; Tue, 08 Apr 2025 10:03:21 +0200 (CEST) Received: from s472.loopia.se (unknown [172.22.191.6]) by s980.loopia.se (Postfix) with ESMTP id EBEB722016C9; Tue, 08 Apr 2025 10:03:20 +0200 (CEST) X-Virus-Scanned: amavisd-new at amavis.loopia.se X-Spam-Flag: NO X-Spam-Score: -1.199 X-Spam-Level: X-Spam-Status: No, score=-1.199 tagged_above=-999 required=6.2 tests=[ALL_TRUSTED=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001] autolearn=disabled Authentication-Results: s472.loopia.se (amavisd-new); dkim=pass (2048-bit key) header.d=yesql.se Received: from s979.loopia.se ([172.22.191.5]) by s472.loopia.se (s472.loopia.se [172.22.190.12]) (amavisd-new, port 10024) with UTF8LMTP id BxZ5XoRg4JqO; Tue, 8 Apr 2025 10:03:20 +0200 (CEST) X-Loopia-Auth: user X-Loopia-User: daniel@yesql.se X-Loopia-Originating-IP: 89.255.232.193 Received: from smtpclient.apple (customer-89-255-232-193.stosn.net [89.255.232.193]) (Authenticated sender: daniel@yesql.se) by s979.loopia.se (Postfix) with ESMTPSA id E449C10BC48D; Tue, 08 Apr 2025 10:03:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yesql.se; s=loopiadkim1707475645; t=1744099400; bh=suQ2AR1Rr6b+muxcypcJotrG4vOJLgzLMoHPE9NeQnE=; h=From:Subject:Date:In-Reply-To:Cc:To:References; b=K1uj4jVRJm01RcsDBHjimnK6oOPMqY6nLrO+LHnyf4Eyl3b7QpIYHSafrjsbsjcAN 1JHzH8Czma0Qr5oXnWdSoJfWEGXqhMqMs7qghOQ3AcuQ0GFMZoKt+XYUPj1NQib+gK TdmzhO6BrlnKN4/KAxZOPecoA6npSQM0JHFPq38aIuIStOoXZ7WgYFwWjz22hXfuPN uFQmGkIIOd6JpHTE/FpqjXb41uHQDKjjKw1LnJbgJbMRNSPSr4Ory9w0ZwVqagk2vn zUnm2iMuoo8G7TlJLg3thx242/aP0ECA++e7lQWqaD2B7Uze8mMu0FnbjSYh7enCTL OuGnAblhupWgw== From: Daniel Gustafsson Message-Id: Content-Type: multipart/alternative; boundary="Apple-Mail=_21310A6A-E5F1-4E61-AB75-9B7D3C412E58" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3776.700.51.11.1\)) Subject: Re: Enhancing Memory Context Statistics Reporting Date: Tue, 8 Apr 2025 10:03:09 +0200 In-Reply-To: Cc: Andres Freund , PostgreSQL Hackers To: Rahila Syed References: <54FAE93D-E156-4684-9352-1CEDE6BD4A1C@yesql.se> <5bxhxniyvjyfldi7yjxcnxkl3i2ghci2grjyeclrbkfqnyhowk@dfkqzbvtbpml> X-Mailer: Apple Mail (2.3776.700.51.11.1) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_21310A6A-E5F1-4E61-AB75-9B7D3C412E58 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On 8 Apr 2025, at 07:40, Rahila Syed wrote: > =20 >> > Renamed both to use MemoryContextReporting* namespace, which leaves >> > MemoryContextReportingBackendState at an unwieldly long name. I'm = running out >> > of ideas on how to improve and it does make purpose quite explicit = at least. >>=20 >> How about >>=20 >> MemoryContextReportingBackendState -> MemoryStatsBackendState >> MemoryContextReportingId -> MemoryStatsContextId >> MemoryContextReportingSharedState -> MemoryStatsCtl >> MemoryContextReportingStatsEntry -> MemoryStatsEntry > =20 > Fixed accordingly. That's much better, thanks. There was a bug in the shmem init function which caused it to fail on = Windows, the attached fixes that. -- Daniel Gustafsson =EF=BF=BC= --Apple-Mail=_21310A6A-E5F1-4E61-AB75-9B7D3C412E58 Content-Type: multipart/mixed; boundary="Apple-Mail=_9EDD47DB-9E7B-45A3-93DD-8E1FC0B49F61" --Apple-Mail=_9EDD47DB-9E7B-45A3-93DD-8E1FC0B49F61 Content-Transfer-Encoding: 7bit Content-Type: text/html; charset=us-ascii
On 8 Apr 2025, at 07:40, Rahila Syed <rahilasyed90@gmail.com> wrote:

 
> Renamed both to use MemoryContextReporting* namespace, which leaves
> MemoryContextReportingBackendState at an unwieldly long name.  I'm running out
> of ideas on how to improve and it does make purpose quite explicit at least.

How about

MemoryContextReportingBackendState -> MemoryStatsBackendState
MemoryContextReportingId -> MemoryStatsContextId
MemoryContextReportingSharedState -> MemoryStatsCtl
MemoryContextReportingStatsEntry -> MemoryStatsEntry
 
Fixed accordingly.

That's much better, thanks.

There was a bug in the shmem init function which caused it to fail on Windows,
the attached fixes that.

--
Daniel Gustafsson

--Apple-Mail=_9EDD47DB-9E7B-45A3-93DD-8E1FC0B49F61 Content-Disposition: attachment; filename=v29-0001-Add-function-to-get-memory-context-stats-for-pro.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v29-0001-Add-function-to-get-memory-context-stats-for-pro.patch" Content-Transfer-Encoding: quoted-printable =46rom=20ec215974fff965040e3531ac57c3fc3023be07ff=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Rahila=20Syed=20=0A= Date:=20Tue,=208=20Apr=202025=2009:38:12=20+0530=0ASubject:=20[PATCH=20= v29]=20Add=20function=20to=20get=20memory=20context=20stats=20for=20= processes=0A=0AThis=20adds=20a=20function=20for=20retrieving=20memory=20= context=20statistics=0Aand=20information=20from=20backends=20as=20well=20= as=20auxiliary=20processes.=0A=0AWhen=20calling=20the=20function=20it=20= sends=20a=20signal=20to=20the=20specified=0Aprocess=20to=20submit=20= statistics=20regarding=20its=20memory=20contexts=0Ainto=20dynamic=20= shared=20memory.=20=20Each=20memory=20context=20is=20returned=0Ain=20= detail,=20followed=20by=20a=20cumulative=20total=20in=20case=20the=20= number=0Aof=20contexts=20exceed=20the=20max=20allocated=20amount=20of=20= shared=20memory.=0AEach=20process=20is=20limited=20to=20use=20at=20most=20= 1Mb=20memory=20for=20this.=0A=0AA=20summary=20can=20also=20be=20= explicitly=20requested=20by=20the=20user,=20this=0Awill=20return=20the=20= TopMemoryContext=20and=20a=20cumulative=20total=20of=0Aall=20lower=20= contexts.=0A=0AIn=20order=20to=20not=20block=20on=20busy=20processes=20= the=20caller=20specifies=0Athe=20number=20of=20seconds=20during=20which=20= to=20retry=20before=20timing=20out.=0AIn=20the=20case=20where=20no=20= statistics=20are=20published=20within=20the=20set=0Atimeout,=20=20the=20= last=20known=20statistics=20are=20returned,=20or=20NULL=20if=0Ano=20= previously=20published=20statistics=20exist.=20=20This=20allows=20dash-=0A= board=20type=20usages=20to=20continually=20publish=20data=20even=20if=20= the=0Atarget=20process=20is=20temporarily=20congested.=20=20Context=20= records=0Acontain=20a=20timestamp=20to=20indicate=20when=20they=20were=20= submitted.=0A=0AAuthor:=20Rahila=20Syed=20=0A= Reviewed-by:=20Daniel=20Gustafsson=20=0AReviewed-by:=20= Andres=20Freund=20=0AReviewed-by:=20Tomas=20Vondra=20= =0AReviewed-by:=20Atsushi=20Torikoshi=20= =0AReviewed-by:=20Fujii=20Masao=20= =0AReviewed-by:=20Alexander=20Korotkov=20= =0ADiscussion:=20= https://postgr.es/m/CAH2L28v8mc9HDt8QoSJ8TRmKau_8FM_HKS41NeO9-6ZAkuZKXw@ma= il.gmail.com=0A---=0A=20doc/src/sgml/func.sgml=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20171=20+++++=0A=20= src/backend/catalog/system_views.sql=20=20=20=20=20=20=20=20=20=20|=20=20= =205=20+=0A=20src/backend/postmaster/autovacuum.c=20=20=20=20=20=20=20=20= =20=20=20|=20=20=204=20+=0A=20src/backend/postmaster/checkpointer.c=20=20= =20=20=20=20=20=20=20|=20=20=204=20+=0A=20= src/backend/postmaster/interrupt.c=20=20=20=20=20=20=20=20=20=20=20=20|=20= =20=204=20+=0A=20src/backend/postmaster/pgarch.c=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20|=20=20=204=20+=0A=20src/backend/postmaster/startup.c=20= =20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=204=20+=0A=20= src/backend/postmaster/walsummarizer.c=20=20=20=20=20=20=20=20|=20=20=20= 4=20+=0A=20src/backend/storage/ipc/ipci.c=20=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20|=20=20=203=20+=0A=20src/backend/storage/ipc/procsignal.c=20= =20=20=20=20=20=20=20=20=20|=20=20=203=20+=0A=20= src/backend/storage/lmgr/lwlock.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=202=20+=0A=20src/backend/storage/lmgr/proc.c=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20|=20=20=201=20+=0A=20src/backend/tcop/postgres.c=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=203=20+=0A=20= .../utils/activity/wait_event_names.txt=20=20=20=20=20=20=20|=20=20=201=20= +=0A=20src/backend/utils/adt/mcxtfuncs.c=20=20=20=20=20=20=20=20=20=20=20= =20=20|=20426=20+++++++++++-=0A=20src/backend/utils/init/globals.c=20=20=20= =20=20=20=20=20=20=20=20=20=20=20|=20=20=201=20+=0A=20= src/backend/utils/init/postinit.c=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=207=20+=0A=20src/backend/utils/mmgr/mcxt.c=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20|=20644=20+++++++++++++++++-=0A=20= src/include/catalog/pg_proc.dat=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20=2010=20+=0A=20src/include/miscadmin.h=20=20=20=20=20=20=20=20=20=20= =20=20=20=20=20=20=20=20=20=20=20=20=20|=20=20=201=20+=0A=20= src/include/storage/lwlock.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20|=20=20=202=20+=0A=20src/include/storage/procsignal.h=20=20=20=20= =20=20=20=20=20=20=20=20=20=20|=20=20=201=20+=0A=20= src/include/utils/memutils.h=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20=20|=20=2082=20+++=0A=20src/test/regress/expected/sysviews.out=20=20= =20=20=20=20=20=20|=20=2019=20+=0A=20src/test/regress/sql/sysviews.sql=20= =20=20=20=20=20=20=20=20=20=20=20=20|=20=2018=20+=0A=20= src/tools/pgindent/typedefs.list=20=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20=20=204=20+=0A=2026=20files=20changed,=201383=20insertions(+),=2045=20= deletions(-)=0A=0Adiff=20--git=20a/doc/src/sgml/func.sgml=20= b/doc/src/sgml/func.sgml=0Aindex=209ab070adffb..42ec4340da1=20100644=0A= ---=20a/doc/src/sgml/func.sgml=0A+++=20b/doc/src/sgml/func.sgml=0A@@=20= -28663,6=20+28663,144=20@@=20acl=20=20=20=20=20=20|=20= {postgres=3DarwdDxtm/postgres,foo=3Dr/postgres}=0A=20=20=20=20=20=20=20=20= =0A=20=20=20=20=20=20=20=0A=20=0A+=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=20=20pg_get_process_memory_contexts=0A= +=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= pg_get_process_memory_contexts=20(=20= pid=20integer,=20= summary=20boolean,=20= timeout=20float=20)=0A+=20=20=20=20=20= =20=20=20setof=20record=0A+=20=20=20=20=20=20=20= =20(=20name=20text,=0A+=20=20=20=20=20= =20=20=20ident=20text,=0A+=20=20=20=20= =20=20=20=20type=20text,=0A+=20=20=20= =20=20=20=20=20path=20integer[],=0A+=20= =20=20=20=20=20=20=20level=20= integer,=0A+=20=20=20=20=20=20=20=20= total_bytes=20bigint,=0A+=20=20=20=20= =20=20=20=20total_nblocks=20bigint,=0A= +=20=20=20=20=20=20=20=20free_bytes=20= bigint,=0A+=20=20=20=20=20=20=20=20= free_chunks=20bigint,=0A+=20=20=20=20= =20=20=20=20used_bytes=20bigint,=0A+=20= =20=20=20=20=20=20=20num_agg_contexts=20= integer,=0A+=20=20=20=20=20=20=20=20= stats_timestamp=20timestamptz=20)=0A= +=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20This=20function=20handles=20requests=20to=20display=20the=20= memory=20contexts=20of=20a=0A+=20=20=20=20=20=20=20=20= PostgreSQL=20process=20with=20the=20specified=0A= +=20=20=20=20=20=20=20=20process=20ID.=20=20The=20function=20can=20be=20= used=20to=20send=20requests=20to=20backends=20as=0A+=20=20=20=20=20=20=20= =20well=20as=20auxiliary=20= processes.=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20The=20returned=20record=20= contains=20extended=20statistics=20per=20each=20memory=0A+=20=20=20=20=20= =20=20=20context:=0A+=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= name=20-=20The=20name=20of=20the=20memory=20= context.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= ident=20-=20Memory=20context=20ID=20(if=20any).=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= type=20-=20The=20type=20of=20memory=20context,=20= possible=0A+=20=20=20=20=20=20=20=20=20=20=20values=20are:=20AllocSet,=20= Generation,=20Slab=20and=20Bump.=0A+=20=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20=20=20=20path=20-=20Memory=20contexts=20= are=20organized=20in=20a=0A+=20=20=20=20=20=20=20=20=20=20=20tree=20= model=20with=20TopMemoryContext=20as=20the=20root,=20and=20all=20other=20= memory=0A+=20=20=20=20=20=20=20=20=20=20=20contexts=20as=20nodes=20in=20= the=20tree.=20The=20path=0A+=20=20=20=20=20=20=20=20= =20=20=20displays=20the=20path=20from=20the=20root=20to=20the=20current=20= memory=20context.=20The=0A+=20=20=20=20=20=20=20=20=20=20=20path=20is=20= limited=20to=20100=20children=20per=20node,=20which=20each=20node=20= limited=0A+=20=20=20=20=20=20=20=20=20=20=20to=20a=20max=20depth=20of=20= 100,=20to=20preserve=20memory=20during=20reporting.=20The=0A+=20=20=20=20= =20=20=20=20=20=20=20printed=20path=20will=20also=20be=20limited=20to=20= 100=20nodes=20counting=20from=20the=0A+=20=20=20=20=20=20=20=20=20=20=20= TopMemoryContext.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= level=20-=20The=20level=20in=20the=20tree=20of=20= the=20current=0A+=20=20=20=20=20=20=20=20=20=20=20memory=20context.=0A+=20= =20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= total_bytes=20-=20The=20total=20number=20of=20= bytes=0A+=20=20=20=20=20=20=20=20=20=20=20allocated=20to=20this=20memory=20= context.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= total_nblocks=20-=20The=20total=20number=20of=20= blocks=0A+=20=20=20=20=20=20=20=20=20=20=20used=20for=20the=20allocated=20= memory.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= free_bytes=20-=20The=20amount=20of=20free=20= memory=20in=0A+=20=20=20=20=20=20=20=20=20=20=20this=20memory=20context.=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= free_chunks=20-=20The=20number=20of=20chunks=20= that=0A+=20=20=20=20=20=20=20=20=20=20=20= free_bytes=20corresponds=20to.=0A+=20=20=20=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=20=20=20=20used_bytes=20-=20= The=20total=20number=20of=20bytes=0A+=20=20=20=20=20=20=20=20=20=20=20= currently=20occupied.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=0A= +=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20=20=20= num_agg_contexts=20-=20The=20number=20of=20memory=0A= +=20=20=20=20=20=20=20=20=20=20=20contexts=20aggregated=20in=20the=20= displayed=20statistics.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20= =20=20=20=20stats_timestamp=20-=20When=20the=20= statistics=20were=0A+=20=20=20=20=20=20=20=20=20=20=20extracted=20from=20= the=20process.=0A+=20=20=20=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20=20=0A+=20=20=20=20=20=20=20=20=0A+=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20= =20=20=20When=20summary=20is=20= true,=20statistics=0A+=20=20=20=20=20=20=20=20for=20= memory=20contexts=20at=20levels=201=20and=202=20are=20displayed,=20with=20= level=201=0A+=20=20=20=20=20=20=20=20representing=20the=20root=20node=20= (i.e.,=20TopMemoryContext).=0A+=20=20=20=20=20=20=20=20= Statistics=20for=20contexts=20on=20level=202=20and=20below=20are=20= aggregates=20of=20all=0A+=20=20=20=20=20=20=20=20child=20contexts'=20= statistics,=20where=20num_agg_contexts=0A+=20=20=20=20= =20=20=20=20indicate=20the=20number=20aggregated=20child=20contexts.=20=20= When=0A+=20=20=20=20=20=20=20=20summary=20is=20= false,=0A+=20=20=20=20=20=20=20=20the=20= num_agg_contexts=20value=20is=201,=0A+=20=20= =20=20=20=20=20=20indicating=20that=20individual=20statistics=20are=20= being=20displayed.=20The=20levels=0A+=20=20=20=20=20=20=20=20are=20= limited=20to=20the=20first=20100=20contexts.=0A+=20=20=20=20=20=20=20= =0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20Busy=20= processes=20can=20delay=20reporting=20memory=20context=20statistics,=0A+=20= =20=20=20=20=20=20=20timeout=20specifies=20the=20= number=20of=20seconds=0A+=20=20=20=20=20=20=20=20to=20wait=20for=20= updated=20statistics.=20timeout=20can=20be=0A+=20=20= =20=20=20=20=20=20specified=20in=20fractions=20of=20a=20second.=0A+=20=20= =20=20=20=20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20= =20=20After=20receiving=20memory=20context=20statistics=20from=20the=20= target=20process,=20it=0A+=20=20=20=20=20=20=20=20returns=20the=20= results=20as=20one=20row=20per=20context.=20=20If=20all=20the=20contexts=20= don't=0A+=20=20=20=20=20=20=20=20fit=20within=20the=20pre-determined=20= size=20limit,=20the=20remaining=20context=0A+=20=20=20=20=20=20=20=20= statistics=20are=20aggregated=20and=20a=20cumulative=20total=20is=20= displayed.=20=20The=0A+=20=20=20=20=20=20=20=20= num_agg_contexts=20column=20indicates=20the=20number=20= of=0A+=20=20=20=20=20=20=20=20contexts=20aggregated=20in=20the=20= displayed=20statistics.=20=20When=0A+=20=20=20=20=20=20=20=20= num_agg_contexts=20is=201=20is=20= means=0A+=20=20=20=20=20=20=20=20that=20the=20context=20statistics=20are=20= displayed=20separately.=0A+=20=20=20=20=20=20=20=0A+=20=20= =20=20=20=20=0A+=0A=20=20=20=20=20=20=20=0A=20=20=20=20=20=20=20= =20=0A= =20=20=20=20=20=20=20=20=20=0A@@=20-28802,6=20+28940,39=20@@=20= LOG:=20=20Grand=20total:=201651920=20bytes=20in=20201=20blocks;=20622360=20= free=20(88=20chunks);=201029560=0A=20=20=20=20=20because=20it=20may=20= generate=20a=20large=20number=20of=20log=20messages.=0A=20=20=20=20= =0A=20=0A+=20=20=20=0A+=20=20=20=20= pg_get_process_memory_contexts=20can=20be=20used=0A= +=20=20=20=20to=20request=20the=20memory=20contexts=20statistics=20of=20= any=20postgres=20process.=20For=20example:=0A+=0A= +postgres=3D#=20SELECT=20*=20FROM=20pg_get_process_memory_contexts(=0A+=20= =20(SELECT=20pid=20FROM=20pg_stat_activity=0A+=20=20=20=20WHERE=20= backend_type=20=3D=20'checkpointer'),=0A+=20=20false,=200.5)=20LIMIT=20= 1;=0A+-[=20RECORD=201=20]----+------------------------------=0A+name=20=20= =20=20=20=20=20=20=20=20=20=20=20|=20TopMemoryContext=0A+ident=20=20=20=20= =20=20=20=20=20=20=20=20|=0A+type=20=20=20=20=20=20=20=20=20=20=20=20=20= |=20AllocSet=0A+path=20=20=20=20=20=20=20=20=20=20=20=20=20|=20{1}=0A= +level=20=20=20=20=20=20=20=20=20=20=20=20|=201=0A+total_bytes=20=20=20=20= =20=20|=2090304=0A+total_nblocks=20=20=20=20|=203=0A+free_bytes=20=20=20=20= =20=20=20|=202880=0A+free_chunks=20=20=20=20=20=20|=201=0A+used_bytes=20=20= =20=20=20=20=20|=2087424=0A+num_agg_contexts=20|=201=0A+stats_timestamp=20= =20|=202025-03-24=2013:55:47.796698+01=0A+=0A+=20=20=20=20= =0A+=20=20=20=20=20=0A+=20=20=20=20=20=20While=20= pg_get_process_memory_contexts=20can=20be=20used=20= to=0A+=20=20=20=20=20=20query=20memory=20contexts=20of=20the=20local=20= backend,=0A+=20=20=20=20=20=20= pg_backend_memory_contexts=0A+=20=20=20=20=20=20= (see=20=20for=20= more=20details)=0A+=20=20=20=20=20=20will=20be=20less=20resource=20= intensive=20when=20only=20the=20local=20backend=20is=20of=20interest.=0A= +=20=20=20=20=20=0A+=20=20=20=20=0A+=20=20=20=0A+=0A= =20=20=20=0A=20=0A=20=20=20= =0Adiff=20--git=20a/src/backend/catalog/system_views.sql=20= b/src/backend/catalog/system_views.sql=0Aindex=20= 08f780a2e63..15efb02badb=20100644=0A---=20= a/src/backend/catalog/system_views.sql=0A+++=20= b/src/backend/catalog/system_views.sql=0A@@=20-674,6=20+674,11=20@@=20= GRANT=20SELECT=20ON=20pg_backend_memory_contexts=20TO=20= pg_read_all_stats;=0A=20REVOKE=20EXECUTE=20ON=20FUNCTION=20= pg_get_backend_memory_contexts()=20FROM=20PUBLIC;=0A=20GRANT=20EXECUTE=20= ON=20FUNCTION=20pg_get_backend_memory_contexts()=20TO=20= pg_read_all_stats;=0A=20=0A+REVOKE=20EXECUTE=20ON=20FUNCTION=0A+=09= pg_get_process_memory_contexts(integer,=20boolean,=20float)=20FROM=20= PUBLIC;=0A+GRANT=20EXECUTE=20ON=20FUNCTION=0A+=09= pg_get_process_memory_contexts(integer,=20boolean,=20float)=20TO=20= pg_read_all_stats;=0A+=0A=20--=20Statistics=20views=0A=20=0A=20CREATE=20= VIEW=20pg_stat_all_tables=20AS=0Adiff=20--git=20= a/src/backend/postmaster/autovacuum.c=20= b/src/backend/postmaster/autovacuum.c=0Aindex=202513a8ef8a6..16756152b71=20= 100644=0A---=20a/src/backend/postmaster/autovacuum.c=0A+++=20= b/src/backend/postmaster/autovacuum.c=0A@@=20-781,6=20+781,10=20@@=20= ProcessAutoVacLauncherInterrupts(void)=0A=20=09if=20= (LogMemoryContextPending)=0A=20=09=09ProcessLogMemoryContextInterrupt();=0A= =20=0A+=09/*=20Publish=20memory=20contexts=20of=20this=20process=20*/=0A= +=09if=20(PublishMemoryContextPending)=0A+=09=09= ProcessGetMemoryContextInterrupt();=0A+=0A=20=09/*=20Process=20sinval=20= catchup=20interrupts=20that=20happened=20while=20sleeping=20*/=0A=20=09= ProcessCatchupInterrupt();=0A=20}=0Adiff=20--git=20= a/src/backend/postmaster/checkpointer.c=20= b/src/backend/postmaster/checkpointer.c=0Aindex=20= fda91ffd1ce..d3cb3f1891c=20100644=0A---=20= a/src/backend/postmaster/checkpointer.c=0A+++=20= b/src/backend/postmaster/checkpointer.c=0A@@=20-663,6=20+663,10=20@@=20= ProcessCheckpointerInterrupts(void)=0A=20=09/*=20Perform=20logging=20of=20= memory=20contexts=20of=20this=20process=20*/=0A=20=09if=20= (LogMemoryContextPending)=0A=20=09=09ProcessLogMemoryContextInterrupt();=0A= +=0A+=09/*=20Publish=20memory=20contexts=20of=20this=20process=20*/=0A+=09= if=20(PublishMemoryContextPending)=0A+=09=09= ProcessGetMemoryContextInterrupt();=0A=20}=0A=20=0A=20/*=0Adiff=20--git=20= a/src/backend/postmaster/interrupt.c=20= b/src/backend/postmaster/interrupt.c=0Aindex=200ae9bf906ec..f24f574e748=20= 100644=0A---=20a/src/backend/postmaster/interrupt.c=0A+++=20= b/src/backend/postmaster/interrupt.c=0A@@=20-48,6=20+48,10=20@@=20= ProcessMainLoopInterrupts(void)=0A=20=09/*=20Perform=20logging=20of=20= memory=20contexts=20of=20this=20process=20*/=0A=20=09if=20= (LogMemoryContextPending)=0A=20=09=09ProcessLogMemoryContextInterrupt();=0A= +=0A+=09/*=20Publish=20memory=20contexts=20of=20this=20process=20*/=0A+=09= if=20(PublishMemoryContextPending)=0A+=09=09= ProcessGetMemoryContextInterrupt();=0A=20}=0A=20=0A=20/*=0Adiff=20--git=20= a/src/backend/postmaster/pgarch.c=20b/src/backend/postmaster/pgarch.c=0A= index=207e622ae4bd2..cb7408acf4c=20100644=0A---=20= a/src/backend/postmaster/pgarch.c=0A+++=20= b/src/backend/postmaster/pgarch.c=0A@@=20-867,6=20+867,10=20@@=20= ProcessPgArchInterrupts(void)=0A=20=09if=20(LogMemoryContextPending)=0A=20= =09=09ProcessLogMemoryContextInterrupt();=0A=20=0A+=09/*=20Publish=20= memory=20contexts=20of=20this=20process=20*/=0A+=09if=20= (PublishMemoryContextPending)=0A+=09=09= ProcessGetMemoryContextInterrupt();=0A+=0A=20=09if=20= (ConfigReloadPending)=0A=20=09{=0A=20=09=09char=09=20=20=20*archiveLib=20= =3D=20pstrdup(XLogArchiveLibrary);=0Adiff=20--git=20= a/src/backend/postmaster/startup.c=20b/src/backend/postmaster/startup.c=0A= index=2027e86cf393f..7149a67fcbc=20100644=0A---=20= a/src/backend/postmaster/startup.c=0A+++=20= b/src/backend/postmaster/startup.c=0A@@=20-192,6=20+192,10=20@@=20= ProcessStartupProcInterrupts(void)=0A=20=09/*=20Perform=20logging=20of=20= memory=20contexts=20of=20this=20process=20*/=0A=20=09if=20= (LogMemoryContextPending)=0A=20=09=09ProcessLogMemoryContextInterrupt();=0A= +=0A+=09/*=20Publish=20memory=20contexts=20of=20this=20process=20*/=0A+=09= if=20(PublishMemoryContextPending)=0A+=09=09= ProcessGetMemoryContextInterrupt();=0A=20}=0A=20=0A=20=0Adiff=20--git=20= a/src/backend/postmaster/walsummarizer.c=20= b/src/backend/postmaster/walsummarizer.c=0Aindex=20= 0fec4f1f871..c7a76711cc5=20100644=0A---=20= a/src/backend/postmaster/walsummarizer.c=0A+++=20= b/src/backend/postmaster/walsummarizer.c=0A@@=20-879,6=20+879,10=20@@=20= ProcessWalSummarizerInterrupts(void)=0A=20=09/*=20Perform=20logging=20of=20= memory=20contexts=20of=20this=20process=20*/=0A=20=09if=20= (LogMemoryContextPending)=0A=20=09=09ProcessLogMemoryContextInterrupt();=0A= +=0A+=09/*=20Publish=20memory=20contexts=20of=20this=20process=20*/=0A+=09= if=20(PublishMemoryContextPending)=0A+=09=09= ProcessGetMemoryContextInterrupt();=0A=20}=0A=20=0A=20/*=0Adiff=20--git=20= a/src/backend/storage/ipc/ipci.c=20b/src/backend/storage/ipc/ipci.c=0A= index=202fa045e6b0f..00c76d05356=20100644=0A---=20= a/src/backend/storage/ipc/ipci.c=0A+++=20= b/src/backend/storage/ipc/ipci.c=0A@@=20-51,6=20+51,7=20@@=0A=20#include=20= "storage/sinvaladt.h"=0A=20#include=20"utils/guc.h"=0A=20#include=20= "utils/injection_point.h"=0A+#include=20"utils/memutils.h"=0A=20=0A=20/*=20= GUCs=20*/=0A=20int=09=09=09shared_memory_type=20=3D=20= DEFAULT_SHARED_MEMORY_TYPE;=0A@@=20-150,6=20+151,7=20@@=20= CalculateShmemSize(int=20*num_semaphores)=0A=20=09size=20=3D=20= add_size(size,=20InjectionPointShmemSize());=0A=20=09size=20=3D=20= add_size(size,=20SlotSyncShmemSize());=0A=20=09size=20=3D=20= add_size(size,=20AioShmemSize());=0A+=09size=20=3D=20add_size(size,=20= MemoryContextReportingShmemSize());=0A=20=0A=20=09/*=20include=20= additional=20requested=20shmem=20from=20preload=20libraries=20*/=0A=20=09= size=20=3D=20add_size(size,=20total_addin_request);=0A@@=20-343,6=20= +345,7=20@@=20CreateOrAttachShmemStructs(void)=0A=20=09= WaitEventCustomShmemInit();=0A=20=09InjectionPointShmemInit();=0A=20=09= AioShmemInit();=0A+=09MemoryContextReportingShmemInit();=0A=20}=0A=20=0A=20= /*=0Adiff=20--git=20a/src/backend/storage/ipc/procsignal.c=20= b/src/backend/storage/ipc/procsignal.c=0Aindex=20= b7c39a4c5f0..a3c2cd12277=20100644=0A---=20= a/src/backend/storage/ipc/procsignal.c=0A+++=20= b/src/backend/storage/ipc/procsignal.c=0A@@=20-690,6=20+690,9=20@@=20= procsignal_sigusr1_handler(SIGNAL_ARGS)=0A=20=09if=20= (CheckProcSignal(PROCSIG_LOG_MEMORY_CONTEXT))=0A=20=09=09= HandleLogMemoryContextInterrupt();=0A=20=0A+=09if=20= (CheckProcSignal(PROCSIG_GET_MEMORY_CONTEXT))=0A+=09=09= HandleGetMemoryContextInterrupt();=0A+=0A=20=09if=20= (CheckProcSignal(PROCSIG_PARALLEL_APPLY_MESSAGE))=0A=20=09=09= HandleParallelApplyMessageInterrupt();=0A=20=0Adiff=20--git=20= a/src/backend/storage/lmgr/lwlock.c=20= b/src/backend/storage/lmgr/lwlock.c=0Aindex=203df29658f18..dc4d96c16af=20= 100644=0A---=20a/src/backend/storage/lmgr/lwlock.c=0A+++=20= b/src/backend/storage/lmgr/lwlock.c=0A@@=20-178,6=20+178,8=20@@=20static=20= const=20char=20*const=20BuiltinTrancheNames[]=20=3D=20{=0A=20=09= [LWTRANCHE_XACT_SLRU]=20=3D=20"XactSLRU",=0A=20=09= [LWTRANCHE_PARALLEL_VACUUM_DSA]=20=3D=20"ParallelVacuumDSA",=0A=20=09= [LWTRANCHE_AIO_URING_COMPLETION]=20=3D=20"AioUringCompletion",=0A+=09= [LWTRANCHE_MEMORY_CONTEXT_REPORTING_STATE]=20=3D=20= "MemoryContextReportingState",=0A+=09= [LWTRANCHE_MEMORY_CONTEXT_REPORTING_PROC]=20=3D=20= "MemoryContextReportingPerProcess",=0A=20};=0A=20=0A=20= StaticAssertDecl(lengthof(BuiltinTrancheNames)=20=3D=3D=0Adiff=20--git=20= a/src/backend/storage/lmgr/proc.c=20b/src/backend/storage/lmgr/proc.c=0A= index=20e9ef0fbfe32..f194e6b3dcc=20100644=0A---=20= a/src/backend/storage/lmgr/proc.c=0A+++=20= b/src/backend/storage/lmgr/proc.c=0A@@=20-50,6=20+50,7=20@@=0A=20= #include=20"storage/procsignal.h"=0A=20#include=20"storage/spin.h"=0A=20= #include=20"storage/standby.h"=0A+#include=20"utils/memutils.h"=0A=20= #include=20"utils/timeout.h"=0A=20#include=20"utils/timestamp.h"=0A=20=0A= diff=20--git=20a/src/backend/tcop/postgres.c=20= b/src/backend/tcop/postgres.c=0Aindex=206ae9f38f0c8..dc4c600922d=20= 100644=0A---=20a/src/backend/tcop/postgres.c=0A+++=20= b/src/backend/tcop/postgres.c=0A@@=20-3535,6=20+3535,9=20@@=20= ProcessInterrupts(void)=0A=20=09if=20(LogMemoryContextPending)=0A=20=09=09= ProcessLogMemoryContextInterrupt();=0A=20=0A+=09if=20= (PublishMemoryContextPending)=0A+=09=09= ProcessGetMemoryContextInterrupt();=0A+=0A=20=09if=20= (ParallelApplyMessagePending)=0A=20=09=09ProcessParallelApplyMessages();=0A= =20}=0Adiff=20--git=20a/src/backend/utils/activity/wait_event_names.txt=20= b/src/backend/utils/activity/wait_event_names.txt=0Aindex=20= 8bce14c38fd..23eaf559c8d=20100644=0A---=20= a/src/backend/utils/activity/wait_event_names.txt=0A+++=20= b/src/backend/utils/activity/wait_event_names.txt=0A@@=20-161,6=20+161,7=20= @@=20WAL_RECEIVER_EXIT=09"Waiting=20for=20the=20WAL=20receiver=20to=20= exit."=0A=20WAL_RECEIVER_WAIT_START=09"Waiting=20for=20startup=20process=20= to=20send=20initial=20data=20for=20streaming=20replication."=0A=20= WAL_SUMMARY_READY=09"Waiting=20for=20a=20new=20WAL=20summary=20to=20be=20= generated."=0A=20XACT_GROUP_UPDATE=09"Waiting=20for=20the=20group=20= leader=20to=20update=20transaction=20status=20at=20transaction=20end."=0A= +MEM_CXT_PUBLISH=09"Waiting=20for=20a=20process=20to=20publish=20memory=20= information."=0A=20=0A=20ABI_compatibility:=0A=20=0Adiff=20--git=20= a/src/backend/utils/adt/mcxtfuncs.c=20= b/src/backend/utils/adt/mcxtfuncs.c=0Aindex=20396c2f223b4..d459c89cfde=20= 100644=0A---=20a/src/backend/utils/adt/mcxtfuncs.c=0A+++=20= b/src/backend/utils/adt/mcxtfuncs.c=0A@@=20-17,28=20+17,25=20@@=0A=20=0A=20= #include=20"funcapi.h"=0A=20#include=20"mb/pg_wchar.h"=0A+#include=20= "miscadmin.h"=0A+#include=20"access/twophase.h"=0A+#include=20= "catalog/pg_authid_d.h"=0A=20#include=20"storage/proc.h"=0A=20#include=20= "storage/procarray.h"=0A+#include=20"utils/acl.h"=0A=20#include=20= "utils/array.h"=0A=20#include=20"utils/builtins.h"=0A=20#include=20= "utils/hsearch.h"=0A+#include=20"utils/memutils.h"=0A+#include=20= "utils/wait_event_types.h"=0A=20=0A=20/*=20----------=0A=20=20*=20The=20= max=20bytes=20for=20showing=20identifiers=20of=20MemoryContext.=0A=20=20= *=20----------=0A=20=20*/=0A=20#define=20= MEMORY_CONTEXT_IDENT_DISPLAY_SIZE=091024=0A-=0A-/*=0A-=20*=20= MemoryContextId=0A-=20*=09=09Used=20for=20storage=20of=20transient=20= identifiers=20for=0A-=20*=09=09pg_get_backend_memory_contexts.=0A-=20*/=0A= -typedef=20struct=20MemoryContextId=0A-{=0A-=09MemoryContext=20context;=0A= -=09int=09=09=09context_id;=0A-}=09=09=09MemoryContextId;=0A+struct=20= MemoryStatsBackendState=20*memCxtState=20=3D=20NULL;=0A+struct=20= MemoryStatsCtl=20*memCxtArea=20=3D=20NULL;=0A=20=0A=20/*=0A=20=20*=20= int_list_to_array=0A@@=20-89,7=20+86,7=20@@=20= PutMemoryContextsStatsTupleStore(Tuplestorestate=20*tupstore,=0A=20=09=20= */=0A=20=09for=20(MemoryContext=20cur=20=3D=20context;=20cur=20!=3D=20= NULL;=20cur=20=3D=20cur->parent)=0A=20=09{=0A-=09=09MemoryContextId=20= *entry;=0A+=09=09MemoryStatsContextId=20*entry;=0A=20=09=09bool=09=09= found;=0A=20=0A=20=09=09entry=20=3D=20hash_search(context_id_lookup,=20= &cur,=20HASH_FIND,=20&found);=0A@@=20-143,24=20+140,7=20@@=20= PutMemoryContextsStatsTupleStore(Tuplestorestate=20*tupstore,=0A=20=09= else=0A=20=09=09nulls[1]=20=3D=20true;=0A=20=0A-=09switch=20= (context->type)=0A-=09{=0A-=09=09case=20T_AllocSetContext:=0A-=09=09=09= type=20=3D=20"AllocSet";=0A-=09=09=09break;=0A-=09=09case=20= T_GenerationContext:=0A-=09=09=09type=20=3D=20"Generation";=0A-=09=09=09= break;=0A-=09=09case=20T_SlabContext:=0A-=09=09=09type=20=3D=20"Slab";=0A= -=09=09=09break;=0A-=09=09case=20T_BumpContext:=0A-=09=09=09type=20=3D=20= "Bump";=0A-=09=09=09break;=0A-=09=09default:=0A-=09=09=09type=20=3D=20= "???";=0A-=09=09=09break;=0A-=09}=0A+=09type=20=3D=20= ContextTypeToString(context->type);=0A=20=0A=20=09values[2]=20=3D=20= CStringGetTextDatum(type);=0A=20=09values[3]=20=3D=20= Int32GetDatum(list_length(path));=09/*=20level=20*/=0A@@=20-175,6=20= +155,38=20@@=20PutMemoryContextsStatsTupleStore(Tuplestorestate=20= *tupstore,=0A=20=09list_free(path);=0A=20}=0A=20=0A+/*=0A+=20*=20= ContextTypeToString=0A+=20*=09=09Returns=20a=20textual=20representation=20= of=20a=20context=20type=0A+=20*=0A+=20*=20This=20should=20cover=20the=20= same=20types=20as=20MemoryContextIsValid.=0A+=20*/=0A+const=20char=20*=0A= +ContextTypeToString(NodeTag=20type)=0A+{=0A+=09const=20char=20= *context_type;=0A+=0A+=09switch=20(type)=0A+=09{=0A+=09=09case=20= T_AllocSetContext:=0A+=09=09=09context_type=20=3D=20"AllocSet";=0A+=09=09= =09break;=0A+=09=09case=20T_GenerationContext:=0A+=09=09=09context_type=20= =3D=20"Generation";=0A+=09=09=09break;=0A+=09=09case=20T_SlabContext:=0A= +=09=09=09context_type=20=3D=20"Slab";=0A+=09=09=09break;=0A+=09=09case=20= T_BumpContext:=0A+=09=09=09context_type=20=3D=20"Bump";=0A+=09=09=09= break;=0A+=09=09default:=0A+=09=09=09context_type=20=3D=20"???";=0A+=09=09= =09break;=0A+=09}=0A+=09return=20context_type;=0A+}=0A+=0A=20/*=0A=20=20= *=20pg_get_backend_memory_contexts=0A=20=20*=09=09SQL=20SRF=20showing=20= backend=20memory=20context.=0A@@=20-189,7=20+201,7=20@@=20= pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09HTAB=09=20=20=20= *context_id_lookup;=0A=20=0A=20=09ctl.keysize=20=3D=20= sizeof(MemoryContext);=0A-=09ctl.entrysize=20=3D=20= sizeof(MemoryContextId);=0A+=09ctl.entrysize=20=3D=20= sizeof(MemoryStatsContextId);=0A=20=09ctl.hcxt=20=3D=20= CurrentMemoryContext;=0A=20=0A=20=09context_id_lookup=20=3D=20= hash_create("pg_get_backend_memory_contexts",=0A@@=20-216,7=20+228,7=20= @@=20pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)=0A=20=0A=20=09= foreach_ptr(MemoryContextData,=20cur,=20contexts)=0A=20=09{=0A-=09=09= MemoryContextId=20*entry;=0A+=09=09MemoryStatsContextId=20*entry;=0A=20=09= =09bool=09=09found;=0A=20=0A=20=09=09/*=0A@@=20-224,8=20+236,8=20@@=20= pg_get_backend_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09=09=20*=20= PutMemoryContextsStatsTupleStore=20needs=20this=20to=20populate=20the=20= "path"=0A=20=09=09=20*=20column=20with=20the=20parent=20context_ids.=0A=20= =09=09=20*/=0A-=09=09entry=20=3D=20(MemoryContextId=20*)=20= hash_search(context_id_lookup,=20&cur,=0A-=09=09=09=09=09=09=09=09=09=09=09= =09HASH_ENTER,=20&found);=0A+=09=09entry=20=3D=20(MemoryStatsContextId=20= *)=20hash_search(context_id_lookup,=20&cur,=0A+=09=09=09=09=09=09=09=09=09= =09=09=09=09=09=20HASH_ENTER,=20&found);=0A=20=09=09entry->context_id=20= =3D=20context_id++;=0A=20=09=09Assert(!found);=0A=20=0A@@=20-305,3=20= +317,349=20@@=20pg_log_backend_memory_contexts(PG_FUNCTION_ARGS)=0A=20=0A= =20=09PG_RETURN_BOOL(true);=0A=20}=0A+=0A+/*=0A+=20*=20= pg_get_process_memory_contexts=0A+=20*=09=09Signal=20a=20backend=20or=20= an=20auxiliary=20process=20to=20send=20its=20memory=20contexts,=0A+=20*=09= =09wait=20for=20the=20results=20and=20display=20them.=0A+=20*=0A+=20*=20= By=20default,=20only=20superusers=20or=20users=20with=20= PG_READ_ALL_STATS=20are=20allowed=20to=0A+=20*=20signal=20a=20process=20= to=20return=20the=20memory=20contexts.=20This=20is=20because=20allowing=0A= +=20*=20any=20users=20to=20issue=20this=20request=20at=20an=20unbounded=20= rate=20would=20cause=20lots=20of=0A+=20*=20requests=20to=20be=20sent,=20= which=20can=20lead=20to=20denial=20of=20service.=20Additional=20roles=0A= +=20*=20can=20be=20permitted=20with=20GRANT.=0A+=20*=0A+=20*=20On=20= receipt=20of=20this=20signal,=20a=20backend=20or=20an=20auxiliary=20= process=20sets=20the=20flag=0A+=20*=20in=20the=20signal=20handler,=20= which=20causes=20the=20next=20CHECK_FOR_INTERRUPTS()=0A+=20*=20or=20= process-specific=20interrupt=20handler=20to=20copy=20the=20memory=20= context=20details=0A+=20*=20to=20a=20dynamic=20shared=20memory=20space.=0A= +=20*=0A+=20*=20We=20have=20defined=20a=20limit=20on=20DSA=20memory=20= that=20could=20be=20allocated=20per=20process=20-=0A+=20*=20if=20the=20= process=20has=20more=20memory=20contexts=20than=20what=20can=20fit=20in=20= the=20allocated=0A+=20*=20size,=20the=20excess=20contexts=20are=20= summarized=20and=20represented=20as=20cumulative=20total=0A+=20*=20at=20= the=20end=20of=20the=20buffer.=0A+=20*=0A+=20*=20After=20sending=20the=20= signal,=20wait=20on=20a=20condition=20variable.=20The=20publishing=0A+=20= *=20backend,=20after=20copying=20the=20data=20to=20shared=20memory,=20= sends=20signal=20on=20that=0A+=20*=20condition=20variable.=20There=20is=20= one=20condition=20variable=20per=20publishing=20backend.=0A+=20*=20Once=20= the=20condition=20variable=20is=20signalled,=20check=20if=20the=20latest=20= memory=20context=0A+=20*=20information=20is=20available=20and=20display.=0A= +=20*=0A+=20*=20If=20the=20publishing=20backend=20does=20not=20respond=20= before=20the=20condition=20variable=0A+=20*=20times=20out,=20which=20is=20= set=20to=20MEMSTATS_WAIT_TIMEOUT,=20retry=20given=20that=20there=20is=0A= +=20*=20time=20left=20within=20the=20timeout=20specified=20by=20the=20= user,=20before=20giving=20up=20and=0A+=20*=20returning=20previously=20= published=20statistics,=20if=20any.=20If=20no=20previous=20statistics=0A= +=20*=20exist,=20return=20NULL.=0A+=20*/=0A+#define=20= MEMSTATS_WAIT_TIMEOUT=20100=0A+Datum=0A= +pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A+{=0A+=09int=09=09=09= pid=20=3D=20PG_GETARG_INT32(0);=0A+=09bool=09=09summary=20=3D=20= PG_GETARG_BOOL(1);=0A+=09double=09=09timeout=20=3D=20= PG_GETARG_FLOAT8(2);=0A+=09PGPROC=09=20=20=20*proc;=0A+=09ProcNumber=09= procNumber=20=3D=20INVALID_PROC_NUMBER;=0A+=09bool=09=09proc_is_aux=20=3D=20= false;=0A+=09ReturnSetInfo=20*rsinfo=20=3D=20(ReturnSetInfo=20*)=20= fcinfo->resultinfo;=0A+=09MemoryStatsEntry=20*memcxt_info;=0A+=09= TimestampTz=20start_timestamp;=0A+=0A+=09/*=0A+=09=20*=20See=20if=20the=20= process=20with=20given=20pid=20is=20a=20backend=20or=20an=20auxiliary=20= process=0A+=09=20*=20and=20remember=20the=20type=20for=20when=20we=20= requery=20the=20process=20later.=0A+=09=20*/=0A+=09proc=20=3D=20= BackendPidGetProc(pid);=0A+=09if=20(proc=20=3D=3D=20NULL)=0A+=09{=0A+=09=09= proc=20=3D=20AuxiliaryPidGetProc(pid);=0A+=09=09proc_is_aux=20=3D=20= true;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20BackendPidGetProc()=20and=20= AuxiliaryPidGetProc()=20return=20NULL=20if=20the=20pid=0A+=09=20*=20= isn't=20valid;=20this=20is=20however=20not=20a=20problem=20and=20leave=20= with=20a=20WARNING.=0A+=09=20*=20See=20comment=20in=20= pg_log_backend_memory_contexts=20for=20a=20discussion=20on=20this.=0A+=09= =20*/=0A+=09if=20(proc=20=3D=3D=20NULL)=0A+=09{=0A+=09=09/*=0A+=09=09=20= *=20This=20is=20just=20a=20warning=20so=20a=20loop-through-resultset=20= will=20not=20abort=0A+=09=09=20*=20if=20one=20backend=20terminated=20on=20= its=20own=20during=20the=20run.=0A+=09=09=20*/=0A+=09=09ereport(WARNING,=0A= +=09=09=09=09(errmsg("PID=20%d=20is=20not=20a=20PostgreSQL=20server=20= process",=20pid)));=0A+=09=09PG_RETURN_NULL();=0A+=09}=0A+=0A+=09= InitMaterializedSRF(fcinfo,=200);=0A+=0A+=09procNumber=20=3D=20= GetNumberFromPGProc(proc);=0A+=0A+=09= LWLockAcquire(&memCxtState[procNumber].lw_lock,=20LW_EXCLUSIVE);=0A+=09= memCxtState[procNumber].summary=20=3D=20summary;=0A+=09= LWLockRelease(&memCxtState[procNumber].lw_lock);=0A+=0A+=09= start_timestamp=20=3D=20GetCurrentTimestamp();=0A+=0A+=09/*=0A+=09=20*=20= Send=20a=20signal=20to=20a=20PostgreSQL=20process,=20informing=20it=20we=20= want=20it=20to=0A+=09=20*=20produce=20information=20about=20its=20memory=20= contexts.=0A+=09=20*/=0A+=09if=20(SendProcSignal(pid,=20= PROCSIG_GET_MEMORY_CONTEXT,=20procNumber)=20<=200)=0A+=09{=0A+=09=09= ereport(WARNING,=0A+=09=09=09=09errmsg("could=20not=20send=20signal=20to=20= process=20%d:=20%m",=20pid));=0A+=09=09PG_RETURN_NULL();=0A+=09}=0A+=0A+=09= /*=0A+=09=20*=20Even=20if=20the=20proc=20has=20published=20statistics,=20= the=20may=20not=20be=20due=20to=20the=0A+=09=20*=20current=20request,=20= but=20previously=20published=20stats.=20=20Check=20if=20the=20stats=0A+=09= =20*=20are=20updated=20by=20comparing=20the=20timestamp,=20if=20the=20= stats=20are=20newer=20than=20our=0A+=09=20*=20previously=20recorded=20= timestamp=20from=20before=20sending=20the=20procsignal,=20they=0A+=09=20= *=20must=20by=20definition=20be=20updated.=20Wait=20for=20the=20timeout=20= specified=20by=20the=0A+=09=20*=20user,=20following=20which=20display=20= old=20statistics=20if=20available=20or=20return=0A+=09=20*=20NULL.=0A+=09= =20*/=0A+=09while=20(1)=0A+=09{=0A+=09=09long=09=09msecs;=0A+=0A+=09=09= /*=0A+=09=09=20*=20We=20expect=20to=20come=20out=20of=20sleep=20when=20= the=20requested=20process=20has=0A+=09=09=20*=20finished=20publishing=20= the=20statistics,=20verified=20using=20the=20valid=20DSA=0A+=09=09=20*=20= pointer.=0A+=09=09=20*=0A+=09=09=20*=20Make=20sure=20that=20the=20= information=20belongs=20to=20pid=20we=20requested=0A+=09=09=20*=20= information=20for,=20Otherwise=20loop=20back=20and=20wait=20for=20the=20= server=0A+=09=09=20*=20process=20to=20finish=20publishing=20statistics.=0A= +=09=09=20*/=0A+=09=09LWLockAcquire(&memCxtState[procNumber].lw_lock,=20= LW_EXCLUSIVE);=0A+=0A+=09=09/*=0A+=09=09=20*=20Note=20in=20procnumber.h=20= file=20says=20that=20a=20procNumber=20can=20be=20re-used=20for=0A+=09=09=20= *=20a=20different=20backend=20immediately=20after=20a=20backend=20exits.=20= In=20case=20an=0A+=09=09=20*=20old=20process'=20data=20was=20there=20and=20= not=20updated=20by=20the=20current=20process=0A+=09=09=20*=20in=20the=20= slot=20identified=20by=20the=20procNumber,=20the=20pid=20of=20the=20= requested=0A+=09=09=20*=20process=20and=20the=20proc_id=20might=20not=20= match.=0A+=09=09=20*/=0A+=09=09if=20(memCxtState[procNumber].proc_id=20= =3D=3D=20pid)=0A+=09=09{=0A+=09=09=09/*=0A+=09=09=09=20*=20Break=20if=20= the=20latest=20stats=20have=20been=20read,=20indicated=20by=0A+=09=09=09=20= *=20statistics=20timestamp=20being=20newer=20than=20the=20current=20= request=0A+=09=09=09=20*=20timestamp.=0A+=09=09=09=20*/=0A+=09=09=09= msecs=20=3D=20TimestampDifferenceMilliseconds(start_timestamp,=0A+=09=09=09= =09=09=09=09=09=09=09=09=09=09memCxtState[procNumber].stats_timestamp);=0A= +=0A+=09=09=09if=20= (DsaPointerIsValid(memCxtState[procNumber].memstats_dsa_pointer)=0A+=09=09= =09=09&&=20msecs=20>=200)=0A+=09=09=09=09break;=0A+=09=09}=0A+=09=09= LWLockRelease(&memCxtState[procNumber].lw_lock);=0A+=0A+=09=09/*=0A+=09=09= =20*=20Recheck=20the=20state=20of=20the=20backend=20before=20sleeping=20= on=20the=20condition=0A+=09=09=20*=20variable=20to=20ensure=20the=20= process=20is=20still=20alive.=20=20Only=20check=20the=0A+=09=09=20*=20= relevant=20process=20type=20based=20on=20the=20earlier=20PID=20check.=0A= +=09=09=20*/=0A+=09=09if=20(proc_is_aux)=0A+=09=09=09proc=20=3D=20= AuxiliaryPidGetProc(pid);=0A+=09=09else=0A+=09=09=09proc=20=3D=20= BackendPidGetProc(pid);=0A+=0A+=09=09/*=0A+=09=09=20*=20The=20process=20= ending=20during=20memory=20context=20processing=20is=20not=20an=0A+=09=09= =20*=20error.=0A+=09=09=20*/=0A+=09=09if=20(proc=20=3D=3D=20NULL)=0A+=09=09= {=0A+=09=09=09ereport(WARNING,=0A+=09=09=09=09=09errmsg("PID=20%d=20is=20= no=20longer=20a=20PostgreSQL=20server=20process",=0A+=09=09=09=09=09=09=20= =20=20pid));=0A+=09=09=09PG_RETURN_NULL();=0A+=09=09}=0A+=0A+=09=09msecs=20= =3D=20TimestampDifferenceMilliseconds(start_timestamp,=20= GetCurrentTimestamp());=0A+=0A+=09=09/*=0A+=09=09=20*=20If=20we=20= haven't=20already=20exceeded=20the=20timeout=20value,=20sleep=20for=20= the=0A+=09=09=20*=20remainder=20of=20the=20timeout=20on=20the=20= condition=20variable.=0A+=09=09=20*/=0A+=09=09if=20(msecs=20>=200=20&&=20= msecs=20<=20(timeout=20*=201000))=0A+=09=09{=0A+=09=09=09/*=0A+=09=09=09=20= *=20Wait=20for=20the=20timeout=20as=20defined=20by=20the=20user.=20If=20= no=20updated=0A+=09=09=09=20*=20statistics=20are=20available=20within=20= the=20allowed=20time=20then=20display=0A+=09=09=09=20*=20previously=20= published=20statistics=20if=20there=20are=20any.=20If=20no=0A+=09=09=09=20= *=20previous=20statistics=20are=20available=20then=20return=20NULL.=20=20= The=20timer=0A+=09=09=09=20*=20is=20defined=20in=20milliseconds=20since=20= thats=20what=20the=20condition=0A+=09=09=09=20*=20variable=20sleep=20= uses.=0A+=09=09=09=20*/=0A+=09=09=09if=20= (ConditionVariableTimedSleep(&memCxtState[procNumber].memcxt_cv,=0A+=09=09= =09=09=09=09=09=09=09=09=09((timeout=20*=201000)=20-=20msecs),=20= WAIT_EVENT_MEM_CXT_PUBLISH))=0A+=09=09=09{=0A+=09=09=09=09= LWLockAcquire(&memCxtState[procNumber].lw_lock,=20LW_EXCLUSIVE);=0A+=09=09= =09=09/*=20Displaying=20previously=20published=20statistics=20if=20= available=20*/=0A+=09=09=09=09if=20= (DsaPointerIsValid(memCxtState[procNumber].memstats_dsa_pointer))=0A+=09=09= =09=09=09break;=0A+=09=09=09=09else=0A+=09=09=09=09{=0A+=09=09=09=09=09= LWLockRelease(&memCxtState[procNumber].lw_lock);=0A+=09=09=09=09=09= PG_RETURN_NULL();=0A+=09=09=09=09}=0A+=09=09=09}=0A+=09=09}=0A+=09=09= else=0A+=09=09{=0A+=09=09=09= LWLockAcquire(&memCxtState[procNumber].lw_lock,=20LW_EXCLUSIVE);=0A+=09=09= =09/*=20Displaying=20previously=20published=20statistics=20if=20= available=20*/=0A+=09=09=09if=20= (DsaPointerIsValid(memCxtState[procNumber].memstats_dsa_pointer))=0A+=09=09= =09=09break;=0A+=09=09=09else=0A+=09=09=09{=0A+=09=09=09=09= LWLockRelease(&memCxtState[procNumber].lw_lock);=0A+=09=09=09=09= PG_RETURN_NULL();=0A+=09=09=09}=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20= *=20We=20should=20only=20reach=20here=20with=20a=20valid=20DSA=20handle,=20= either=20containing=0A+=09=20*=20updated=20statistics=20or=20previously=20= published=20statistics=20(identified=20by=0A+=09=20*=20the=20timestamp.=0A= +=09=20*/=0A+=09Assert(memCxtArea->memstats_dsa_handle=20!=3D=20= DSA_HANDLE_INVALID);=0A+=09/*=20Attach=20to=20the=20dsa=20area=20if=20we=20= have=20not=20already=20done=20so=20*/=0A+=09if=20(area=20=3D=3D=20NULL)=0A= +=09{=0A+=09=09MemoryContext=20oldcontext=20=3D=20CurrentMemoryContext;=0A= +=0A+=09=09MemoryContextSwitchTo(TopMemoryContext);=0A+=09=09area=20=3D=20= dsa_attach(memCxtArea->memstats_dsa_handle);=0A+=09=09= MemoryContextSwitchTo(oldcontext);=0A+=09=09dsa_pin_mapping(area);=0A+=09= }=0A+=0A+=09/*=0A+=09=20*=20Backend=20has=20finished=20publishing=20the=20= stats,=20project=20them.=0A+=09=20*/=0A+=09memcxt_info=20=3D=20= (MemoryStatsEntry=20*)=0A+=09=09dsa_get_address(area,=20= memCxtState[procNumber].memstats_dsa_pointer);=0A+=0A+#define=20= PG_GET_PROCESS_MEMORY_CONTEXTS_COLS=0912=0A+=09for=20(int=20i=20=3D=200;=20= i=20<=20memCxtState[procNumber].total_stats;=20i++)=0A+=09{=0A+=09=09= ArrayType=20=20*path_array;=0A+=09=09int=09=09=09path_length;=0A+=09=09= Datum=09=09values[PG_GET_PROCESS_MEMORY_CONTEXTS_COLS];=0A+=09=09bool=09=09= nulls[PG_GET_PROCESS_MEMORY_CONTEXTS_COLS];=0A+=09=09char=09=20=20=20= *name;=0A+=09=09char=09=20=20=20*ident;=0A+=09=09Datum=09=20=20=20= *path_datum=20=3D=20NULL;=0A+=09=09int=09=09=20=20=20*path_int=20=3D=20= NULL;=0A+=0A+=09=09memset(values,=200,=20sizeof(values));=0A+=09=09= memset(nulls,=200,=20sizeof(nulls));=0A+=0A+=09=09if=20= (DsaPointerIsValid(memcxt_info[i].name))=0A+=09=09{=0A+=09=09=09name=20=3D= =20(char=20*)=20dsa_get_address(area,=20memcxt_info[i].name);=0A+=09=09=09= values[0]=20=3D=20CStringGetTextDatum(name);=0A+=09=09}=0A+=09=09else=0A= +=09=09=09nulls[0]=20=3D=20true;=0A+=0A+=09=09if=20= (DsaPointerIsValid(memcxt_info[i].ident))=0A+=09=09{=0A+=09=09=09ident=20= =3D=20(char=20*)=20dsa_get_address(area,=20memcxt_info[i].ident);=0A+=09=09= =09values[1]=20=3D=20CStringGetTextDatum(ident);=0A+=09=09}=0A+=09=09= else=0A+=09=09=09nulls[1]=20=3D=20true;=0A+=0A+=09=09values[2]=20=3D=20= CStringGetTextDatum(ContextTypeToString(memcxt_info[i].type));=0A+=0A+=09= =09path_length=20=3D=20memcxt_info[i].path_length;=0A+=09=09path_datum=20= =3D=20(Datum=20*)=20palloc(path_length=20*=20sizeof(Datum));=0A+=09=09if=20= (DsaPointerIsValid(memcxt_info[i].path))=0A+=09=09{=0A+=09=09=09path_int=20= =3D=20(int=20*)=20dsa_get_address(area,=20memcxt_info[i].path);=0A+=09=09= =09for=20(int=20j=20=3D=200;=20j=20<=20path_length;=20j++)=0A+=09=09=09=09= path_datum[j]=20=3D=20Int32GetDatum(path_int[j]);=0A+=09=09=09path_array=20= =3D=20construct_array_builtin(path_datum,=20path_length,=20INT4OID);=0A+=09= =09=09values[3]=20=3D=20PointerGetDatum(path_array);=0A+=09=09}=0A+=09=09= else=0A+=09=09=09nulls[3]=20=3D=20true;=0A+=0A+=09=09values[4]=20=3D=20= Int32GetDatum(memcxt_info[i].levels);=0A+=09=09values[5]=20=3D=20= Int64GetDatum(memcxt_info[i].totalspace);=0A+=09=09values[6]=20=3D=20= Int64GetDatum(memcxt_info[i].nblocks);=0A+=09=09values[7]=20=3D=20= Int64GetDatum(memcxt_info[i].freespace);=0A+=09=09values[8]=20=3D=20= Int64GetDatum(memcxt_info[i].freechunks);=0A+=09=09values[9]=20=3D=20= Int64GetDatum(memcxt_info[i].totalspace=20-=0A+=09=09=09=09=09=09=09=09=20= =20memcxt_info[i].freespace);=0A+=09=09values[10]=20=3D=20= Int32GetDatum(memcxt_info[i].num_agg_stats);=0A+=09=09values[11]=20=3D=20= TimestampTzGetDatum(memCxtState[procNumber].stats_timestamp);=0A+=0A+=09=09= tuplestore_putvalues(rsinfo->setResult,=20rsinfo->setDesc,=0A+=09=09=09=09= =09=09=09=20values,=20nulls);=0A+=09}=0A+=09= LWLockRelease(&memCxtState[procNumber].lw_lock);=0A+=0A+=09= ConditionVariableCancelSleep();=0A+=0A+=09PG_RETURN_NULL();=0A+}=0A+=0A= +Size=0A+MemoryContextReportingShmemSize(void)=0A+{=0A+=09Size=09=09sz=20= =3D=200;=0A+=09Size=09=09TotalProcs=20=3D=200;=0A+=0A+=09TotalProcs=20=3D=20= add_size(TotalProcs,=20NUM_AUXILIARY_PROCS);=0A+=09TotalProcs=20=3D=20= add_size(TotalProcs,=20MaxBackends);=0A+=09sz=20=3D=20add_size(sz,=20= mul_size(TotalProcs,=20sizeof(MemoryStatsBackendState)));=0A+=0A+=09sz=20= =3D=20add_size(sz,=20sizeof(MemoryStatsCtl));=0A+=0A+=09return=20sz;=0A= +}=0A+=0A+/*=0A+=20*=20Initialize=20shared=20memory=20for=20displaying=20= memory=20context=20statistics=0A+=20*/=0A+void=0A= +MemoryContextReportingShmemInit(void)=0A+{=0A+=09bool=09=09found;=0A+=0A= +=09memCxtArea=20=3D=20(MemoryStatsCtl=20*)=0A+=09=09= ShmemInitStruct("MemoryStatsCtl",=0A+=09=09=09=09=09=09= sizeof(MemoryStatsCtl),=20&found);=0A+=0A+=09if=20(!found)=0A+=09{=0A+=09= =09LWLockInitialize(&memCxtArea->lw_lock,=20= LWTRANCHE_MEMORY_CONTEXT_REPORTING_STATE);=0A+=09=09= memCxtArea->memstats_dsa_handle=20=3D=20DSA_HANDLE_INVALID;=0A+=09}=0A+=0A= +=09memCxtState=20=3D=20(MemoryStatsBackendState=20*)=0A+=09=09= ShmemInitStruct("MemoryStatsBackendState",=0A+=09=09=09=09=09=09= ((MaxBackends=20+=20NUM_AUXILIARY_PROCS)=20*=20= sizeof(MemoryStatsBackendState)),=0A+=09=09=09=09=09=09&found);=0A+=0A+=09= if=20(found)=0A+=09=09return;=0A+=0A+=09for=20(int=20i=20=3D=200;=20i=20= <=20(MaxBackends=20+=20NUM_AUXILIARY_PROCS);=20i++)=0A+=09{=0A+=09=09= ConditionVariableInit(&memCxtState[i].memcxt_cv);=0A+=09=09= LWLockInitialize(&memCxtState[i].lw_lock,=20= LWTRANCHE_MEMORY_CONTEXT_REPORTING_PROC);=0A+=09=09= memCxtState[i].memstats_dsa_pointer=20=3D=20InvalidDsaPointer;=0A+=09}=0A= +}=0Adiff=20--git=20a/src/backend/utils/init/globals.c=20= b/src/backend/utils/init/globals.c=0Aindex=202152aad97d9..92304a1f124=20= 100644=0A---=20a/src/backend/utils/init/globals.c=0A+++=20= b/src/backend/utils/init/globals.c=0A@@=20-39,6=20+39,7=20@@=20volatile=20= sig_atomic_t=20TransactionTimeoutPending=20=3D=20false;=0A=20volatile=20= sig_atomic_t=20IdleSessionTimeoutPending=20=3D=20false;=0A=20volatile=20= sig_atomic_t=20ProcSignalBarrierPending=20=3D=20false;=0A=20volatile=20= sig_atomic_t=20LogMemoryContextPending=20=3D=20false;=0A+volatile=20= sig_atomic_t=20PublishMemoryContextPending=20=3D=20false;=0A=20volatile=20= sig_atomic_t=20IdleStatsUpdateTimeoutPending=20=3D=20false;=0A=20= volatile=20uint32=20InterruptHoldoffCount=20=3D=200;=0A=20volatile=20= uint32=20QueryCancelHoldoffCount=20=3D=200;=0Adiff=20--git=20= a/src/backend/utils/init/postinit.c=20= b/src/backend/utils/init/postinit.c=0Aindex=20c09c4d404ba..01309ef3f86=20= 100644=0A---=20a/src/backend/utils/init/postinit.c=0A+++=20= b/src/backend/utils/init/postinit.c=0A@@=20-667,6=20+667,13=20@@=20= BaseInit(void)=0A=20=09=20*=20drop=20ephemeral=20slots,=20which=20in=20= turn=20triggers=20stats=20reporting.=0A=20=09=20*/=0A=20=09= ReplicationSlotInitialize();=0A+=0A+=09/*=0A+=09=20*=20The=20before=20= shmem=20exit=20callback=20frees=20the=20DSA=20memory=20occupied=20by=20= the=0A+=09=20*=20latest=20memory=20context=20statistics=20that=20could=20= be=20published=20by=20this=20proc=0A+=09=20*=20if=20requested.=0A+=09=20= */=0A+=09before_shmem_exit(AtProcExit_memstats_cleanup,=200);=0A=20}=0A=20= =0A=20=0Adiff=20--git=20a/src/backend/utils/mmgr/mcxt.c=20= b/src/backend/utils/mmgr/mcxt.c=0Aindex=20d98ae9db6be..f3a588e1375=20= 100644=0A---=20a/src/backend/utils/mmgr/mcxt.c=0A+++=20= b/src/backend/utils/mmgr/mcxt.c=0A@@=20-23,6=20+23,11=20@@=0A=20=0A=20= #include=20"mb/pg_wchar.h"=0A=20#include=20"miscadmin.h"=0A+#include=20= "nodes/pg_list.h"=0A+#include=20"storage/lwlock.h"=0A+#include=20= "storage/ipc.h"=0A+#include=20"utils/dsa.h"=0A+#include=20= "utils/hsearch.h"=0A=20#include=20"utils/memdebug.h"=0A=20#include=20= "utils/memutils.h"=0A=20#include=20"utils/memutils_internal.h"=0A@@=20= -135,6=20+140,17=20@@=20static=20const=20MemoryContextMethods=20= mcxt_methods[]=20=3D=20{=0A=20};=0A=20=0A=20#undef=20BOGUS_MCTX=0A+/*=0A= +=20*=20This=20is=20passed=20to=20MemoryContextStatsInternal=20to=20= determine=20whether=0A+=20*=20to=20print=20context=20statistics=20or=20= not=20and=20where=20to=20print=20them=20logs=20or=0A+=20*=20stderr.=0A+=20= */=0A+typedef=20enum=20PrintDestination=0A+{=0A+=09PRINT_STATS_TO_STDERR=20= =3D=200,=0A+=09PRINT_STATS_TO_LOGS,=0A+=09PRINT_STATS_NONE=0A+}=09=09=09= PrintDestination;=0A=20=0A=20/*=0A=20=20*=20CurrentMemoryContext=0A@@=20= -156,16=20+172,31=20@@=20MemoryContext=20CurTransactionContext=20=3D=20= NULL;=0A=20=0A=20/*=20This=20is=20a=20transient=20link=20to=20the=20= active=20portal's=20memory=20context:=20*/=0A=20MemoryContext=20= PortalContext=20=3D=20NULL;=0A+dsa_area=20=20=20*area=20=3D=20NULL;=0A=20= =0A=20static=20void=20MemoryContextDeleteOnly(MemoryContext=20context);=0A= =20static=20void=20MemoryContextCallResetCallbacks(MemoryContext=20= context);=0A=20static=20void=20MemoryContextStatsInternal(MemoryContext=20= context,=20int=20level,=0A=20=09=09=09=09=09=09=09=09=09=20=20=20int=20= max_level,=20int=20max_children,=0A=20=09=09=09=09=09=09=09=09=09=20=20=20= MemoryContextCounters=20*totals,=0A-=09=09=09=09=09=09=09=09=09=20=20=20= bool=20print_to_stderr);=0A+=09=09=09=09=09=09=09=09=09=20=20=20= PrintDestination=20print_location,=0A+=09=09=09=09=09=09=09=09=09=20=20=20= int=20*num_contexts);=0A=20static=20void=20= MemoryContextStatsPrint(MemoryContext=20context,=20void=20*passthru,=0A=20= =09=09=09=09=09=09=09=09=09const=20char=20*stats_string,=0A=20=09=09=09=09= =09=09=09=09=09bool=20print_to_stderr);=0A+static=20void=20= PublishMemoryContext(MemoryStatsEntry=20*memcxt_infos,=0A+=09=09=09=09=09= =09=09=09=20int=20curr_id,=20MemoryContext=20context,=0A+=09=09=09=09=09=09= =09=09=20List=20*path,=0A+=09=09=09=09=09=09=09=09=20= MemoryContextCounters=20stat,=0A+=09=09=09=09=09=09=09=09=20int=20= num_contexts,=20dsa_area=20*area,=0A+=09=09=09=09=09=09=09=09=20int=20= max_levels);=0A+static=20void=20compute_contexts_count_and_ids(List=20= *contexts,=20HTAB=20*context_id_lookup,=0A+=09=09=09=09=09=09=09=09=09=09= =20=20=20int=20*stats_count,=0A+=09=09=09=09=09=09=09=09=09=09=20=20=20= bool=20summary);=0A+static=20List=20*compute_context_path(MemoryContext=20= c,=20HTAB=20*context_id_lookup);=0A+static=20void=20= free_memorycontextstate_dsa(dsa_area=20*area,=20int=20total_stats,=0A+=09= =09=09=09=09=09=09=09=09=09dsa_pointer=20prev_dsa_pointer);=0A+static=20= void=20end_memorycontext_reporting(void);=0A=20=0A=20/*=0A=20=20*=20You=20= should=20not=20do=20memory=20allocations=20within=20a=20critical=20= section,=20because=0A@@=20-831,11=20+862,19=20@@=20= MemoryContextStatsDetail(MemoryContext=20context,=0A=20=09=09=09=09=09=09= =20bool=20print_to_stderr)=0A=20{=0A=20=09MemoryContextCounters=20= grand_totals;=0A+=09int=09=09=09num_contexts;=0A+=09PrintDestination=20= print_location;=0A=20=0A=20=09memset(&grand_totals,=200,=20= sizeof(grand_totals));=0A=20=0A+=09if=20(print_to_stderr)=0A+=09=09= print_location=20=3D=20PRINT_STATS_TO_STDERR;=0A+=09else=0A+=09=09= print_location=20=3D=20PRINT_STATS_TO_LOGS;=0A+=0A+=09/*=20num_contexts=20= report=20number=20of=20contexts=20aggregated=20in=20the=20output=20*/=0A=20= =09MemoryContextStatsInternal(context,=200,=20max_level,=20max_children,=0A= -=09=09=09=09=09=09=09=20=20=20&grand_totals,=20print_to_stderr);=0A+=09=09= =09=09=09=09=09=20=20=20&grand_totals,=20print_location,=20= &num_contexts);=0A=20=0A=20=09if=20(print_to_stderr)=0A=20=09=09= fprintf(stderr,=0A@@=20-870,13=20+909,14=20@@=20= MemoryContextStatsDetail(MemoryContext=20context,=0A=20=20*=09=09One=20= recursion=20level=20for=20MemoryContextStats=0A=20=20*=0A=20=20*=20Print=20= stats=20for=20this=20context=20if=20possible,=20but=20in=20any=20case=20= accumulate=20counts=0A-=20*=20into=20*totals=20(if=20not=20NULL).=0A+=20= *=20into=20*totals=20(if=20not=20NULL).=20The=20callers=20should=20make=20= sure=20that=20print_location=0A+=20*=20is=20set=20to=20= PRINT_STATS_STDERR=20or=20PRINT_STATS_TO_LOGS=20or=20PRINT_STATS_NONE.=0A= =20=20*/=0A=20static=20void=0A=20= MemoryContextStatsInternal(MemoryContext=20context,=20int=20level,=0A=20=09= =09=09=09=09=09=20=20=20int=20max_level,=20int=20max_children,=0A=20=09=09= =09=09=09=09=20=20=20MemoryContextCounters=20*totals,=0A-=09=09=09=09=09=09= =20=20=20bool=20print_to_stderr)=0A+=09=09=09=09=09=09=20=20=20= PrintDestination=20print_location,=20int=20*num_contexts)=0A=20{=0A=20=09= MemoryContext=20child;=0A=20=09int=09=09=09ichild;=0A@@=20-884,10=20= +924,39=20@@=20MemoryContextStatsInternal(MemoryContext=20context,=20int=20= level,=0A=20=09Assert(MemoryContextIsValid(context));=0A=20=0A=20=09/*=20= Examine=20the=20context=20itself=20*/=0A-=09= context->methods->stats(context,=0A-=09=09=09=09=09=09=09= MemoryContextStatsPrint,=0A-=09=09=09=09=09=09=09&level,=0A-=09=09=09=09=09= =09=09totals,=20print_to_stderr);=0A+=09switch=20(print_location)=0A+=09= {=0A+=09=09case=20PRINT_STATS_TO_STDERR:=0A+=09=09=09= context->methods->stats(context,=0A+=09=09=09=09=09=09=09=09=09= MemoryContextStatsPrint,=0A+=09=09=09=09=09=09=09=09=09&level,=0A+=09=09=09= =09=09=09=09=09=09totals,=20true);=0A+=09=09=09break;=0A+=0A+=09=09case=20= PRINT_STATS_TO_LOGS:=0A+=09=09=09context->methods->stats(context,=0A+=09=09= =09=09=09=09=09=09=09MemoryContextStatsPrint,=0A+=09=09=09=09=09=09=09=09= =09&level,=0A+=09=09=09=09=09=09=09=09=09totals,=20false);=0A+=09=09=09= break;=0A+=0A+=09=09case=20PRINT_STATS_NONE:=0A+=0A+=09=09=09/*=0A+=09=09= =09=20*=20Do=20not=20print=20the=20statistics=20if=20print_location=20is=0A= +=09=09=09=20*=20PRINT_STATS_NONE,=20only=20compute=20totals.=20This=20= is=20used=20in=0A+=09=09=09=20*=20reporting=20of=20memory=20context=20= statistics=20via=20a=20sql=20function.=20Last=0A+=09=09=09=20*=20= parameter=20is=20not=20relevant.=0A+=09=09=09=20*/=0A+=09=09=09= context->methods->stats(context,=0A+=09=09=09=09=09=09=09=09=09NULL,=0A+=09= =09=09=09=09=09=09=09=09NULL,=0A+=09=09=09=09=09=09=09=09=09totals,=20= false);=0A+=09=09=09break;=0A+=09}=0A+=0A+=09/*=20Increment=20the=20= context=20count=20for=20each=20of=20the=20recursive=20call=20*/=0A+=09= *num_contexts=20=3D=20*num_contexts=20+=201;=0A=20=0A=20=09/*=0A=20=09=20= *=20Examine=20children.=0A@@=20-907,7=20+976,7=20@@=20= MemoryContextStatsInternal(MemoryContext=20context,=20int=20level,=0A=20=09= =09=09MemoryContextStatsInternal(child,=20level=20+=201,=0A=20=09=09=09=09= =09=09=09=09=09=20=20=20max_level,=20max_children,=0A=20=09=09=09=09=09=09= =09=09=09=20=20=20totals,=0A-=09=09=09=09=09=09=09=09=09=20=20=20= print_to_stderr);=0A+=09=09=09=09=09=09=09=09=09=20=20=20print_location,=20= num_contexts);=0A=20=09=09}=0A=20=09}=0A=20=0A@@=20-926,7=20+995,13=20@@=20= MemoryContextStatsInternal(MemoryContext=20context,=20int=20level,=0A=20=09= =09=09child=20=3D=20MemoryContextTraverseNext(child,=20context);=0A=20=09= =09}=0A=20=0A-=09=09if=20(print_to_stderr)=0A+=09=09/*=0A+=09=09=20*=20= Add=20the=20count=20of=20children=20contexts=20which=20are=20traversed=20= in=20the=0A+=09=09=20*=20non-recursive=20manner.=0A+=09=09=20*/=0A+=09=09= *num_contexts=20=3D=20*num_contexts=20+=20ichild;=0A+=0A+=09=09if=20= (print_location=20=3D=3D=20PRINT_STATS_TO_STDERR)=0A=20=09=09{=0A=20=09=09= =09for=20(int=20i=20=3D=200;=20i=20<=3D=20level;=20i++)=0A=20=09=09=09=09= fprintf(stderr,=20"=20=20");=0A@@=20-939,7=20+1014,7=20@@=20= MemoryContextStatsInternal(MemoryContext=20context,=20int=20level,=0A=20=09= =09=09=09=09local_totals.freechunks,=0A=20=09=09=09=09=09= local_totals.totalspace=20-=20local_totals.freespace);=0A=20=09=09}=0A-=09= =09else=0A+=09=09else=20if=20(print_location=20=3D=3D=20= PRINT_STATS_TO_LOGS)=0A=20=09=09=09ereport(LOG_SERVER_ONLY,=0A=20=09=09=09= =09=09(errhidestmt(true),=0A=20=09=09=09=09=09=20errhidecontext(true),=0A= @@=20-1276,6=20+1351,22=20@@=20HandleLogMemoryContextInterrupt(void)=0A=20= =09/*=20latch=20will=20be=20set=20by=20procsignal_sigusr1_handler=20*/=0A= =20}=0A=20=0A+/*=0A+=20*=20HandleGetMemoryContextInterrupt=0A+=20*=09=09= Handle=20receipt=20of=20an=20interrupt=20indicating=20a=20request=20to=20= publish=20memory=0A+=20*=09=09contexts=20statistics.=0A+=20*=0A+=20*=20= All=20the=20actual=20work=20is=20deferred=20to=20= ProcessGetMemoryContextInterrupt()=20as=0A+=20*=20this=20cannot=20be=20= performed=20in=20a=20signal=20handler.=0A+=20*/=0A+void=0A= +HandleGetMemoryContextInterrupt(void)=0A+{=0A+=09InterruptPending=20=3D=20= true;=0A+=09PublishMemoryContextPending=20=3D=20true;=0A+=09/*=20latch=20= will=20be=20set=20by=20procsignal_sigusr1_handler=20*/=0A+}=0A+=0A=20/*=0A= =20=20*=20ProcessLogMemoryContextInterrupt=0A=20=20*=20=09=09Perform=20= logging=20of=20memory=20contexts=20of=20this=20backend=20process.=0A@@=20= -1313,6=20+1404,537=20@@=20ProcessLogMemoryContextInterrupt(void)=0A=20=09= MemoryContextStatsDetail(TopMemoryContext,=20100,=20100,=20false);=0A=20= }=0A=20=0A+/*=0A+=20*=20ProcessGetMemoryContextInterrupt=0A+=20*=09=09= Generate=20information=20about=20memory=20contexts=20used=20by=20the=20= process.=0A+=20*=0A+=20*=20Performs=20a=20breadth=20first=20search=20on=20= the=20memory=20context=20tree,=20thus=20parents=0A+=20*=20statistics=20= are=20reported=20before=20their=20children=20in=20the=20monitoring=20= function=0A+=20*=20output.=0A+=20*=0A+=20*=20Statistics=20for=20all=20= the=20processes=20are=20shared=20via=20the=20same=20dynamic=20shared=0A+=20= *=20area.=20=20Statistics=20written=20by=20each=20process=20are=20= tracked=20independently=20in=0A+=20*=20per-process=20DSA=20pointers.=20= These=20pointers=20are=20stored=20in=20static=20shared=20memory.=0A+=20*=0A= +=20*=20We=20calculate=20maximum=20number=20of=20context's=20statistics=20= that=20can=20be=20displayed=0A+=20*=20using=20a=20pre-determined=20limit=20= for=20memory=20available=20per=20process=20for=20this=0A+=20*=20utility=20= maximum=20size=20of=20statistics=20for=20each=20context.=20=20The=20= remaining=20context=0A+=20*=20statistics=20if=20any=20are=20captured=20= as=20a=20cumulative=20total=20at=20the=20end=20of=0A+=20*=20individual=20= context's=20statistics.=0A+=20*=0A+=20*=20If=20summary=20is=20true,=20we=20= capture=20the=20level=201=20and=20level=202=20contexts=0A+=20*=20= statistics.=20=20For=20that=20we=20traverse=20the=20memory=20context=20= tree=20recursively=20in=0A+=20*=20depth=20first=20search=20manner=20to=20= cover=20all=20the=20children=20of=20a=20parent=20context,=20to=0A+=20*=20= be=20able=20to=20display=20a=20cumulative=20total=20of=20memory=20= consumption=20by=20a=20parent=20at=0A+=20*=20level=202=20and=20all=20its=20= children.=0A+=20*/=0A+void=0A+ProcessGetMemoryContextInterrupt(void)=0A= +{=0A+=09List=09=20=20=20*contexts;=0A+=09HASHCTL=09=09ctl;=0A+=09HTAB=09= =20=20=20*context_id_lookup;=0A+=09int=09=09=09context_id=20=3D=200;=0A+=09= MemoryStatsEntry=20*meminfo;=0A+=09bool=09=09summary=20=3D=20false;=0A+=09= int=09=09=09max_stats;=0A+=09int=09=09=09idx=20=3D=20MyProcNumber;=0A+=09= int=09=09=09stats_count=20=3D=200;=0A+=09int=09=09=09stats_num=20=3D=20= 0;=0A+=09MemoryContextCounters=20stat;=0A+=09int=09=09=09= num_individual_stats=20=3D=200;=0A+=0A+=09PublishMemoryContextPending=20= =3D=20false;=0A+=0A+=09/*=0A+=09=20*=20The=20hash=20table=20is=20used=20= for=20constructing=20"path"=20column=20of=20the=20view,=0A+=09=20*=20= similar=20to=20its=20local=20backend=20counterpart.=0A+=09=20*/=0A+=09= ctl.keysize=20=3D=20sizeof(MemoryContext);=0A+=09ctl.entrysize=20=3D=20= sizeof(MemoryStatsContextId);=0A+=09ctl.hcxt=20=3D=20= CurrentMemoryContext;=0A+=0A+=09context_id_lookup=20=3D=20= hash_create("pg_get_remote_backend_memory_contexts",=0A+=09=09=09=09=09=09= =09=09=09256,=0A+=09=09=09=09=09=09=09=09=09&ctl,=0A+=09=09=09=09=09=09=09= =09=09HASH_ELEM=20|=20HASH_BLOBS=20|=20HASH_CONTEXT);=0A+=0A+=09/*=20= List=20of=20contexts=20to=20process=20in=20the=20next=20round=20-=20= start=20at=20the=20top.=20*/=0A+=09contexts=20=3D=20= list_make1(TopMemoryContext);=0A+=0A+=09/*=20Compute=20the=20number=20of=20= stats=20that=20can=20fit=20in=20the=20defined=20limit=20*/=0A+=09= max_stats=20=3D=0A+=09=09MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND=20/=20= MAX_MEMORY_CONTEXT_STATS_SIZE;=0A+=09= LWLockAcquire(&memCxtState[idx].lw_lock,=20LW_EXCLUSIVE);=0A+=09summary=20= =3D=20memCxtState[idx].summary;=0A+=09= LWLockRelease(&memCxtState[idx].lw_lock);=0A+=0A+=09/*=0A+=09=20*=20= Traverse=20the=20memory=20context=20tree=20to=20find=20total=20number=20= of=20contexts.=20If=0A+=09=20*=20summary=20is=20requested=20report=20the=20= total=20number=20of=20contexts=20at=20level=201=20and=0A+=09=20*=202=20= from=20the=20top.=20Also,=20populate=20the=20hash=20table=20of=20context=20= ids.=0A+=09=20*/=0A+=09compute_contexts_count_and_ids(contexts,=20= context_id_lookup,=20&stats_count,=0A+=09=09=09=09=09=09=09=09=20=20=20= summary);=0A+=0A+=09/*=0A+=09=20*=20Allocate=20memory=20in=20this=20= process's=20DSA=20for=20storing=20statistics=20of=20the=20the=0A+=09=20*=20= memory=20contexts=20upto=20max_stats,=20for=20contexts=20that=20don't=20= fit=20within=20a=0A+=09=20*=20limit,=20a=20cumulative=20total=20is=20= written=20as=20the=20last=20record=20in=20the=20DSA=0A+=09=20*=20= segment.=0A+=09=20*/=0A+=09stats_num=20=3D=20Min(stats_count,=20= max_stats);=0A+=0A+=09LWLockAcquire(&memCxtArea->lw_lock,=20= LW_EXCLUSIVE);=0A+=0A+=09/*=0A+=09=20*=20Create=20a=20DSA=20and=20send=20= handle=20to=20the=20the=20client=20process=20after=20storing=0A+=09=20*=20= the=20context=20statistics.=20If=20number=20of=20contexts=20exceed=20a=20= predefined=0A+=09=20*=20limit(8MB),=20a=20cumulative=20total=20is=20= stored=20for=20such=20contexts.=0A+=09=20*/=0A+=09if=20= (memCxtArea->memstats_dsa_handle=20=3D=3D=20DSA_HANDLE_INVALID)=0A+=09{=0A= +=09=09MemoryContext=20oldcontext=20=3D=20CurrentMemoryContext;=0A+=09=09= dsa_handle=09handle;=0A+=0A+=09=09= MemoryContextSwitchTo(TopMemoryContext);=0A+=0A+=09=09area=20=3D=20= dsa_create(memCxtArea->lw_lock.tranche);=0A+=0A+=09=09handle=20=3D=20= dsa_get_handle(area);=0A+=09=09MemoryContextSwitchTo(oldcontext);=0A+=0A= +=09=09dsa_pin_mapping(area);=0A+=0A+=09=09/*=0A+=09=09=20*=20Pin=20the=20= DSA=20area,=20this=20is=20to=20make=20sure=20the=20area=20remains=20= attachable=0A+=09=09=20*=20even=20if=20current=20backend=20exits.=20This=20= is=20done=20so=20that=20the=20statistics=0A+=09=09=20*=20are=20published=20= even=20if=20the=20process=20exits=20while=20a=20client=20is=20waiting.=0A= +=09=09=20*/=0A+=09=09dsa_pin(area);=0A+=0A+=09=09/*=20Set=20the=20= handle=20in=20shared=20memory=20*/=0A+=09=09= memCxtArea->memstats_dsa_handle=20=3D=20handle;=0A+=09}=0A+=0A+=09/*=0A+=09= =20*=20If=20DSA=20exists,=20created=20by=20another=20process=20= publishing=20statistics,=20attach=0A+=09=20*=20to=20it.=0A+=09=20*/=0A+=09= else=20if=20(area=20=3D=3D=20NULL)=0A+=09{=0A+=09=09MemoryContext=20= oldcontext=20=3D=20CurrentMemoryContext;=0A+=0A+=09=09= MemoryContextSwitchTo(TopMemoryContext);=0A+=09=09area=20=3D=20= dsa_attach(memCxtArea->memstats_dsa_handle);=0A+=09=09= MemoryContextSwitchTo(oldcontext);=0A+=09=09dsa_pin_mapping(area);=0A+=09= }=0A+=09LWLockRelease(&memCxtArea->lw_lock);=0A+=0A+=09/*=0A+=09=20*=20= Hold=20the=20process=20lock=20to=20protect=20writes=20to=20process=20= specific=20memory.=20Two=0A+=09=20*=20processes=20publishing=20= statistics=20do=20not=20block=20each=20other.=0A+=09=20*/=0A+=09= LWLockAcquire(&memCxtState[idx].lw_lock,=20LW_EXCLUSIVE);=0A+=09= memCxtState[idx].proc_id=20=3D=20MyProcPid;=0A+=0A+=09if=20= (DsaPointerIsValid(memCxtState[idx].memstats_dsa_pointer))=0A+=09{=0A+=09= =09/*=0A+=09=09=20*=20Free=20any=20previous=20allocations,=20free=20the=20= name,=20ident=20and=20path=0A+=09=09=20*=20pointers=20before=20freeing=20= the=20pointer=20that=20contains=20them.=0A+=09=09=20*/=0A+=09=09= free_memorycontextstate_dsa(area,=20memCxtState[idx].total_stats,=0A+=09=09= =09=09=09=09=09=09=09memCxtState[idx].memstats_dsa_pointer);=0A+=09}=0A+=09= /*=0A+=09=20*=20Assigning=20total=20stats=20before=20allocating=20memory=20= so=20that=20memory=20cleanup=0A+=09=20*=20can=20run=20if=20any=20= subsequent=20dsa_allocate=20call=20to=20allocate=20name/ident/path=0A+=09= =20*=20fails.=0A+=09=20*/=0A+=09memCxtState[idx].total_stats=20=3D=20= stats_num;=0A+=09memCxtState[idx].memstats_dsa_pointer=20=3D=0A+=09=09= dsa_allocate0(area,=20stats_num=20*=20sizeof(MemoryStatsEntry));=0A+=0A+=09= meminfo=20=3D=20(MemoryStatsEntry=20*)=0A+=09=09dsa_get_address(area,=20= memCxtState[idx].memstats_dsa_pointer);=0A+=0A+=09if=20(summary)=0A+=09{=0A= +=09=09int=09=09=09cxt_id=20=3D=200;=0A+=09=09List=09=20=20=20*path=20=3D=20= NIL;=0A+=0A+=09=09/*=20Copy=20TopMemoryContext=20statistics=20to=20DSA=20= */=0A+=09=09memset(&stat,=200,=20sizeof(stat));=0A+=09=09= (*TopMemoryContext->methods->stats)=20(TopMemoryContext,=20NULL,=20NULL,=0A= +=09=09=09=09=09=09=09=09=09=09=09=20&stat,=20true);=0A+=09=09path=20=3D=20= lcons_int(1,=20path);=0A+=09=09PublishMemoryContext(meminfo,=20cxt_id,=20= TopMemoryContext,=20path,=20stat,=0A+=09=09=09=09=09=09=09=201,=20area,=20= 100);=0A+=09=09cxt_id=20=3D=20cxt_id=20+=201;=0A+=0A+=09=09/*=0A+=09=09=20= *=20Copy=20statistics=20for=20each=20of=20TopMemoryContexts=20children.=09= This=0A+=09=09=20*=20includes=20statistics=20of=20at=20most=20100=20= children=20per=20node,=20with=20each=0A+=09=09=20*=20child=20node=20= limited=20to=20a=20depth=20of=20100=20in=20its=20subtree.=0A+=09=09=20*/=0A= +=09=09for=20(MemoryContext=20c=20=3D=20TopMemoryContext->firstchild;=20= c=20!=3D=20NULL;=0A+=09=09=09=20c=20=3D=20c->nextchild)=0A+=09=09{=0A+=09= =09=09MemoryContextCounters=20grand_totals;=0A+=09=09=09int=09=09=09= num_contexts=20=3D=200;=0A+=09=09=09int=09=09=09level=20=3D=200;=0A+=0A+=09= =09=09path=20=3D=20NIL;=0A+=09=09=09memset(&grand_totals,=200,=20= sizeof(grand_totals));=0A+=0A+=09=09=09MemoryContextStatsInternal(c,=20= level,=20100,=20100,=20&grand_totals,=0A+=09=09=09=09=09=09=09=09=09=20=20= =20PRINT_STATS_NONE,=20&num_contexts);=0A+=0A+=09=09=09path=20=3D=20= compute_context_path(c,=20context_id_lookup);=0A+=0A+=09=09=09/*=0A+=09=09= =09=20*=20Register=20the=20stats=20entry=20first,=20that=20way=20the=20= cleanup=20handler=0A+=09=09=09=20*=20can=20reach=20it=20in=20case=20of=20= allocation=20failures=20of=20one=20or=20more=0A+=09=09=09=20*=20members.=0A= +=09=09=09=20*/=0A+=09=09=09memCxtState[idx].total_stats=20=3D=20= cxt_id++;=0A+=09=09=09PublishMemoryContext(meminfo,=20cxt_id,=20c,=20= path,=0A+=09=09=09=09=09=09=09=09=20grand_totals,=20num_contexts,=20= area,=20100);=0A+=09=09}=0A+=09=09memCxtState[idx].total_stats=20=3D=20= cxt_id;=0A+=0A+=09=09end_memorycontext_reporting();=0A+=0A+=09=09/*=20= Notify=20waiting=20backends=20and=20return=20*/=0A+=09=09= hash_destroy(context_id_lookup);=0A+=0A+=09=09return;=0A+=09}=0A+=0A+=09= foreach_ptr(MemoryContextData,=20cur,=20contexts)=0A+=09{=0A+=09=09List=09= =20=20=20*path=20=3D=20NIL;=0A+=0A+=09=09/*=0A+=09=09=20*=20Figure=20out=20= the=20transient=20context_id=20of=20this=20context=20and=20each=20of=20= its=0A+=09=09=20*=20ancestors,=20to=20compute=20a=20path=20for=20this=20= context.=0A+=09=09=20*/=0A+=09=09path=20=3D=20compute_context_path(cur,=20= context_id_lookup);=0A+=0A+=09=09/*=20Examine=20the=20context=20stats=20= */=0A+=09=09memset(&stat,=200,=20sizeof(stat));=0A+=09=09= (*cur->methods->stats)=20(cur,=20NULL,=20NULL,=20&stat,=20true);=0A+=0A+=09= =09/*=20Account=20for=20saving=20one=20statistics=20slot=20for=20= cumulative=20reporting=20*/=0A+=09=09if=20(context_id=20<=20(max_stats=20= -=201)=20||=20stats_count=20<=3D=20max_stats)=0A+=09=09{=0A+=09=09=09/*=20= Copy=20statistics=20to=20DSA=20memory=20*/=0A+=09=09=09= PublishMemoryContext(meminfo,=20context_id,=20cur,=20path,=20stat,=201,=20= area,=20100);=0A+=09=09}=0A+=09=09else=0A+=09=09{=0A+=09=09=09= meminfo[max_stats=20-=201].totalspace=20+=3D=20stat.totalspace;=0A+=09=09= =09meminfo[max_stats=20-=201].nblocks=20+=3D=20stat.nblocks;=0A+=09=09=09= meminfo[max_stats=20-=201].freespace=20+=3D=20stat.freespace;=0A+=09=09=09= meminfo[max_stats=20-=201].freechunks=20+=3D=20stat.freechunks;=0A+=09=09= }=0A+=0A+=09=09/*=0A+=09=09=20*=20DSA=20max=20limit=20per=20process=20is=20= reached,=20write=20aggregate=20of=20the=0A+=09=09=20*=20remaining=20= statistics.=0A+=09=09=20*=0A+=09=09=20*=20We=20can=20store=20contexts=20= from=200=20to=20max_stats=20-=201.=20When=20stats_count=20is=0A+=09=09=20= *=20greater=20than=20max_stats,=20we=20stop=20reporting=20individual=20= statistics=0A+=09=09=20*=20when=20context_id=20equals=20max_stats=20-=20= 2.=20As=20we=20use=20max_stats=20-=201=20array=0A+=09=09=20*=20slot=20= for=20reporting=20cumulative=20statistics=20or=20"Remaining=20Totals".=0A= +=09=09=20*/=0A+=09=09if=20(stats_count=20>=20max_stats=20&&=20= context_id=20=3D=3D=20(max_stats=20-=202))=0A+=09=09{=0A+=09=09=09char=09= =20=20=20*nameptr;=0A+=09=09=09int=09=09=09namelen=20=3D=20= strlen("Remaining=20Totals");=0A+=0A+=09=09=09num_individual_stats=20=3D=20= context_id=20+=201;=0A+=09=09=09meminfo[max_stats=20-=201].name=20=3D=20= dsa_allocate(area,=20namelen=20+=201);=0A+=09=09=09nameptr=20=3D=20= dsa_get_address(area,=20meminfo[max_stats=20-=201].name);=0A+=09=09=09= strncpy(nameptr,=20"Remaining=20Totals",=20namelen);=0A+=09=09=09= meminfo[max_stats=20-=201].ident=20=3D=20InvalidDsaPointer;=0A+=09=09=09= meminfo[max_stats=20-=201].path=20=3D=20InvalidDsaPointer;=0A+=09=09=09= meminfo[max_stats=20-=201].type=20=3D=200;=0A+=09=09}=0A+=09=09= context_id++;=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20Statistics=20are=20not=20= aggregated,=20i.e=20individual=20statistics=20reported=20when=0A+=09=20*=20= stats_count=20<=3D=20max_stats.=0A+=09=20*/=0A+=09if=20(stats_count=20<=3D= =20max_stats)=0A+=09{=0A+=09=09memCxtState[idx].total_stats=20=3D=20= context_id;=0A+=09}=0A+=09/*=20Report=20number=20of=20aggregated=20= memory=20contexts=20*/=0A+=09else=0A+=09{=0A+=09=09meminfo[max_stats=20-=20= 1].num_agg_stats=20=3D=20context_id=20-=0A+=09=09=09= num_individual_stats;=0A+=0A+=09=09/*=0A+=09=09=20*=20Total=20stats=20= equals=20num_individual_stats=20+=201=20record=20for=20cumulative=0A+=09=09= =20*=20statistics.=0A+=09=09=20*/=0A+=09=09memCxtState[idx].total_stats=20= =3D=20num_individual_stats=20+=201;=0A+=09}=0A+=0A+=09/*=20Notify=20= waiting=20backends=20and=20return=20*/=0A+=09= end_memorycontext_reporting();=0A+=0A+=09= hash_destroy(context_id_lookup);=0A+}=0A+=0A+/*=0A+=20*=20Update=20= timestamp=20and=20signal=20all=20the=20waiting=20client=20backends=20= after=20copying=0A+=20*=20all=20the=20statistics.=0A+=20*/=0A+static=20= void=0A+end_memorycontext_reporting(void)=0A+{=0A+=09= memCxtState[MyProcNumber].stats_timestamp=20=3D=20GetCurrentTimestamp();=0A= +=09LWLockRelease(&memCxtState[MyProcNumber].lw_lock);=0A+=09= ConditionVariableBroadcast(&memCxtState[MyProcNumber].memcxt_cv);=0A+}=0A= +=0A+/*=0A+=20*=20compute_context_path=0A+=20*=0A+=20*=20Append=20the=20= transient=20context_id=20of=20this=20context=20and=20each=20of=20its=20= ancestors=0A+=20*=20to=20a=20list,=20in=20order=20to=20compute=20a=20= path.=0A+=20*/=0A+static=20List=20*=0A= +compute_context_path(MemoryContext=20c,=20HTAB=20*context_id_lookup)=0A= +{=0A+=09bool=09=09found;=0A+=09List=09=20=20=20*path=20=3D=20NIL;=0A+=09= MemoryContext=20cur_context;=0A+=0A+=09for=20(cur_context=20=3D=20c;=20= cur_context=20!=3D=20NULL;=20cur_context=20=3D=20cur_context->parent)=0A= +=09{=0A+=09=09MemoryStatsContextId=20*cur_entry;=0A+=0A+=09=09cur_entry=20= =3D=20hash_search(context_id_lookup,=20&cur_context,=20HASH_FIND,=20= &found);=0A+=0A+=09=09if=20(!found)=0A+=09=09=09elog(ERROR,=20"hash=20= table=20corrupted,=20can't=20construct=20path=20value");=0A+=0A+=09=09= path=20=3D=20lcons_int(cur_entry->context_id,=20path);=0A+=09}=0A+=0A+=09= return=20path;=0A+}=0A+=0A+/*=0A+=20*=20Return=20the=20number=20of=20= contexts=20allocated=20currently=20by=20the=20backend=0A+=20*=20Assign=20= context=20ids=20to=20each=20of=20the=20contexts.=0A+=20*/=0A+static=20= void=0A+compute_contexts_count_and_ids(List=20*contexts,=20HTAB=20= *context_id_lookup,=0A+=09=09=09=09=09=09=09=20=20=20int=20*stats_count,=20= bool=20summary)=0A+{=0A+=09foreach_ptr(MemoryContextData,=20cur,=20= contexts)=0A+=09{=0A+=09=09MemoryStatsContextId=20*entry;=0A+=09=09bool=09= =09found;=0A+=0A+=09=09entry=20=3D=20(MemoryStatsContextId=20*)=20= hash_search(context_id_lookup,=20&cur,=0A+=09=09=09=09=09=09=09=09=09=09=09= =09=09=09=20HASH_ENTER,=20&found);=0A+=09=09Assert(!found);=0A+=0A+=09=09= /*=0A+=09=09=20*=20context=20id=20starts=20with=201=20so=20increment=20= the=20stats_count=0A+=09=09=20*=20before=20assigning=0A+=09=09=20*/=0A+=09= =09entry->context_id=20=3D=20++(*stats_count);=0A+=0A+=09=09/*=20Append=20= the=20children=20of=20the=20current=20context=20to=20the=20main=20list.=20= */=0A+=09=09for=20(MemoryContext=20c=20=3D=20cur->firstchild;=20c=20!=3D=20= NULL;=20c=20=3D=20c->nextchild)=0A+=09=09{=0A+=09=09=09if=20(summary)=0A= +=09=09=09{=0A+=09=09=09=09entry=20=3D=20(MemoryStatsContextId=20*)=20= hash_search(context_id_lookup,=20&c,=0A+=09=09=09=09=09=09=09=09=09=09=09= =09=09=09=09=09=20HASH_ENTER,=20&found);=0A+=09=09=09=09Assert(!found);=0A= +=0A+=09=09=09=09entry->context_id=20=3D=20++(*stats_count);=0A+=09=09=09= }=0A+=0A+=09=09=09contexts=20=3D=20lappend(contexts,=20c);=0A+=09=09}=0A= +=0A+=09=09/*=0A+=09=09=20*=20In=20summary=20mode=20only=20the=20first=20= two=20level=20(from=20top)=20contexts=20are=0A+=09=09=20*=20displayed.=0A= +=09=09=20*/=0A+=09=09if=20(summary)=0A+=09=09=09break;=0A+=09}=0A+}=0A+=0A= +/*=0A+=20*=20PublishMemoryContext=0A+=20*=0A+=20*=20Copy=20the=20memory=20= context=20statistics=20of=20a=20single=20context=20to=20a=20DSA=20memory=0A= +=20*/=0A+static=20void=0A+PublishMemoryContext(MemoryStatsEntry=20= *memcxt_info,=20int=20curr_id,=0A+=09=09=09=09=09=20MemoryContext=20= context,=20List=20*path,=0A+=09=09=09=09=09=20MemoryContextCounters=20= stat,=20int=20num_contexts,=0A+=09=09=09=09=09=20dsa_area=20*area,=20int=20= max_levels)=0A+{=0A+=09const=20char=20*ident=20=3D=20context->ident;=0A+=09= const=20char=20*name=20=3D=20context->name;=0A+=09int=09=09=20=20=20= *path_list;=0A+=0A+=09/*=0A+=09=20*=20To=20be=20consistent=20with=20= logging=20output,=20we=20label=20dynahash=20contexts=20with=0A+=09=20*=20= just=20the=20hash=20table=20name=20as=20with=20= MemoryContextStatsPrint().=0A+=09=20*/=0A+=09if=20(context->ident=20&&=20= strncmp(context->name,=20"dynahash",=208)=20=3D=3D=200)=0A+=09{=0A+=09=09= name=20=3D=20context->ident;=0A+=09=09ident=20=3D=20NULL;=0A+=09}=0A+=0A= +=09if=20(name=20!=3D=20NULL)=0A+=09{=0A+=09=09int=09=09=09namelen=20=3D=20= strlen(name);=0A+=09=09char=09=20=20=20*nameptr;=0A+=0A+=09=09if=20= (strlen(name)=20>=3D=20MEMORY_CONTEXT_IDENT_SHMEM_SIZE)=0A+=09=09=09= namelen=20=3D=20pg_mbcliplen(name,=20namelen,=0A+=09=09=09=09=09=09=09=09= =20=20=20MEMORY_CONTEXT_IDENT_SHMEM_SIZE=20-=201);=0A+=0A+=09=09= memcxt_info[curr_id].name=20=3D=20dsa_allocate(area,=20namelen=20+=201);=0A= +=09=09nameptr=20=3D=20(char=20*)=20dsa_get_address(area,=20= memcxt_info[curr_id].name);=0A+=09=09strlcpy(nameptr,=20name,=20namelen=20= +=201);=0A+=09}=0A+=09else=0A+=09=09memcxt_info[curr_id].name=20=3D=20= InvalidDsaPointer;=0A+=0A+=09/*=20Trim=20and=20copy=20the=20identifier=20= if=20it=20is=20not=20set=20to=20NULL=20*/=0A+=09if=20(ident=20!=3D=20= NULL)=0A+=09{=0A+=09=09int=09=09=09idlen=20=3D=20strlen(context->ident);=0A= +=09=09char=09=20=20=20*identptr;=0A+=0A+=09=09/*=0A+=09=09=20*=20Some=20= identifiers=20such=20as=20SQL=20query=20string=20can=20be=20very=20long,=0A= +=09=09=20*=20truncate=20oversize=20identifiers.=0A+=09=09=20*/=0A+=09=09= if=20(idlen=20>=3D=20MEMORY_CONTEXT_IDENT_SHMEM_SIZE)=0A+=09=09=09idlen=20= =3D=20pg_mbcliplen(ident,=20idlen,=0A+=09=09=09=09=09=09=09=09=20= MEMORY_CONTEXT_IDENT_SHMEM_SIZE=20-=201);=0A+=0A+=09=09= memcxt_info[curr_id].ident=20=3D=20dsa_allocate(area,=20idlen=20+=201);=0A= +=09=09identptr=20=3D=20(char=20*)=20dsa_get_address(area,=20= memcxt_info[curr_id].ident);=0A+=09=09strlcpy(identptr,=20ident,=20idlen=20= +=201);=0A+=09}=0A+=09else=0A+=09=09memcxt_info[curr_id].ident=20=3D=20= InvalidDsaPointer;=0A+=0A+=09/*=20Allocate=20DSA=20memory=20for=20= storing=20path=20information=20*/=0A+=09if=20(path=20=3D=3D=20NIL)=0A+=09= =09memcxt_info[curr_id].path=20=3D=20InvalidDsaPointer;=0A+=09else=0A+=09= {=0A+=09=09int=09=09=09levels=20=3D=20Min(list_length(path),=20= max_levels);=0A+=0A+=09=09memcxt_info[curr_id].path_length=20=3D=20= levels;=0A+=09=09memcxt_info[curr_id].path=20=3D=20dsa_allocate0(area,=20= levels=20*=20sizeof(int));=0A+=09=09memcxt_info[curr_id].levels=20=3D=20= list_length(path);=0A+=09=09path_list=20=3D=20(int=20*)=20= dsa_get_address(area,=20memcxt_info[curr_id].path);=0A+=0A+=09=09= foreach_int(i,=20path)=0A+=09=09{=0A+=09=09=09= path_list[foreach_current_index(i)]=20=3D=20i;=0A+=09=09=09if=20= (--levels=20=3D=3D=200)=0A+=09=09=09=09break;=0A+=09=09}=0A+=09}=0A+=09= memcxt_info[curr_id].type=20=3D=20context->type;=0A+=09= memcxt_info[curr_id].totalspace=20=3D=20stat.totalspace;=0A+=09= memcxt_info[curr_id].nblocks=20=3D=20stat.nblocks;=0A+=09= memcxt_info[curr_id].freespace=20=3D=20stat.freespace;=0A+=09= memcxt_info[curr_id].freechunks=20=3D=20stat.freechunks;=0A+=09= memcxt_info[curr_id].num_agg_stats=20=3D=20num_contexts;=0A+}=0A+=0A+/*=0A= +=20*=20free_memorycontextstate_dsa=0A+=20*=0A+=20*=20Worker=20for=20= freeing=20resources=20from=20a=20MemoryStatsEntry.=20=20Callers=20are=0A= +=20*=20responsible=20for=20ensuring=20that=20the=20DSA=20pointer=20is=20= valid.=0A+=20*/=0A+static=20void=0A+free_memorycontextstate_dsa(dsa_area=20= *area,=20int=20total_stats,=0A+=09=09=09=09=09=09=09dsa_pointer=20= prev_dsa_pointer)=0A+{=0A+=09MemoryStatsEntry=20*meminfo;=0A+=0A+=09= meminfo=20=3D=20(MemoryStatsEntry=20*)=20dsa_get_address(area,=20= prev_dsa_pointer);=0A+=09Assert(meminfo=20!=3D=20NULL);=0A+=09for=20(int=20= i=20=3D=200;=20i=20<=20total_stats;=20i++)=0A+=09{=0A+=09=09if=20= (DsaPointerIsValid(meminfo[i].name))=0A+=09=09=09dsa_free(area,=20= meminfo[i].name);=0A+=0A+=09=09if=20= (DsaPointerIsValid(meminfo[i].ident))=0A+=09=09=09dsa_free(area,=20= meminfo[i].ident);=0A+=0A+=09=09if=20= (DsaPointerIsValid(meminfo[i].path))=0A+=09=09=09dsa_free(area,=20= meminfo[i].path);=0A+=09}=0A+=0A+=09dsa_free(area,=20= memCxtState[MyProcNumber].memstats_dsa_pointer);=0A+=09= memCxtState[MyProcNumber].memstats_dsa_pointer=20=3D=20= InvalidDsaPointer;=0A+}=0A+=0A+/*=0A+=20*=20Free=20the=20memory=20= context=20statistics=20stored=20by=20this=20process=0A+=20*=20in=20DSA=20= area.=0A+=20*/=0A+void=0A+AtProcExit_memstats_cleanup(int=20code,=20= Datum=20arg)=0A+{=0A+=09int=09=09=09idx=20=3D=20MyProcNumber;=0A+=0A+=09= if=20(memCxtArea->memstats_dsa_handle=20=3D=3D=20DSA_HANDLE_INVALID)=0A+=09= =09return;=0A+=0A+=09LWLockAcquire(&memCxtState[idx].lw_lock,=20= LW_EXCLUSIVE);=0A+=0A+=09if=20= (!DsaPointerIsValid(memCxtState[idx].memstats_dsa_pointer))=0A+=09{=0A+=09= =09LWLockRelease(&memCxtState[idx].lw_lock);=0A+=09=09return;=0A+=09}=0A= +=0A+=09/*=20If=20the=20dsa=20mapping=20could=20not=20be=20found,=20= attach=20to=20the=20area=20*/=0A+=09if=20(area=20=3D=3D=20NULL)=0A+=09=09= area=20=3D=20dsa_attach(memCxtArea->memstats_dsa_handle);=0A+=0A+=09/*=0A= +=09=20*=20Free=20the=20memory=20context=20statistics,=20free=20the=20= name,=20ident=20and=20path=0A+=09=20*=20pointers=20before=20freeing=20= the=20pointer=20that=20contains=20these=20pointers=20and=0A+=09=20*=20= integer=20statistics.=0A+=09=20*/=0A+=09= free_memorycontextstate_dsa(area,=20memCxtState[idx].total_stats,=0A+=09=09= =09=09=09=09=09=09memCxtState[idx].memstats_dsa_pointer);=0A+=0A+=09= dsa_detach(area);=0A+=09LWLockRelease(&memCxtState[idx].lw_lock);=0A+}=0A= +=0A=20void=20*=0A=20palloc(Size=20size)=0A=20{=0Adiff=20--git=20= a/src/include/catalog/pg_proc.dat=20b/src/include/catalog/pg_proc.dat=0A= index=2037a484147a8..4708f55be18=20100644=0A---=20= a/src/include/catalog/pg_proc.dat=0A+++=20= b/src/include/catalog/pg_proc.dat=0A@@=20-8571,6=20+8571,16=20@@=0A=20=20= =20prorettype=20=3D>=20'bool',=20proargtypes=20=3D>=20'int4',=0A=20=20=20= prosrc=20=3D>=20'pg_log_backend_memory_contexts'=20},=0A=20=0A+#=20= publishing=20memory=20contexts=20of=20the=20specified=20postgres=20= process=0A+{=20oid=20=3D>=20'2173',=20descr=20=3D>=20'publish=20memory=20= contexts=20of=20the=20specified=20backend',=0A+=20=20proname=20=3D>=20= 'pg_get_process_memory_contexts',=20provolatile=20=3D>=20'v',=0A+=20=20= prorows=20=3D>=20'100',=20proretset=20=3D>=20't',=20proparallel=20=3D>=20= 'r',=0A+=20=20prorettype=20=3D>=20'record',=20proargtypes=20=3D>=20'int4=20= bool=20float8',=0A+=20=20proallargtypes=20=3D>=20= '{int4,bool,float8,text,text,text,_int4,int4,int8,int8,int8,int8,int8,int4= ,timestamptz}',=0A+=20=20proargmodes=20=3D>=20= '{i,i,i,o,o,o,o,o,o,o,o,o,o,o,o}',=0A+=20=20proargnames=20=3D>=20'{pid,=20= summary,=20retries,=20name,=20ident,=20type,=20path,=20level,=20= total_bytes,=20total_nblocks,=20free_bytes,=20free_chunks,=20used_bytes,=20= num_agg_contexts,=20stats_timestamp}',=0A+=20=20prosrc=20=3D>=20= 'pg_get_process_memory_contexts'=20},=0A+=0A=20#=20non-persistent=20= series=20generator=0A=20{=20oid=20=3D>=20'1066',=20descr=20=3D>=20= 'non-persistent=20series=20generator',=0A=20=20=20proname=20=3D>=20= 'generate_series',=20prorows=20=3D>=20'1000',=0Adiff=20--git=20= a/src/include/miscadmin.h=20b/src/include/miscadmin.h=0Aindex=20= 0d8528b2875..58b2496a9cb=20100644=0A---=20a/src/include/miscadmin.h=0A= +++=20b/src/include/miscadmin.h=0A@@=20-96,6=20+96,7=20@@=20extern=20= PGDLLIMPORT=20volatile=20sig_atomic_t=20IdleSessionTimeoutPending;=0A=20= extern=20PGDLLIMPORT=20volatile=20sig_atomic_t=20= ProcSignalBarrierPending;=0A=20extern=20PGDLLIMPORT=20volatile=20= sig_atomic_t=20LogMemoryContextPending;=0A=20extern=20PGDLLIMPORT=20= volatile=20sig_atomic_t=20IdleStatsUpdateTimeoutPending;=0A+extern=20= PGDLLIMPORT=20volatile=20sig_atomic_t=20PublishMemoryContextPending;=0A=20= =0A=20extern=20PGDLLIMPORT=20volatile=20sig_atomic_t=20= CheckClientConnectionPending;=0A=20extern=20PGDLLIMPORT=20volatile=20= sig_atomic_t=20ClientConnectionLost;=0Adiff=20--git=20= a/src/include/storage/lwlock.h=20b/src/include/storage/lwlock.h=0Aindex=20= 4df1d25c045..d333f338ebb=20100644=0A---=20a/src/include/storage/lwlock.h=0A= +++=20b/src/include/storage/lwlock.h=0A@@=20-219,6=20+219,8=20@@=20= typedef=20enum=20BuiltinTrancheIds=0A=20=09LWTRANCHE_XACT_SLRU,=0A=20=09= LWTRANCHE_PARALLEL_VACUUM_DSA,=0A=20=09LWTRANCHE_AIO_URING_COMPLETION,=0A= +=09LWTRANCHE_MEMORY_CONTEXT_REPORTING_STATE,=0A+=09= LWTRANCHE_MEMORY_CONTEXT_REPORTING_PROC,=0A=20=09= LWTRANCHE_FIRST_USER_DEFINED,=0A=20}=09=09=09BuiltinTrancheIds;=0A=20=0A= diff=20--git=20a/src/include/storage/procsignal.h=20= b/src/include/storage/procsignal.h=0Aindex=20016dfd9b3f6..cfe14631445=20= 100644=0A---=20a/src/include/storage/procsignal.h=0A+++=20= b/src/include/storage/procsignal.h=0A@@=20-35,6=20+35,7=20@@=20typedef=20= enum=0A=20=09PROCSIG_WALSND_INIT_STOPPING,=09/*=20ask=20walsenders=20to=20= prepare=20for=20shutdown=20=20*/=0A=20=09PROCSIG_BARRIER,=09=09=09/*=20= global=20barrier=20interrupt=20=20*/=0A=20=09PROCSIG_LOG_MEMORY_CONTEXT,=20= /*=20ask=20backend=20to=20log=20the=20memory=20contexts=20*/=0A+=09= PROCSIG_GET_MEMORY_CONTEXT,=20/*=20ask=20backend=20to=20send=20the=20= memory=20contexts=20*/=0A=20=09PROCSIG_PARALLEL_APPLY_MESSAGE,=20/*=20= Message=20from=20parallel=20apply=20workers=20*/=0A=20=0A=20=09/*=20= Recovery=20conflict=20reasons=20*/=0Adiff=20--git=20= a/src/include/utils/memutils.h=20b/src/include/utils/memutils.h=0Aindex=20= 8abc26abce2..d328270fafc=20100644=0A---=20a/src/include/utils/memutils.h=0A= +++=20b/src/include/utils/memutils.h=0A@@=20-18,6=20+18,9=20@@=0A=20= #define=20MEMUTILS_H=0A=20=0A=20#include=20"nodes/memnodes.h"=0A= +#include=20"storage/condition_variable.h"=0A+#include=20= "storage/lmgr.h"=0A+#include=20"utils/dsa.h"=0A=20=0A=20=0A=20/*=0A@@=20= -48,6=20+51,23=20@@=0A=20=0A=20#define=20AllocHugeSizeIsValid(size)=09= ((Size)=20(size)=20<=3D=20MaxAllocHugeSize)=0A=20=0A+/*=0A+=20*=20Memory=20= Context=20reporting=20size=20limits.=0A+=20*/=0A+=0A+/*=20Max=20length=20= of=20context=20name=20and=20ident=20*/=0A+#define=20= MEMORY_CONTEXT_IDENT_SHMEM_SIZE=2064=0A+/*=20Maximum=20size=20(in=20= bytes)=20of=20DSA=20area=20per=20process=20*/=0A+#define=20= MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND=20=20((size_t)=20(1=20*=201024=20*=20= 1024))=0A+=0A+/*=0A+=20*=20Maximum=20size=20per=20context.=20Actual=20= size=20may=20be=20lower=20as=20this=20assumes=20the=20worst=0A+=20*=20= case=20of=20deepest=20path=20and=20longest=20identifiers=20(name=20and=20= ident,=20thus=20the=0A+=20*=20multiplication=20by=202).=20The=20path=20= depth=20is=20limited=20to=20100=20like=20for=20memory=0A+=20*=20context=20= logging.=0A+=20*/=0A+#define=20MAX_MEMORY_CONTEXT_STATS_SIZE=20= (sizeof(MemoryStatsEntry)=20+=20\=0A+=09(100=20*=20sizeof(int))=20+=20(2=20= *=20MEMORY_CONTEXT_IDENT_SHMEM_SIZE))=0A=20=0A=20/*=0A=20=20*=20Standard=20= top-level=20memory=20contexts.=0A@@=20-319,4=20+339,66=20@@=20= pg_memory_is_all_zeros(const=20void=20*ptr,=20size_t=20len)=0A=20=09= return=20true;=0A=20}=0A=20=0A+/*=20Dynamic=20shared=20memory=20state=20= for=20statistics=20per=20context=20*/=0A+typedef=20struct=20= MemoryStatsEntry=0A+{=0A+=09dsa_pointer=20name;=0A+=09dsa_pointer=20= ident;=0A+=09dsa_pointer=20path;=0A+=09NodeTag=09=09type;=0A+=09int=09=09= =09path_length;=0A+=09int=09=09=09levels;=0A+=09int64=09=09totalspace;=0A= +=09int64=09=09nblocks;=0A+=09int64=09=09freespace;=0A+=09int64=09=09= freechunks;=0A+=09int=09=09=09num_agg_stats;=0A+}=20MemoryStatsEntry;=0A= +=0A+/*=0A+=20*=20Static=20shared=20memory=20state=20representing=20the=20= DSA=20area=20created=20for=20memory=0A+=20*=20context=20statistics=20= reporting.=20=20A=20single=20DSA=20area=20is=20created=20and=20used=20by=20= all=0A+=20*=20the=20processes,=20each=20having=20its=20specific=20DSA=20= allocations=20for=20sharing=20memory=0A+=20*=20statistics,=20tracked=20= by=20per=20backend=20static=20shared=20memory=20state.=0A+=20*/=0A= +typedef=20struct=20MemoryStatsCtl=0A+{=0A+=09dsa_handle=09= memstats_dsa_handle;=0A+=09LWLock=09=09lw_lock;=0A+}=20MemoryStatsCtl;=0A= +=0A+/*=0A+=20*=20Per=20backend=20static=20shared=20memory=20state=20for=20= memory=20context=20statistics=0A+=20*=20reporting.=0A+=20*/=0A+typedef=20= struct=20MemoryStatsBackendState=0A+{=0A+=09ConditionVariable=20= memcxt_cv;=0A+=09LWLock=09=09lw_lock;=0A+=09int=09=09=09proc_id;=0A+=09= int=09=09=09total_stats;=0A+=09bool=09=09summary;=0A+=09dsa_pointer=20= memstats_dsa_pointer;=0A+=09TimestampTz=20stats_timestamp;=0A+}=20= MemoryStatsBackendState;=0A+=0A+=0A+/*=0A+=20*=20Used=20for=20storage=20= of=20transient=20identifiers=20for=20pg_get_backend_memory_contexts=0A+=20= */=0A+typedef=20struct=20MemoryStatsContextId=0A+{=0A+=09MemoryContext=20= context;=0A+=09int=09=09=09context_id;=0A+}=20MemoryStatsContextId;=0A+=0A= +extern=20PGDLLIMPORT=20MemoryStatsBackendState=20*memCxtState;=0A= +extern=20PGDLLIMPORT=20MemoryStatsCtl=20*memCxtArea;=0A+extern=20void=20= ProcessGetMemoryContextInterrupt(void);=0A+extern=20const=20char=20= *ContextTypeToString(NodeTag=20type);=0A+extern=20void=20= HandleGetMemoryContextInterrupt(void);=0A+extern=20Size=20= MemoryContextReportingShmemSize(void);=0A+extern=20void=20= MemoryContextReportingShmemInit(void);=0A+extern=20void=20= AtProcExit_memstats_cleanup(int=20code,=20Datum=20arg);=0A+extern=20= dsa_area=20*area;=0A=20#endif=09=09=09=09=09=09=09/*=20MEMUTILS_H=20*/=0A= diff=20--git=20a/src/test/regress/expected/sysviews.out=20= b/src/test/regress/expected/sysviews.out=0Aindex=20= 83228cfca29..ae17d028ed3=20100644=0A---=20= a/src/test/regress/expected/sysviews.out=0A+++=20= b/src/test/regress/expected/sysviews.out=0A@@=20-232,3=20+232,22=20@@=20= select=20*=20from=20pg_timezone_abbrevs=20where=20abbrev=20=3D=20'LMT';=0A= =20=20LMT=20=20=20=20|=20@=207=20hours=2052=20mins=2058=20secs=20ago=20|=20= f=0A=20(1=20row)=0A=20=0A+DO=20$$=0A+DECLARE=0A+=20=20=20=20= bg_writer_pid=20int;=0A+=20=20=20=20r=20RECORD;=0A+BEGIN=0A+=20=20=20=20=20= =20=20=20SELECT=20pid=20from=20pg_stat_activity=20where=20= backend_type=3D'background=20writer'=0A+=09=20INTO=20bg_writer_pid;=0A+=0A= +=20=20=20=20=20=20=20=20select=20type,=20name,=20ident=0A+=20=20=20=20=20= =20=20=20from=20pg_get_process_memory_contexts(bg_writer_pid,=20false,=20= 20)=0A+=09=20where=20path=20=3D=20'{1}'=20into=20r;=0A+=09RAISE=20NOTICE=20= '%',=20r;=0A+=20=20=20=20=20=20=20=20select=20type,=20name,=20ident=0A+=20= =20=20=20=20=20=20=20from=20= pg_get_process_memory_contexts(pg_backend_pid(),=20false,=2020)=0A+=09=20= where=20path=20=3D=20'{1}'=20into=20r;=0A+=09RAISE=20NOTICE=20'%',=20r;=0A= +END=20$$;=0A+NOTICE:=20=20(AllocSet,TopMemoryContext,)=0A+NOTICE:=20=20= (AllocSet,TopMemoryContext,)=0Adiff=20--git=20= a/src/test/regress/sql/sysviews.sql=20= b/src/test/regress/sql/sysviews.sql=0Aindex=2066179f026b3..d0917b6868e=20= 100644=0A---=20a/src/test/regress/sql/sysviews.sql=0A+++=20= b/src/test/regress/sql/sysviews.sql=0A@@=20-101,3=20+101,21=20@@=20= select=20count(distinct=20utc_offset)=20>=3D=2024=20as=20ok=20from=20= pg_timezone_abbrevs;=0A=20--=20One=20specific=20case=20we=20can=20check=20= without=20much=20fear=20of=20breakage=0A=20--=20is=20the=20historical=20= local-mean-time=20value=20used=20for=20America/Los_Angeles.=0A=20select=20= *=20from=20pg_timezone_abbrevs=20where=20abbrev=20=3D=20'LMT';=0A+=0A+DO=20= $$=0A+DECLARE=0A+=20=20=20=20bg_writer_pid=20int;=0A+=20=20=20=20r=20= RECORD;=0A+BEGIN=0A+=20=20=20=20=20=20=20=20SELECT=20pid=20from=20= pg_stat_activity=20where=20backend_type=3D'background=20writer'=0A+=09=20= INTO=20bg_writer_pid;=0A+=0A+=20=20=20=20=20=20=20=20select=20type,=20= name,=20ident=0A+=20=20=20=20=20=20=20=20from=20= pg_get_process_memory_contexts(bg_writer_pid,=20false,=2020)=0A+=09=20= where=20path=20=3D=20'{1}'=20into=20r;=0A+=09RAISE=20NOTICE=20'%',=20r;=0A= +=20=20=20=20=20=20=20=20select=20type,=20name,=20ident=0A+=20=20=20=20=20= =20=20=20from=20pg_get_process_memory_contexts(pg_backend_pid(),=20= false,=2020)=0A+=09=20where=20path=20=3D=20'{1}'=20into=20r;=0A+=09RAISE=20= NOTICE=20'%',=20r;=0A+END=20$$;=0Adiff=20--git=20= a/src/tools/pgindent/typedefs.list=20b/src/tools/pgindent/typedefs.list=0A= index=2087e6da8d25e..780e4c4fc07=20100644=0A---=20= a/src/tools/pgindent/typedefs.list=0A+++=20= b/src/tools/pgindent/typedefs.list=0A@@=20-1671,6=20+1671,10=20@@=20= MemoryContextCounters=0A=20MemoryContextData=0A=20MemoryContextMethodID=0A= =20MemoryContextMethods=0A+MemoryStatsBackendState=0A= +MemoryStatsContextId=0A+MemoryStatsCtl=0A+MemoryStatsEntry=0A=20= MemoryStatsPrintFunc=0A=20MergeAction=0A=20MergeActionState=0A--=20=0A= 2.39.3=20(Apple=20Git-146)=0A=0A= --Apple-Mail=_9EDD47DB-9E7B-45A3-93DD-8E1FC0B49F61 Content-Transfer-Encoding: 7bit Content-Type: text/html; charset=us-ascii
--Apple-Mail=_9EDD47DB-9E7B-45A3-93DD-8E1FC0B49F61-- --Apple-Mail=_21310A6A-E5F1-4E61-AB75-9B7D3C412E58--