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 1u19E3-00Evbs-2s for pgsql-hackers@arkaria.postgresql.org; Sat, 05 Apr 2025 19:30:44 +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 1u19D2-0028eF-9d for pgsql-hackers@arkaria.postgresql.org; Sat, 05 Apr 2025 19:29:40 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1u19D1-0028e6-FT for pgsql-hackers@lists.postgresql.org; Sat, 05 Apr 2025 19:29:40 +0000 Received: from smtp.outgoing.loopia.se ([93.188.3.37]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1u19Cx-0039tl-2q for pgsql-hackers@postgresql.org; Sat, 05 Apr 2025 19:29:38 +0000 Received: from s807.loopia.se (localhost [127.0.0.1]) by s807.loopia.se (Postfix) with ESMTP id 120B2344D4F for ; Sat, 05 Apr 2025 21:29:32 +0200 (CEST) Received: from s934.loopia.se (unknown [172.22.191.6]) by s807.loopia.se (Postfix) with ESMTP id EC293346504; Sat, 05 Apr 2025 21:29:31 +0200 (CEST) Received: from s898.loopia.se (unknown [172.22.191.5]) by s934.loopia.se (Postfix) with ESMTP id E86C07CEA61; Sat, 05 Apr 2025 21:29:31 +0200 (CEST) X-Virus-Scanned: amavisd-new at amavis.loopia.se X-Spam-Flag: NO X-Spam-Score: -1.2 X-Spam-Level: X-Spam-Status: No, score=-1.2 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] autolearn=disabled Authentication-Results: s898.loopia.se (amavisd-new); dkim=pass (2048-bit key) header.d=yesql.se Received: from s899.loopia.se ([172.22.191.6]) by s898.loopia.se (s898.loopia.se [172.22.190.17]) (amavisd-new, port 10024) with LMTP id ldQCOi3aP8dq; Sat, 5 Apr 2025 21:29:31 +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 s899.loopia.se (Postfix) with ESMTPSA id 434F02C8BA67; Sat, 05 Apr 2025 21:29:31 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yesql.se; s=loopiadkim1707475645; t=1743881371; bh=DILvI5m0dEWNoH1ylP6p7uuYo+3gfNXupZf3y1wBqF8=; h=From:Subject:Date:In-Reply-To:Cc:To:References; b=Jk09vbyq3p1HGVN7opZQNsuGJabNFJt5HzXP44pgF+uPWjvZ3+9Eriy/HhmoUxAJR TeUSea/cCRVReF/swLHreAeyPp2JfZVx1lPnBoL7rGw36eULUHpNnAXnVVVxX9I9wQ AwsuvDcS3HY7bOr4wX+f7BE8tqA8ej8Y4MGHugPR2SHAKtwmiHCyCu3CE85ByPyhcJ Z4gi/uvugZIYmP3Qapmsa6boE38onajao84majDwmfpirtrHISndL25Rg0FWiMwmH8 0ATQGiV3Ft1BtKGm370CrixT0ToutpFyHCyBmvk7u6E+F7QZUOhaC0uxbdMN1nifgD J+97rqgax9DBA== From: Daniel Gustafsson Message-Id: <54FAE93D-E156-4684-9352-1CEDE6BD4A1C@yesql.se> Content-Type: multipart/mixed; boundary="Apple-Mail=_B78FFBF9-35A3-42C7-B47F-7EFB12A5C22E" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3776.700.51.11.1\)) Subject: Re: Enhancing Memory Context Statistics Reporting Date: Sat, 5 Apr 2025 21:29:21 +0200 In-Reply-To: Cc: PostgreSQL Hackers To: Rahila Syed References: <7d4db5cf-8d72-4ee1-8f2e-f88ef9615f27@vondra.me> <637b3ae3-b9eb-4d83-a942-5f7483911ea4@vondra.me> <29ced66e28ec696d1ac29747bd901df2@oss.nttdata.com> <5a899047-65fc-47c5-9c35-1035f44956c6@vondra.me> <70146bd0-da0f-48ee-bece-1e35536189e0@oss.nttdata.com> <2eb8fd76-89f0-42e8-bc79-152d50c63016@vondra.me> <81607c8c04a21b5cac87b21e46566074@oss.nttdata.com> <4c2b5401-41ad-43b9-9215-c7b2d901f8ed@vondra.me> <84996B31-C278-4373-8F56-C5A38A4530BA@yesql.se> 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=_B78FFBF9-35A3-42C7-B47F-7EFB12A5C22E Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On 2 Apr 2025, at 23:44, Daniel Gustafsson wrote: > I think this version is close to a committable state, will spend a = little more > time testing, polishing and rewriting the commit message. I will also = play > around with placement within the memory context code files to keep it = from > making backpatch issues. After a bit more polish I landed with the attached, which I most likely = will go ahead with after another round in CI. -- Daniel Gustafsson --Apple-Mail=_B78FFBF9-35A3-42C7-B47F-7EFB12A5C22E Content-Disposition: attachment; filename=v23-0001-Add-function-to-get-memory-context-stats-for-pro.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v23-0001-Add-function-to-get-memory-context-stats-for-pro.patch" Content-Transfer-Encoding: quoted-printable =46rom=200640d85687f5c9c917aab97b76c336d052ddfad5=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Rahila=20Syed=20=0A= Date:=20Wed,=2026=20Mar=202025=2014:38:39=20+0530=0ASubject:=20[PATCH=20= v23]=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=20retries=20to=20perform,=20= each=20with=20a=20500msec=20sleep.=0AIn=20the=20case=20there=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= Tomas=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|=20=2095=20+++=0A=20= src/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=20src/backend/postmaster/interrupt.c=20=20=20=20=20= =20=20=20=20=20=20=20|=20=20=204=20+=0A=20= src/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/proc.c=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20|=20=2015=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|=20432=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/mmgr/mcxt.c=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20= =20=20|=20615=20+++++++++++++++++-=0A=20src/include/catalog/pg_proc.dat=20= =20=20=20=20=20=20=20=20=20=20=20=20=20=20|=20=2010=20+=0A=20= src/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=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=2080=20+++=0A=20src/test/regress/expected/sysviews.out=20=20= =20=20=20=20=20=20|=20=2014=20+=0A=20src/test/regress/sql/sysviews.sql=20= =20=20=20=20=20=20=20=20=20=20=20=20|=20=2014=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=2022=20files=20changed,=201276=20insertions(+),=2040=20= deletions(-)=0A=0Adiff=20--git=20a/doc/src/sgml/func.sgml=20= b/doc/src/sgml/func.sgml=0Aindex=200224f93733d..b5add4bf99a=20100644=0A= ---=20a/doc/src/sgml/func.sgml=0A+++=20b/doc/src/sgml/func.sgml=0A@@=20= -28650,6=20+28650,68=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= retries=20integer=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=20Memory=20contexts=20are=20= arranged=20in=20a=20tree-like=20hierarchy.=20=20When=0A+=20=20=20=20=20=20= =20=20summary=20is=20true,=20= statistics=0A+=20=20=20=20=20=20=20=20for=20memory=20contexts=20at=20= levels=201=20and=202=20are=20displayed,=20with=20level=201=0A+=20=20=20=20= =20=20=20=20representing=20the=20root=20node=20(i.e.,=20= TopMemoryContext).=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=20retries=20sets=20the=20= number=20of=20times=20the=20client=20will=0A+=20=20=20=20=20=20=20=20= retry=20to=20get=20updated=20statistics.=20=20The=20sleep=20per=20try=20= is=0A+=20=20=20=20=20=20=20=200.5=20seconds.=20=20= This=20parameter=20can=20be=20increased=20if=20the=0A+=20=20=20=20=20=20=20= =20user=20anticipates=20a=20delay=20in=20the=20response=20from=20the=20= reporting=20process.=0A+=20=20=20=20=20=20=20=20Conversely,=20if=20users=20= are=20frequently=20and=20periodically=20querying=20the=0A+=20=20=20=20=20= =20=20=20process=20for=20statistics,=20or=20if=20there=20are=20= concurrent=20requests=20for=0A+=20=20=20=20=20=20=20=20statistics=20of=20= the=20same=20process,=20lowering=20the=20parameter=20might=20help=0A+=20=20= =20=20=20=20=20=20achieve=20a=20faster=20response.=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=20= receiving=20memory=20context=20statistics=20from=20the=20target=20= process,=20it=0A+=20=20=20=20=20=20=20=20returns=20the=20results=20as=20= one=20row=20per=20context.=20=20If=20all=20the=20contexts=20don't=0A+=20=20= =20=20=20=20=20=20fit=20within=20the=20pre-determined=20size=20limit,=20= the=20remaining=20context=0A+=20=20=20=20=20=20=20=20statistics=20are=20= aggregated=20and=20a=20cumulative=20total=20is=20displayed.=20=20The=0A+=20= =20=20=20=20=20=20=20num_agg_contexts=20column=20= indicates=20the=20number=20of=0A+=20=20=20=20=20=20=20=20contexts=20= aggregated=20in=20the=20displayed=20statistics.=20=20When=0A+=20=20=20=20= =20=20=20=20num_agg_contexts=20is=20= 1=20is=20means=0A+=20=20=20=20=20=20=20=20that=20the=20= context=20statistics=20are=20displayed=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= -28789,6=20+28851,39=20@@=20LOG:=20=20Grand=20total:=201651920=20bytes=20= in=20201=20blocks;=20622360=20free=20(88=20chunks);=201029560=0A=20=20=20= =20=20because=20it=20may=20generate=20a=20large=20number=20of=20log=20= messages.=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=20,=20false,=205)=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/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..362a6dc9528=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-343,6=20+344,8=20@@=20= CreateOrAttachShmemStructs(void)=0A=20=09WaitEventCustomShmemInit();=0A=20= =09InjectionPointShmemInit();=0A=20=09AioShmemInit();=0A+=09= MemCtxShmemInit();=0A+=09MemCtxBackendShmemInit();=0A=20}=0A=20=0A=20/*=0A= diff=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/proc.c=20b/src/backend/storage/lmgr/proc.c=0A= index=20e9ef0fbfe32..41a60a11d2b=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= @@=20-546,6=20+547,13=20@@=20InitProcess(void)=0A=20=09=20*/=0A=20=09= PGSemaphoreReset(MyProc->sem);=0A=20=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=0A+=09=20*=20backend=20if=20requested.=0A+=09=20= */=0A+=09before_shmem_exit(AtProcExit_memstats_dsa_free,=200);=0A+=0A=20=09= /*=0A=20=09=20*=20Arrange=20to=20clean=20up=20at=20backend=20exit.=0A=20=09= =20*/=0A@@=20-720,6=20+728,13=20@@=20InitAuxiliaryProcess(void)=0A=20=09=20= */=0A=20=09PGSemaphoreReset(MyProc->sem);=0A=20=0A+=09/*=0A+=09=20*=20= The=20before=20shmem=20exit=20callback=20frees=20the=20DSA=20memory=20= occupied=20by=20the=0A+=09=20*=20latest=20memory=20context=20statistics=20= that=20could=20be=20published=20by=20this=0A+=09=20*=20process=20if=20= requested.=0A+=09=20*/=0A+=09= before_shmem_exit(AtProcExit_memstats_dsa_free,=200);=0A+=0A=20=09/*=0A=20= =09=20*=20Arrange=20to=20clean=20up=20at=20process=20exit.=0A=20=09=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..ee0e42535b6=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_CTX_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..375509f2551=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,26=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+#include=20"nodes/pg_list.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=20max=20bytes=20for=20showing=20= identifiers=20of=20MemoryContext.=0A=20=20*=20----------=0A=20=20*/=0A=20= #define=20MEMORY_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= MemoryContextBackendState=20*memCtxState=20=3D=20NULL;=0A+struct=20= MemoryContextState=20*memCtxArea=20=3D=20NULL;=0A=20=0A=20/*=0A=20=20*=20= int_list_to_array=0A@@=20-143,24=20+141,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,=20true);=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= +156,44=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.=20If=20missing_ok=20is=0A+=20*=20= false=20then=20execution=20will=20error=20out=20on=20invalid=20context=20= types.=0A+=20*/=0A+const=20char=20*=0A+ContextTypeToString(NodeTag=20= type,=20bool=20missing_ok)=0A+{=0A+=09const=20char=20*context_type;=0A+=0A= +=09switch=20(type)=0A+=09{=0A+=09=09case=20T_AllocSetContext:=0A+=09=09=09= context_type=20=3D=20"AllocSet";=0A+=09=09=09break;=0A+=09=09case=20= T_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=20T_BumpContext:=0A+=09=09=09= context_type=20=3D=20"Bump";=0A+=09=09=09break;=0A+=09=09default:=0A+=09=09= =09if=20(missing_ok)=0A+=09=09=09=09context_type=20=3D=20"???";=0A+=09=09= =09else=0A+=09=09=09=09ereport(ERROR,=0A+=09=09=09=09=09=09= errcode(ERRCODE_UNDEFINED_OBJECT),=0A+=09=09=09=09=09=09errmsg("invalid=20= memory=20context=20type=20specified"));=0A+=09=09=09break;=0A+=09}=0A+=09= return=20(context_type);=0A+}=0A+=0A=20/*=0A=20=20*=20= pg_get_backend_memory_contexts=0A=20=20*=09=09SQL=20SRF=20showing=20= backend=20memory=20context.=0A@@=20-305,3=20+324,358=20@@=20= pg_log_backend_memory_contexts(PG_FUNCTION_ARGS)=0A=20=0A=20=09= PG_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=20for=20max_retries=0A+=20*=20= number=20of=20times,=20which=20is=20defined=20by=20user,=20before=20= giving=20up=20and=0A+=20*=20returning=20previously=20published=20= statistics,=20if=20any.=20If=20no=20previous=20statistics=0A+=20*=20= exist,=20return=20NULL.=0A+=20*/=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=09get_summary=20=3D=20= PG_GETARG_BOOL(1);=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+=09dsa_area=20=20=20*area;=0A+=09= MemoryContextEntry=20*memctx_info;=0A+=09int=09=09=09num_retries=20=3D=20= 0;=0A+=09TimestampTz=20curr_timestamp;=0A+=09int=09=09=09max_retries=20=3D= =20PG_GETARG_INT32(2);=0A+=0A+=09/*=0A+=09=20*=20Only=20superusers=20or=20= users=20with=20pg_read_all_stats=20privileges=20can=20view=20the=0A+=09=20= *=20memory=20context=20statistics=20of=20another=20process.=0A+=09=20*/=0A= +=09if=20(!has_privs_of_role(GetUserId(),=20ROLE_PG_READ_ALL_STATS))=0A+=09= =09ereport(ERROR,=0A+=09=09=09=09= errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),=0A+=09=09=09=09= errmsg("permission=20denied=20to=20extract=20memory=20context=20= statistics"));=0A+=0A+=09/*=0A+=09=20*=20See=20if=20the=20process=20with=20= given=20pid=20is=20a=20backend=20or=20an=20auxiliary=20process=0A+=09=20= *=20and=20remember=20the=20type=20for=20when=20we=20requery=20the=20= process=20later.=0A+=09=20*/=0A+=09proc=20=3D=20BackendPidGetProc(pid);=0A= +=09if=20(proc=20=3D=3D=20NULL)=0A+=09{=0A+=09=09proc=20=3D=20= AuxiliaryPidGetProc(pid);=0A+=09=09proc_is_aux=20=3D=20true;=0A+=09}=0A+=0A= +=09/*=0A+=09=20*=20BackendPidGetProc()=20and=20AuxiliaryPidGetProc()=20= return=20NULL=20if=20the=20pid=0A+=09=20*=20isn't=20valid;=20this=20is=20= however=20not=20a=20problem=20and=20leave=20with=20a=20WARNING.=0A+=09=20= *=20See=20comment=20in=20pg_log_backend_memory_contexts=20for=20a=20= discussion=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=20= a=20loop-through-resultset=20will=20not=20abort=0A+=09=09=20*=20if=20one=20= backend=20terminated=20on=20its=20own=20during=20the=20run.=0A+=09=09=20= */=0A+=09=09ereport(WARNING,=0A+=09=09=09=09(errmsg("PID=20%d=20is=20not=20= a=20PostgreSQL=20server=20process",=20pid)));=0A+=09=09PG_RETURN_NULL();=0A= +=09}=0A+=0A+=09InitMaterializedSRF(fcinfo,=200);=0A+=0A+=09procNumber=20= =3D=20GetNumberFromPGProc(proc);=0A+=0A+=09= LWLockAcquire(&memCtxState[procNumber].lw_lock,=20LW_EXCLUSIVE);=0A+=09= memCtxState[procNumber].get_summary=20=3D=20get_summary;=0A+=09= LWLockRelease(&memCtxState[procNumber].lw_lock);=0A+=0A+=09= curr_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*=20A=20valid=20DSA=20pointer=20isn't=20proof=20that=20= statistics=20are=20available,=20it=20can=0A+=09=20*=20be=20valid=20due=20= to=20previously=20published=20stats.=20Check=20if=20the=20stats=20are=0A= +=09=20*=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=20max_retries=20= *=0A+=09=20*=20MEMSTATS_WAIT_TIMEOUT,=20following=20which=20display=20= old=20statistics=20if=0A+=09=20*=20available=20or=20return=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(&memCtxState[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(memCtxState[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(curr_timestamp,=0A+=09=09=09= =09=09=09=09=09=09=09=09=09=09memCtxState[procNumber].stats_timestamp);=0A= +=0A+=09=09=09if=20= (DsaPointerIsValid(memCtxState[procNumber].memstats_dsa_pointer)=0A+=09=09= =09=09&&=20msecs=20>=200)=0A+=09=09=09=09break;=0A+=09=09}=0A+=09=09= LWLockRelease(&memCtxState[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+#define=20= MEMSTATS_WAIT_TIMEOUT=20500=0A+=0A+=09=09if=20= (ConditionVariableTimedSleep(&memCtxState[procNumber].memctx_cv,=0A+=09=09= =09=09=09=09=09=09=09=09MEMSTATS_WAIT_TIMEOUT,=0A+=09=09=09=09=09=09=09=09= =09=09WAIT_EVENT_MEM_CTX_PUBLISH))=0A+=09=09{=0A+=09=09=09/*=0A+=09=09=09= =20*=20Wait=20for=20max_retries,=20as=20defined=20by=20the=20user.=20If=20= no=20updated=0A+=09=09=09=20*=20statistics=20are=20available=20within=20= the=20wait=20time=20defined=20by=0A+=09=09=09=20*=20max_retries=20then=20= display=20previously=20published=20statistics=20if=0A+=09=09=09=20*=20= there=20are=20any.=20If=20no=20previous=20statistics=20are=20available=20= then=0A+=09=09=09=20*=20return=20NULL.=0A+=09=09=09=20*/=0A+=09=09=09if=20= (num_retries=20>=20max_retries)=0A+=09=09=09{=0A+=09=09=09=09= LWLockAcquire(&memCtxState[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(memCtxState[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(&memCtxState[procNumber].lw_lock);=0A+=09=09=09=09=09= PG_RETURN_NULL();=0A+=09=09=09=09}=0A+=09=09=09}=0A+=09=09=09= ereport(DEBUG1,=0A+=09=09=09=09=09errmsg("timed=20out=20waiting=20for=20= process=20with=20PID=20%d=20to=20publish=20stats,=20retrying",=0A+=09=09=09= =09=09=09=20=20=20pid));=0A+=09=09=09num_retries=20=3D=20num_retries=20+=20= 1;=0A+=09=09}=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20We=20should=20only=20= reach=20here=20with=20a=20valid=20DSA=20handle,=20either=20containing=0A= +=09=20*=20updated=20statistics=20or=20previously=20published=20= statistics=20(identified=20by=0A+=09=20*=20the=20timestamp.=0A+=09=20*/=0A= +=09Assert(memCtxArea->memstats_dsa_handle=20!=3D=20DSA_HANDLE_INVALID);=0A= +=09area=20=3D=20dsa_attach(memCtxArea->memstats_dsa_handle);=0A+=0A+=09= /*=0A+=09=20*=20Backend=20has=20finished=20publishing=20the=20stats,=20= project=20them.=0A+=09=20*/=0A+=09memctx_info=20=3D=20= (MemoryContextEntry=20*)=0A+=09=09dsa_get_address(area,=20= memCtxState[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<=20memCtxState[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(memctx_info[i].name))=0A+=09=09{=0A+=09=09=09name=20=3D= =20(char=20*)=20dsa_get_address(area,=20memctx_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(memctx_info[i].ident))=0A+=09=09{=0A+=09=09=09ident=20= =3D=20(char=20*)=20dsa_get_address(area,=20memctx_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=09if=20= (memctx_info[i].type=20!=3D=20NULL)=0A+=09=09=09values[2]=20=3D=20= CStringGetTextDatum(memctx_info[i].type);=0A+=09=09else=0A+=09=09=09= nulls[2]=20=3D=20true;=0A+=0A+=09=09path_length=20=3D=20= memctx_info[i].path_length;=0A+=09=09path_datum=20=3D=20(Datum=20*)=20= palloc(path_length=20*=20sizeof(Datum));=0A+=09=09if=20= (DsaPointerIsValid(memctx_info[i].path))=0A+=09=09{=0A+=09=09=09path_int=20= =3D=20(int=20*)=20dsa_get_address(area,=20memctx_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(path_length);=20/*=20level=20*/=0A+=09=09values[5]=20=3D=20= Int64GetDatum(memctx_info[i].totalspace);=0A+=09=09values[6]=20=3D=20= Int64GetDatum(memctx_info[i].nblocks);=0A+=09=09values[7]=20=3D=20= Int64GetDatum(memctx_info[i].freespace);=0A+=09=09values[8]=20=3D=20= Int64GetDatum(memctx_info[i].freechunks);=0A+=09=09values[9]=20=3D=20= Int64GetDatum(memctx_info[i].totalspace=20-=0A+=09=09=09=09=09=09=09=09=20= =20memctx_info[i].freespace);=0A+=09=09values[10]=20=3D=20= Int32GetDatum(memctx_info[i].num_agg_stats);=0A+=09=09values[11]=20=3D=20= TimestampTzGetDatum(memCtxState[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(&memCtxState[procNumber].lw_lock);=0A+=0A+=09= ConditionVariableCancelSleep();=0A+=09dsa_detach(area);=0A+=0A+=09= PG_RETURN_NULL();=0A+}=0A+=0A+/*=0A+=20*=20Init=20shared=20memory=20for=20= reporting=20memory=20context=20information.=0A+=20*/=0A+void=0A= +MemCtxBackendShmemInit(void)=0A+{=0A+=09bool=09=09found;=0A+=09Size=09=09= TotalProcs;=0A+=0A+=09TotalProcs=20=3D=20add_size(MaxBackends,=20= NUM_AUXILIARY_PROCS);=0A+=09TotalProcs=20=3D=20add_size(TotalProcs,=20= max_prepared_xacts);=0A+=0A+=09memCtxState=20=3D=20= (MemoryContextBackendState=20*)=0A+=09=09= ShmemInitStruct("MemoryContextBackendState",=0A+=09=09=09=09=09=09= mul_size(TotalProcs,=20sizeof(MemoryContextBackendState)),=0A+=09=09=09=09= =09=09&found);=0A+=0A+=09if=20(!IsUnderPostmaster)=0A+=09{=0A+=09=09= Assert(!found);=0A+=0A+=09=09for=20(int=20i=20=3D=200;=20i=20<=20= TotalProcs;=20i++)=0A+=09=09{=0A+=09=09=09= ConditionVariableInit(&memCtxState[i].memctx_cv);=0A+=0A+=09=09=09= LWLockInitialize(&memCtxState[i].lw_lock,=20LWLockNewTrancheId());=0A+=09= =09=09LWLockRegisterTranche(memCtxState[i].lw_lock.tranche,=0A+=09=09=09=09= =09=09=09=09=20=20"mem_context_backend_stats_reporting");=0A+=0A+=09=09=09= memCtxState[i].memstats_dsa_pointer=20=3D=20InvalidDsaPointer;=0A+=09=09= }=0A+=09}=0A+=09else=0A+=09{=0A+=09=09Assert(found);=0A+=09}=0A+}=0A+=0A= +/*=0A+=20*=20Initialize=20shared=20memory=20for=20displaying=20memory=20= context=20statistics=0A+=20*/=0A+void=0A+MemCtxShmemInit(void)=0A+{=0A+=09= bool=09=09found;=0A+=0A+=09memCtxArea=20=3D=20(MemoryContextState=20*)=0A= +=09=09ShmemInitStruct("MemoryContextState",=20= sizeof(MemoryContextState),=20&found);=0A+=0A+=09if=20= (!IsUnderPostmaster)=0A+=09{=0A+=09=09Assert(!found);=0A+=0A+=09=09= LWLockInitialize(&memCtxArea->lw_lock,=0A+=09=09=09=09=09=09=20= LWLockNewTrancheId());=0A+=09=09= LWLockRegisterTranche(memCtxArea->lw_lock.tranche,=0A+=09=09=09=09=09=09=09= =20=20"mem_context_stats_reporting");=0A+=09=09= memCtxArea->memstats_dsa_handle=20=3D=20DSA_HANDLE_INVALID;=0A+=09}=0A+=09= else=0A+=09{=0A+=09=09Assert(found);=0A+=09}=0A+}=0Adiff=20--git=20= a/src/backend/utils/init/globals.c=20b/src/backend/utils/init/globals.c=0A= index=202152aad97d9..92304a1f124=20100644=0A---=20= a/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/mmgr/mcxt.c=20b/src/backend/utils/mmgr/mcxt.c=0A= index=20d98ae9db6be..f29a282cb5f=20100644=0A---=20= a/src/backend/utils/mmgr/mcxt.c=0A+++=20b/src/backend/utils/mmgr/mcxt.c=0A= @@=20-23,6=20+23,13=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/fd.h"=0A+#include=20"storage/lwlock.h"=0A+#include=20= "storage/dsm.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+142,17=20@@=20static=20= const=20MemoryContextMethods=20mcxt_methods[]=20=3D=20{=0A=20};=0A=20=0A=20= #undef=20BOGUS_MCTX=0A+/*=0A+=20*=20This=20is=20passed=20to=20= MemoryContextStatsInternal=20to=20determine=20whether=0A+=20*=20to=20= print=20context=20statistics=20or=20not=20and=20where=20to=20print=20= them=20logs=20or=0A+=20*=20stderr.=0A+=20*/=0A+typedef=20enum=20= PrintDestination=0A+{=0A+=09PRINT_STATS_TO_STDERR=20=3D=200,=0A+=09= PRINT_STATS_TO_LOGS,=0A+=09PRINT_STATS_NONE=0A+}=09=09=09= PrintDestination;=0A=20=0A=20/*=0A=20=20*=20CurrentMemoryContext=0A@@=20= -162,10=20+180,23=20@@=20static=20void=20= MemoryContextCallResetCallbacks(MemoryContext=20context);=0A=20static=20= void=20MemoryContextStatsInternal(MemoryContext=20context,=20int=20= level,=0A=20=09=09=09=09=09=09=09=09=09=20=20=20int=20max_level,=20int=20= max_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(MemoryContextEntry=20*memctx_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+static=20void=20= compute_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=20bool=20= get_summary);=0A+static=20List=20*compute_context_path(MemoryContext=20= c,=20HTAB=20*context_id_lookup,=0A+=09=09=09=09=09=09=09=09=20=20int=20= max_level);=0A+static=20void=20dsa_free_previous_stats(dsa_area=20*area,=20= int=20total_stats,=0A+=09=09=09=09=09=09=09=09=09dsa_pointer=20= prev_dsa_pointer);=0A=20=0A=20/*=0A=20=20*=20You=20should=20not=20do=20= memory=20allocations=20within=20a=20critical=20section,=20because=0A@@=20= -831,11=20+862,19=20@@=20MemoryContextStatsDetail(MemoryContext=20= context,=0A=20=09=09=09=09=09=09=20bool=20print_to_stderr)=0A=20{=0A=20=09= MemoryContextCounters=20grand_totals;=0A+=09int=09=09=09num_contexts;=0A= +=09PrintDestination=20print_location;=0A=20=0A=20=09= memset(&grand_totals,=200,=20sizeof(grand_totals));=0A=20=0A+=09if=20= (print_to_stderr)=0A+=09=09print_location=20=3D=20PRINT_STATS_TO_STDERR;=0A= +=09else=0A+=09=09print_location=20=3D=20PRINT_STATS_TO_LOGS;=0A+=0A+=09= /*=20num_contexts=20report=20number=20of=20contexts=20aggregated=20in=20= the=20output=20*/=0A=20=09MemoryContextStatsInternal(context,=200,=20= max_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=09fprintf(stderr,=0A@@=20-870,13=20+909,14=20= @@=20MemoryContextStatsDetail(MemoryContext=20context,=0A=20=20*=09=09= One=20recursion=20level=20for=20MemoryContextStats=0A=20=20*=0A=20=20*=20= Print=20stats=20for=20this=20context=20if=20possible,=20but=20in=20any=20= case=20accumulate=20counts=0A-=20*=20into=20*totals=20(if=20not=20NULL).=0A= +=20*=20into=20*totals=20(if=20not=20NULL).=20The=20callers=20should=20= make=20sure=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,508=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=20get_summary=20is=20true,=20= we=20capture=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= MemoryContextEntry=20*meminfo;=0A+=09bool=09=09get_summary=20=3D=20= false;=0A+=09dsa_area=20=20=20*area=20=3D=20NULL;=0A+=09int=09=09=09= max_stats;=0A+=09int=09=09=09idx=20=3D=20MyProcNumber;=0A+=09int=09=09=09= stats_count=20=3D=200;=0A+=09MemoryContextCounters=20stat;=0A+=09int=09=09= =09num_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(MemoryContextId);=0A+=09ctl.hcxt=20=3D=20CurrentMemoryContext;=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=20(MAX_SEGMENTS_PER_BACKEND=20*=20= DSA_DEFAULT_INIT_SEGMENT_SIZE)=0A+=09=09/=20= (MAX_MEMORY_CONTEXT_STATS_SIZE);=0A+=09= LWLockAcquire(&memCtxState[idx].lw_lock,=20LW_EXCLUSIVE);=0A+=09= get_summary=20=3D=20memCtxState[idx].get_summary;=0A+=09= LWLockRelease(&memCtxState[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= get_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_count=20=3D=20Min(stats_count,=20= max_stats);=0A+=0A+=09LWLockAcquire(&memCtxArea->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= (memCtxArea->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(memCtxArea->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= memCtxArea->memstats_dsa_handle=20=3D=20handle;=0A+=09}=0A+=0A+=09/*=0A+=09= =20*=20If=20DSA=20exists,=20created=20by=20another=20process=20= publishing=20statistics,=20or=20by=0A+=09=20*=20the=20previous=20= execution=20of=20this=20function=20by=20this=20process,=20attach=20to=20= it.=0A+=09=20*/=0A+=09else=20if=20(area=20=3D=3D=20NULL)=0A+=09{=0A+=09=09= MemoryContext=20oldcontext=20=3D=20CurrentMemoryContext;=0A+=0A+=09=09= MemoryContextSwitchTo(TopMemoryContext);=0A+=09=09area=20=3D=20= dsa_attach(memCtxArea->memstats_dsa_handle);=0A+=09=09= MemoryContextSwitchTo(oldcontext);=0A+=09=09dsa_pin_mapping(area);=0A+=09= }=0A+=09LWLockRelease(&memCtxArea->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(&memCtxState[idx].lw_lock,=20LW_EXCLUSIVE);=0A+=09= memCtxState[idx].proc_id=20=3D=20MyProcPid;=0A+=0A+=09if=20= (DsaPointerIsValid(memCtxState[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= dsa_free_previous_stats(area,=20memCtxState[idx].total_stats,=0A+=09=09=09= =09=09=09=09=09memCtxState[idx].memstats_dsa_pointer);=0A+=0A+=09=09= dsa_free(area,=20memCtxState[idx].memstats_dsa_pointer);=0A+=09=09= memCtxState[idx].memstats_dsa_pointer=20=3D=20InvalidDsaPointer;=0A+=09}=0A= +=09memCtxState[idx].memstats_dsa_pointer=20=3D=0A+=09=09= dsa_allocate0(area,=20stats_count=20*=20sizeof(MemoryContextEntry));=0A+=0A= +=09meminfo=20=3D=20(MemoryContextEntry=20*)=0A+=09=09= dsa_get_address(area,=20memCtxState[idx].memstats_dsa_pointer);=0A+=0A+=09= if=20(get_summary)=0A+=09{=0A+=09=09int=09=09=09ctx_id=20=3D=200;=0A+=09=09= List=09=20=20=20*path=20=3D=20NIL;=0A+=0A+=09=09/*=20Copy=20= TopMemoryContext=20statistics=20to=20DSA=20*/=0A+=09=09memset(&stat,=20= 0,=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=20lcons_int(1,=20path);=0A+=09=09= PublishMemoryContext(meminfo,=20ctx_id,=20TopMemoryContext,=20path,=20= stat,=0A+=09=09=09=09=09=09=09=201,=20area);=0A+=09=09ctx_id=20=3D=20= ctx_id=20+=201;=0A+=0A+=09=09/*=0A+=09=09=20*=20Copy=20statistics=20for=20= each=20of=20TopMemoryContexts=20children.=09This=0A+=09=09=20*=20= includes=20statistics=20of=20all=20of=20their=20children=20upto=20level=20= 100.=0A+=09=09=20*/=0A+=09=09for=20(MemoryContext=20c=20=3D=20= TopMemoryContext->firstchild;=20c=20!=3D=20NULL;=0A+=09=09=09=20c=20=3D=20= c->nextchild)=0A+=09=09{=0A+=09=09=09MemoryContextCounters=20= grand_totals;=0A+=09=09=09int=09=09=09num_contexts=20=3D=200;=0A+=09=09=09= int=09=09=09level=20=3D=200;=0A+=0A+=09=09=09path=20=3D=20NIL;=0A+=09=09=09= memset(&grand_totals,=200,=20sizeof(grand_totals));=0A+=0A+=09=09=09= MemoryContextStatsInternal(c,=20level,=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=20compute_context_path(c,=20context_id_lookup,=20= 100);=0A+=0A+=09=09=09PublishMemoryContext(meminfo,=20ctx_id,=20c,=20= path,=0A+=09=09=09=09=09=09=09=09=20grand_totals,=20num_contexts,=20= area);=0A+=09=09=09ctx_id=20=3D=20ctx_id=20+=201;=0A+=09=09}=0A+=09=09= memCtxState[idx].total_stats=20=3D=20ctx_id;=0A+=09=09goto=20cleanup;=0A= +=09}=0A+=0A+=09foreach_ptr(MemoryContextData,=20cur,=20contexts)=0A+=09= {=0A+=09=09List=09=20=20=20*path=20=3D=20NIL;=0A+=09=09char=09=20=20=20= *name;=0A+=0A+=09=09/*=0A+=09=09=20*=20Figure=20out=20the=20transient=20= context_id=20of=20this=20context=20and=20each=20of=20its=0A+=09=09=20*=20= ancestors,=20to=20compute=20a=20path=20for=20this=20context.=0A+=09=09=20= */=0A+=09=09path=20=3D=20compute_context_path(cur,=20context_id_lookup,=20= 100);=0A+=0A+=09=09if=20(context_id=20<=3D=20(max_stats=20-=202))=0A+=09=09= {=0A+=09=09=09/*=20Examine=20the=20context=20stats=20*/=0A+=09=09=09= memset(&stat,=200,=20sizeof(stat));=0A+=09=09=09(*cur->methods->stats)=20= (cur,=20NULL,=20NULL,=20&stat,=20true);=0A+=09=09=09/*=20Copy=20= statistics=20to=20DSA=20memory=20*/=0A+=09=09=09= PublishMemoryContext(meminfo,=20context_id,=20cur,=20path,=20stat,=201,=20= area);=0A+=09=09}=0A+=09=09else=0A+=09=09{=0A+=09=09=09/*=20Examine=20= the=20context=20stats=20*/=0A+=09=09=09memset(&stat,=200,=20= sizeof(stat));=0A+=09=09=09(*cur->methods->stats)=20(cur,=20NULL,=20= NULL,=20&stat,=20true);=0A+=0A+=09=09=09meminfo[max_stats=20-=20= 1].totalspace=20+=3D=20stat.totalspace;=0A+=09=09=09meminfo[max_stats=20= -=201].nblocks=20+=3D=20stat.nblocks;=0A+=09=09=09meminfo[max_stats=20-=20= 1].freespace=20+=3D=20stat.freespace;=0A+=09=09=09meminfo[max_stats=20-=20= 1].freechunks=20+=3D=20stat.freechunks;=0A+=09=09}=0A+=0A+=09=09/*=0A+=09= =09=20*=20DSA=20max=20limit=20per=20process=20is=20reached,=20write=20= aggregate=20of=20the=0A+=09=09=20*=20remaining=20statistics.=0A+=09=09=20= */=0A+=09=09if=20(context_id=20=3D=3D=20(max_stats=20-=202)=20&&=20= context_id=20<=20(stats_count=20-=201))=0A+=09=09{=0A+=09=09=09= num_individual_stats=20=3D=20context_id=20+=201;=0A+=09=09=09= meminfo[max_stats=20-=201].name=20=3D=20dsa_allocate0(area,=2017);=0A+=09= =09=09name=20=3D=20dsa_get_address(area,=20meminfo[max_stats=20-=20= 1].name);=0A+=09=09=09strncpy(name,=20"Remaining=20Totals",=2016);=0A+=09= =09=09meminfo[max_stats=20-=201].ident=20=3D=20InvalidDsaPointer;=0A+=09=09= =09meminfo[max_stats=20-=201].path=20=3D=20InvalidDsaPointer;=0A+=09=09=09= meminfo[max_stats=20-=201].type=20=3D=20NULL;=0A+=09=09}=0A+=09=09= context_id++;=0A+=09}=0A+=09/*=20Statistics=20are=20not=20aggregated,=20= i.e=20individual=20statistics=20reported=20*/=0A+=09if=20(context_id=20<=20= (max_stats=20-=202))=0A+=09{=0A+=09=09memCtxState[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=09memCtxState[idx].total_stats=20= =3D=20num_individual_stats=20+=201;=0A+=09}=0A+=0A+cleanup:=0A+=0A+=09/*=0A= +=09=20*=20Signal=20all=20the=20waiting=20client=20backends=20after=20= copying=20all=20the=20statistics=0A+=09=20*/=0A+=09= memCtxState[idx].stats_timestamp=20=3D=20GetCurrentTimestamp();=0A+=09= LWLockRelease(&memCtxState[idx].lw_lock);=0A+=09= ConditionVariableBroadcast(&memCtxState[idx].memctx_cv);=0A+=09= hash_destroy(context_id_lookup);=0A+=09dsa_detach(area);=0A+}=0A+=0A+/*=0A= +=20*=20compute_context_path=0A+=20*=0A+=20*=20Append=20the=20transient=20= context_id=20of=20this=20context=20and=20each=20of=20its=20ancestors=0A+=20= *=20to=20a=20list,=20in=20order=20to=20compute=20a=20path.=0A+=20*/=0A= +static=20List=20*=0A+compute_context_path(MemoryContext=20c,=20HTAB=20= *context_id_lookup,=20int=20max_level)=0A+{=0A+=09bool=09=09found;=0A+=09= List=09=20=20=20*path=20=3D=20NIL;=0A+=09List=09=20=20=20*tmp=20=3D=20= NIL;=0A+=0A+=09for=20(MemoryContext=20cur_context=20=3D=20c;=20= cur_context=20!=3D=20NULL;=20cur_context=20=3D=20cur_context->parent)=0A= +=09{=0A+=09=09MemoryContextId=20*cur_entry;=0A+=0A+=09=09cur_entry=20=3D=20= hash_search(context_id_lookup,=20&cur_context,=20HASH_FIND,=20&found);=0A= +=0A+=09=09if=20(!found)=0A+=09=09=09elog(ERROR,=20"hash=20table=20= corrupted,=20can't=20construct=20path=20value");=0A+=0A+=09=09path=20=3D=20= lcons_int(cur_entry->context_id,=20path);=0A+=09}=0A+=0A+=09if=20= (list_length(path)=20>=20max_level)=0A+=09{=0A+=09=09tmp=20=3D=20= list_copy_head(path,=20max_level);=0A+=09=09list_free(path);=0A+=09=09= path=20=3D=20tmp;=0A+=09}=0A+=0A+=09return=20path;=0A+}=0A+=0A+/*=0A+=20= *=20Return=20the=20number=20of=20contexts=20allocated=20currently=20by=20= the=20backend=0A+=20*=20Assign=20context=20ids=20to=20each=20of=20the=20= contexts.=0A+=20*/=0A+static=20void=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=20get_summary)=0A+{=0A+=09foreach_ptr(MemoryContextData,=20cur,=20= contexts)=0A+=09{=0A+=09=09MemoryContextId=20*entry;=0A+=09=09bool=09=09= found;=0A+=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=09Assert(!found);=0A+=0A+=09=09/*=20= context=20id=20starts=20with=201=20*/=0A+=09=09entry->context_id=20=3D=20= (++(*stats_count));=0A+=0A+=09=09/*=20Append=20the=20children=20of=20the=20= current=20context=20to=20the=20main=20list.=20*/=0A+=09=09for=20= (MemoryContext=20c=20=3D=20cur->firstchild;=20c=20!=3D=20NULL;=20c=20=3D=20= c->nextchild)=0A+=09=09{=0A+=09=09=09if=20(get_summary)=0A+=09=09=09{=0A= +=09=09=09=09entry=20=3D=20(MemoryContextId=20*)=20= hash_search(context_id_lookup,=20&c,=0A+=09=09=09=09=09=09=09=09=09=09=09= =09=09=09HASH_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=20only=20the=20first=20two=20level=20= (from=20top)=20contexts=20are=0A+=09=09=20*=20displayed=0A+=09=09=20*/=0A= +=09=09if=20(get_summary)=0A+=09=09=09break;=0A+=09}=0A+}=0A+=0A+/*=0A+=20= *=20PublishMemoryContext=0A+=20*=0A+=20*=20Copy=20the=20memory=20context=20= statistics=20of=20a=20single=20context=20to=20a=20DSA=20memory=0A+=20*/=0A= +static=20void=0A+PublishMemoryContext(MemoryContextEntry=20= *memctx_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)=0A+{=0A= +=09const=20char=09=20=20=20*ident=20=3D=20context->ident;=0A+=09const=20= char=09=20=20=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=0A+=09=20*=20with=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=09namelen=20=3D=20= strlen(name);=0A+=09=09char=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= memctx_info[curr_id].name=20=3D=20dsa_allocate0(area,=20namelen=20+=20= 1);=0A+=09=09nameptr=20=3D=20(char=20*)=20dsa_get_address(area,=20= memctx_info[curr_id].name);=0A+=09=09strlcpy(nameptr,=20name,=20namelen=20= +=201);=0A+=09}=0A+=09else=0A+=09=09memctx_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=09idlen=20=3D=20strlen(context->ident);=0A= +=09=09char=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= memctx_info[curr_id].ident=20=3D=20dsa_allocate0(area,=20idlen=20+=201);=0A= +=09=09identptr=20=3D=20(char=20*)=20dsa_get_address(area,=20= memctx_info[curr_id].ident);=0A+=09=09strlcpy(identptr,=20ident,=20idlen=20= +=201);=0A+=09}=0A+=09else=0A+=09=09memctx_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= =09memctx_info[curr_id].path=20=3D=20InvalidDsaPointer;=0A+=09else=0A+=09= {=0A+=09=09memctx_info[curr_id].path_length=20=3D=20list_length(path);=0A= +=09=09memctx_info[curr_id].path=20=3D=20dsa_allocate0(area,=0A+=09=09=09= =09=09=09=09=09=09=09=09=09=20=20memctx_info[curr_id].path_length=20*=20= sizeof(int));=0A+=09=09path_list=20=3D=20(int=20*)=20= dsa_get_address(area,=20memctx_info[curr_id].path);=0A+=09=09= foreach_int(i,=20path)=0A+=09=09=09path_list[foreach_current_index(i)]=20= =3D=20i;=0A+=09}=0A+=09memctx_info[curr_id].type=20=3D=20= ContextTypeToString(context->type,=20true);=0A+=09= memctx_info[curr_id].totalspace=20=3D=20stat.totalspace;=0A+=09= memctx_info[curr_id].nblocks=20=3D=20stat.nblocks;=0A+=09= memctx_info[curr_id].freespace=20=3D=20stat.freespace;=0A+=09= memctx_info[curr_id].freechunks=20=3D=20stat.freechunks;=0A+=09= memctx_info[curr_id].num_agg_stats=20=3D=20num_contexts;=0A+}=0A+=0A+/*=0A= +=20*=20dsa_free_previous_stats=0A+=20*=0A+=20*=20Worker=20for=20freeing=20= resources=20from=20a=20MemoryContextEntry.=20=20Callers=20are=0A+=20*=20= responsible=20for=20ensuring=20that=20the=20DSA=20pointer=20is=20valid.=0A= +=20*/=0A+static=20void=0A+dsa_free_previous_stats(dsa_area=20*area,=20= int=20total_stats,=0A+=09=09=09=09=09=09dsa_pointer=20prev_dsa_pointer)=0A= +{=0A+=09MemoryContextEntry=20*meminfo;=0A+=0A+=09meminfo=20=3D=20= (MemoryContextEntry=20*)=20dsa_get_address(area,=20prev_dsa_pointer);=0A= +=09Assert(meminfo=20!=3D=20NULL);=0A+=09for=20(int=20i=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+=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_dsa_free(int=20code,=20= Datum=20arg)=0A+{=0A+=09int=09=09=09idx=20=3D=20MyProcNumber;=0A+=09= dsm_segment=20*dsm_seg=20=3D=20NULL;=0A+=09dsa_area=20=20=20*area=20=3D=20= NULL;=0A+=0A+=09if=20(memCtxArea->memstats_dsa_handle=20=3D=3D=20= DSA_HANDLE_INVALID)=0A+=09=09return;=0A+=0A+=09dsm_seg=20=3D=20= dsm_find_mapping(memCtxArea->memstats_dsa_handle);=0A+=0A+=09= LWLockAcquire(&memCtxState[idx].lw_lock,=20LW_EXCLUSIVE);=0A+=0A+=09if=20= (!DsaPointerIsValid(memCtxState[idx].memstats_dsa_pointer))=0A+=09{=0A+=09= =09LWLockRelease(&memCtxState[idx].lw_lock);=0A+=09=09return;=0A+=09}=0A= +=0A+=09/*=20If=20the=20dsm=20mapping=20could=20not=20be=20found,=20= attach=20to=20the=20area=20*/=0A+=09if=20(dsm_seg=20!=3D=20NULL)=0A+=09=09= return;=0A+=09area=20=3D=20dsa_attach(memCtxArea->memstats_dsa_handle);=0A= +=0A+=09/*=0A+=09=20*=20Free=20the=20memory=20context=20statistics,=20= free=20the=20name,=20ident=20and=20path=0A+=09=20*=20pointers=20before=20= freeing=20the=20pointer=20that=20contains=20these=20pointers=20and=0A+=09= =20*=20integer=20statistics.=0A+=09=20*/=0A+=09= dsa_free_previous_stats(area,=20memCtxState[idx].total_stats,=0A+=09=09=09= =09=09=09=09memCtxState[idx].memstats_dsa_pointer);=0A+=09dsa_free(area,=20= memCtxState[idx].memstats_dsa_pointer);=0A+=09= memCtxState[idx].memstats_dsa_pointer=20=3D=20InvalidDsaPointer;=0A+=0A+=09= dsa_detach(area);=0A+=09LWLockRelease(&memCtxState[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=205d5be8ba4e1..1f7a2c7ce41=20100644=0A---=20= a/src/include/catalog/pg_proc.dat=0A+++=20= b/src/include/catalog/pg_proc.dat=0A@@=20-8559,6=20+8559,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=20int4',=0A+=20=20proallargtypes=20=3D>=20= '{int4,bool,int4,text,text,text,_int4,int4,int8,int8,int8,int8,int8,int4,t= imestamptz}',=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/procsignal.h=20b/src/include/storage/procsignal.h=0A= index=20016dfd9b3f6..cfe14631445=20100644=0A---=20= a/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..33ee288736d=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,22=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=20Mb)=20= of=20DSA=20area=20per=20process=20*/=0A+#define=20= MAX_SEGMENTS_PER_BACKEND=201=0A+/*=0A+=20*=20Maximum=20size=20per=20= context.=20Actual=20size=20may=20be=20lower=20as=20this=20assumes=20the=20= worst=0A+=20*=20case=20of=20deepest=20path=20and=20longest=20identifiers=20= (name=20and=20ident,=20thus=20the=0A+=20*=20multiplication=20by=202).=20= The=20path=20depth=20is=20limited=20to=20100=20like=20for=20memory=0A+=20= *=20context=20logging.=0A+=20*/=0A+#define=20= MAX_MEMORY_CONTEXT_STATS_SIZE=20sizeof(MemoryContextEntry)=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=20top-level=20memory=20contexts.=0A@@=20= -319,4=20+338,65=20@@=20pg_memory_is_all_zeros(const=20void=20*ptr,=20= size_t=20len)=0A=20=09return=20true;=0A=20}=0A=20=0A+/*=20Dynamic=20= shared=20memory=20state=20for=20statistics=20per=20context=20*/=0A= +typedef=20struct=20MemoryContextEntry=0A+{=0A+=09dsa_pointer=20name;=0A= +=09dsa_pointer=20ident;=0A+=09dsa_pointer=20path;=0A+=09const=20char=20= *type;=0A+=09int=09=09=09path_length;=0A+=09int64=09=09totalspace;=0A+=09= int64=09=09nblocks;=0A+=09int64=09=09freespace;=0A+=09int64=09=09= freechunks;=0A+=09int=09=09=09num_agg_stats;=0A+}=20MemoryContextEntry;=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=20MemoryContextState=0A+{=0A+=09dsa_handle=09= memstats_dsa_handle;=0A+=09LWLock=09=09lw_lock;=0A+}=20= MemoryContextState;=0A+=0A+/*=0A+=20*=20Per=20backend=20static=20shared=20= memory=20state=20for=20memory=20context=20statistics=0A+=20*=20= reporting.=0A+=20*/=0A+typedef=20struct=20MemoryContextBackendState=0A+{=0A= +=09ConditionVariable=20memctx_cv;=0A+=09LWLock=09=09lw_lock;=0A+=09int=09= =09=09proc_id;=0A+=09int=09=09=09total_stats;=0A+=09bool=09=09= get_summary;=0A+=09dsa_pointer=20memstats_dsa_pointer;=0A+=09TimestampTz=20= stats_timestamp;=0A+}=20MemoryContextBackendState;=0A+=0A+=0A+/*=0A+=20*=20= Used=20for=20storage=20of=20transient=20identifiers=20for=20= pg_get_backend_memory_contexts=0A+=20*/=0A+typedef=20struct=20= MemoryContextId=0A+{=0A+=09MemoryContext=20context;=0A+=09int=09=09=09= context_id;=0A+}=20MemoryContextId;=0A+=0A+extern=20PGDLLIMPORT=20= MemoryContextBackendState=20*memCtxState;=0A+extern=20PGDLLIMPORT=20= MemoryContextState=20*memCtxArea;=0A+extern=20void=20= ProcessGetMemoryContextInterrupt(void);=0A+extern=20const=20char=20= *ContextTypeToString(NodeTag=20type,=20bool=20missing_ok);=0A+extern=20= void=20HandleGetMemoryContextInterrupt(void);=0A+extern=20void=20= MemCtxShmemInit(void);=0A+extern=20void=20MemCtxBackendShmemInit(void);=0A= +extern=20void=20AtProcExit_memstats_dsa_free(int=20code,=20Datum=20= arg);=0A+=0A=20#endif=09=09=09=09=09=09=09/*=20MEMUTILS_H=20*/=0Adiff=20= --git=20a/src/test/regress/expected/sysviews.out=20= b/src/test/regress/expected/sysviews.out=0Aindex=20= 83228cfca29..dca20ae1a26=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,17=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=20launcher_pid=20= int;=0A+=20=20=20=20r=20RECORD;=0A+BEGIN=0A+=20=20=20=20=20=20=20=20= SELECT=20pid=20from=20pg_stat_activity=20where=20= backend_type=3D'autovacuum=20launcher'=0A+=09=20INTO=20launcher_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(launcher_pid,=20false,=20= 20)=0A+=09=20where=20path=20=3D=20'{1}'=20into=20r;=0A+=09RAISE=20NOTICE=20= '%',=20r;=0A+END=20$$;=0A+NOTICE:=20=20(AllocSet,TopMemoryContext,)=0A= diff=20--git=20a/src/test/regress/sql/sysviews.sql=20= b/src/test/regress/sql/sysviews.sql=0Aindex=2066179f026b3..4767351d4e2=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,17=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=20launcher_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'autovacuum=20launcher'=0A+=09=20= INTO=20launcher_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(launcher_pid,=20false,=2020)=0A+=09=20= where=20path=20=3D=20'{1}'=20into=20r;=0A+=09RAISE=20NOTICE=20'%',=20r;=0A= +END=20$$;=0Adiff=20--git=20a/src/tools/pgindent/typedefs.list=20= b/src/tools/pgindent/typedefs.list=0Aindex=200c81d03950d..864a0d2b56b=20= 100644=0A---=20a/src/tools/pgindent/typedefs.list=0A+++=20= b/src/tools/pgindent/typedefs.list=0A@@=20-1662,12=20+1662,16=20@@=20= MemoizeState=0A=20MemoizeTuple=0A=20MemoryChunk=0A=20MemoryContext=0A= +MemoryContextBackendState=0A=20MemoryContextCallback=0A=20= MemoryContextCallbackFunction=0A=20MemoryContextCounters=0A=20= MemoryContextData=0A+MemoryContextEntry=0A+MemoryContextId=0A=20= MemoryContextMethodID=0A=20MemoryContextMethods=0A+MemoryContextState=0A=20= MemoryStatsPrintFunc=0A=20MergeAction=0A=20MergeActionState=0A--=20=0A= 2.39.3=20(Apple=20Git-146)=0A=0A= --Apple-Mail=_B78FFBF9-35A3-42C7-B47F-7EFB12A5C22E--