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 1tx52y-002bi6-UN for pgsql-hackers@arkaria.postgresql.org; Tue, 25 Mar 2025 14:14:30 +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 1tx52x-0050h0-Lr for pgsql-hackers@arkaria.postgresql.org; Tue, 25 Mar 2025 14:14:27 +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 1tx52w-0050gs-Ni for pgsql-hackers@lists.postgresql.org; Tue, 25 Mar 2025 14:14:27 +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 1tx52t-0013PT-03 for pgsql-hackers@postgresql.org; Tue, 25 Mar 2025 14:14:25 +0000 Received: from s807.loopia.se (localhost [127.0.0.1]) by s807.loopia.se (Postfix) with ESMTP id 924412B8E3C for ; Tue, 25 Mar 2025 15:14:19 +0100 (CET) Received: from s934.loopia.se (unknown [172.22.191.5]) by s807.loopia.se (Postfix) with ESMTP id 806502B88FC; Tue, 25 Mar 2025 15:14:19 +0100 (CET) Received: from s473.loopia.se (unknown [172.22.191.5]) by s934.loopia.se (Postfix) with ESMTP id 7D63F7CEA66; Tue, 25 Mar 2025 15:14:19 +0100 (CET) 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: s473.loopia.se (amavisd-new); dkim=pass (2048-bit key) header.d=yesql.se Received: from s934.loopia.se ([172.22.191.6]) by s473.loopia.se (s473.loopia.se [172.22.190.13]) (amavisd-new, port 10024) with UTF8LMTP id LJ3X3SiQNUMa; Tue, 25 Mar 2025 15:14:18 +0100 (CET) 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 s934.loopia.se (Postfix) with ESMTPSA id 8C2937CEA50; Tue, 25 Mar 2025 15:14:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yesql.se; s=loopiadkim1707475645; t=1742912058; bh=WUR2CMdpkxJszsKFSbVDrfksR5k7Q2y7qNhAqej9ysA=; h=From:Subject:Date:In-Reply-To:Cc:To:References; b=F5ZcUkl1c5GD5P8h/33W+t3/vi2XYlXGTe0ua4ElERqKTiuVq2JiCcCnaoef4LaCa JMEf+yBcB6XC+/8fC2Hpw0Sx3qDk2hr0pGvyIqIZLztWk+uLQH4KTCiB3ybLqIuwve /LnVx0AgWRyq5NiW2VcbX/+OofXjbKnHAxwfeNmLS60onDc95q7BeSqTlr/dKhcwu+ fNMW2UuAqSRPheGJZxL9yt8pChVyT8LjdLD/Yt9JX/T6wNYZ2TTJE8RwhDWKyXkHE2 GJqLbdOatCGUUU5chC7ur3FrtlcBDq3AqaPab4Zy7IO6tlvXrP5h1ApLJz6csRCpsX GYV/K87oIHWcg== From: Daniel Gustafsson Message-Id: Content-Type: multipart/mixed; boundary="Apple-Mail=_85513A8F-54AD-4F62-B91C-5F6D88A33786" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3776.700.51.11.1\)) Subject: Re: Enhancing Memory Context Statistics Reporting Date: Tue, 25 Mar 2025 15:14:08 +0100 In-Reply-To: Cc: Ashutosh Bapat , Alexander Korotkov , Tomas Vondra , 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=_85513A8F-54AD-4F62-B91C-5F6D88A33786 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii > On 20 Mar 2025, at 08:39, Rahila Syed wrote: Thanks for the new version, I believe this will be a welcome tool in the debugging toolbox. I took a cleanup pass over the docs with among others the below changes: * You had broken the text in paragraphs, but without tags they = are rendered as a single blob of text so added that. * Removed the "(PID)" explanation as process id is used elsewhere on = the same page already without explanation. * Added markup on PostgreSQL * Added markup on paramater values * Switched the example query output to use \x * Added a note on when pg_backend_memory_contexts is a better choice The paragraphs need some re-indenting to avoid too long lines, but I = opted out of doing so here to make reviewing the changes easier. A few comments on the code (all comments are performed in 0003 attached = here which also has smaller cleanups wrt indentation, code style etc): +#include I don't think we need this, maybe it was from an earlier version of the = patch? +MEM_CTX_PUBLISH "Waiting for backend to publish memory information." I wonder if this should really be "process" and not backend? + default: + context_type =3D "???"; + break; In ContextTypeToString() I'm having second thoughts about this, there = shouldn't be any legitimate use-case of passing a nodetag this function which = would fail MemoryContextIsValid(). I wonder if we aren't helping callers more by = erroring out rather than silently returning an unknown? I haven't changed this = but maybe we should to set the API right from the start? + * if the process has more memory contexts than that can fit in the = allocated s/than that can/than what can/? + errmsg("memory context statistics privilege error")); Similar checks elsewhere in the tree mostly use "permission denied to = .." so I think we should adopt that here as well. + LWLockAcquire(&memCtxState[procNumber].lw_lock, LW_EXCLUSIVE); + msecs =3D + TimestampDifferenceMilliseconds(curr_timestamp, + = memCtxState[procNumber].stats_timestamp); Since we only want to consider the stats if they are from the current = process, we can delay checking the time difference until after we've checked the = pid and thus reduce the amount of time we hold the lock in the error case. + /* + * Recheck the state of the backend before sleeping on the = condition + * variable + */ + proc =3D BackendPidGetProc(pid); Here we are really rechecking that the process is still alive, but I = wonder if we should take the opportunity to ensure that the type is what we expect = it to be? If the pid has moved from being a backend to an aux proc or vice = versa we really don't want to go on. + ereport(WARNING, + errmsg("PID %d is not a PostgreSQL server process", + pid)); I wonder if we should differentiate between the warnings? When we hit = this in the loop the errmsg is describing a slightly different case. I did = leave it for now, but it's food for thought if we should perhaps reword this one. + ereport(LOG, + errmsg("Wait for %d process to publish stats timed out, = trying again", + pid)); This should probably by DEBUG1, in a congested cluster it might cause a = fair bit of logging which isn't really helping the user. Also, nitpick, = errmsg starts with a lowercase letter. +static Size +MemCtxShmemSize(void) We don't really need this function anymore and keeping it separate we = risk it going out of sync with the matching calcuation in = MemCtxBackendShmemInit, so I think we should condense into one. else { + Assert(print_location =3D=3D PRINT_STATS_NONE); Rather than an if-then-else and an assert we can use a switch statement = without a default, this way we'll automatically get a warning if a value is = missed. + ereport(LOG, + errmsg("hash table corrupted, can't construct path = value")); I know you switched from elog(LOG.. to ereport(LOG.. but I still think = a LOG entry stating corruption isn't helpful, it's not actionable for the = user. Given that it's a case that shouldn't happen I wonder if we should = downgrade it to an Assert(false) and potentially a DEBUG1? -- Daniel Gustafsson --Apple-Mail=_85513A8F-54AD-4F62-B91C-5F6D88A33786 Content-Disposition: attachment; filename=v19-0001-Preparatory-changes-for-reporting-memory-context.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v19-0001-Preparatory-changes-for-reporting-memory-context.patch" Content-Transfer-Encoding: quoted-printable =46rom=20ba6368a9db0e1f420897cca302ed2a80c94f2ca1=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Rahila=20Syed=20=0A= Date:=20Mon,=203=20Feb=202025=2015:33:19=20+0530=0ASubject:=20[PATCH=20= v19=201/3]=20Preparatory=20changes=20for=20reporting=20memory=20context=0A= =20statistics=0A=0AEnsure=20that=20MemoryContextStatsInternal=20can=20= return=20number=20of=0Acontexts.=20Also,=20provide=20an=20option=20in=20= MemoryContextStatsInternal=0Ato=20return=20without=20printing=20stats=20= to=20either=20stderr=20or=20logs.=0A---=0A=20= src/backend/utils/mmgr/mcxt.c=20|=2065=20= +++++++++++++++++++++++++++++------=0A=201=20file=20changed,=2055=20= insertions(+),=2010=20deletions(-)=0A=0Adiff=20--git=20= a/src/backend/utils/mmgr/mcxt.c=20b/src/backend/utils/mmgr/mcxt.c=0A= index=2091060de0ab7..34cdcdf2fd3=20100644=0A---=20= a/src/backend/utils/mmgr/mcxt.c=0A+++=20b/src/backend/utils/mmgr/mcxt.c=0A= @@=20-135,6=20+135,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= -162,7=20+173,7=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,=20int=20*num_contexts);=0A=20static=20= void=20MemoryContextStatsPrint(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@@=20-831,11=20= +842,19=20@@=20MemoryContextStatsDetail(MemoryContext=20context,=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-876,18=20+895,43=20= @@=20static=20void=0A=20MemoryContextStatsInternal(MemoryContext=20= context,=20int=20level,=0A=20=09=09=09=09=09=09=20=20=20int=20max_level,=20= int=20max_children,=0A=20=09=09=09=09=09=09=20=20=20= MemoryContextCounters=20*totals,=0A-=09=09=09=09=09=09=20=20=20bool=20= print_to_stderr)=0A+=09=09=09=09=09=09=20=20=20PrintDestination=20= print_location,=20int=20*num_contexts)=0A=20{=0A=20=09MemoryContext=20= child;=0A=20=09int=09=09=09ichild;=0A+=09bool=09=09print_to_stderr=20=3D=20= true;=0A=20=0A+=09check_stack_depth();=0A=20=09= Assert(MemoryContextIsValid(context));=0A=20=0A-=09/*=20Examine=20the=20= context=20itself=20*/=0A-=09context->methods->stats(context,=0A-=09=09=09= =09=09=09=09MemoryContextStatsPrint,=0A-=09=09=09=09=09=09=09&level,=0A-=09= =09=09=09=09=09=09totals,=20print_to_stderr);=0A+=09if=20(print_location=20= =3D=3D=20PRINT_STATS_TO_STDERR)=0A+=09=09print_to_stderr=20=3D=20true;=0A= +=09else=20if=20(print_location=20=3D=3D=20PRINT_STATS_TO_LOGS)=0A+=09=09= print_to_stderr=20=3D=20false;=0A+=0A+=09if=20(print_location=20!=3D=20= PRINT_STATS_NONE)=0A+=09{=0A+=09=09/*=20Examine=20the=20context=20itself=20= */=0A+=09=09context->methods->stats(context,=0A+=09=09=09=09=09=09=09=09= MemoryContextStatsPrint,=0A+=09=09=09=09=09=09=09=09&level,=0A+=09=09=09=09= =09=09=09=09totals,=20print_to_stderr);=0A+=09}=0A+=0A+=09/*=0A+=09=20*=20= Do=20not=20print=20the=20statistics=20if=20print_to_stderr=20is=20= PRINT_STATS_NONE,=0A+=09=20*=20only=20compute=20totals.=0A+=09=20*/=0A+=09= else=0A+=09{=0A+=09=09/*=20Examine=20the=20context=20itself=20*/=0A+=09=09= context->methods->stats(context,=0A+=09=09=09=09=09=09=09=09NULL,=0A+=09=09= =09=09=09=09=09=09NULL,=0A+=09=09=09=09=09=09=09=09totals,=20= print_to_stderr);=0A+=09}=0A+=09/*=20Increment=20the=20context=20count=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+951,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-925,6=20+969,7=20@@=20= MemoryContextStatsInternal(MemoryContext=20context,=20int=20level,=0A=20=09= =09=09ichild++;=0A=20=09=09=09child=20=3D=20= MemoryContextTraverseNext(child,=20context);=0A=20=09=09}=0A+=09=09= *num_contexts=20=3D=20*num_contexts=20+=20ichild;=0A=20=0A=20=09=09if=20= (print_to_stderr)=0A=20=09=09{=0A@@=20-939,7=20+984,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=20PRINT_STATS_NONE)=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=0A= 2.39.3=20(Apple=20Git-146)=0A=0A= --Apple-Mail=_85513A8F-54AD-4F62-B91C-5F6D88A33786 Content-Disposition: attachment; filename=v19-0002-Function-to-report-memory-context-statistics.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v19-0002-Function-to-report-memory-context-statistics.patch" Content-Transfer-Encoding: quoted-printable =46rom=20991c7404073c4dfa4e2dd55e6f169ec2c9868ee4=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Rahila=20Syed=20=0A= Date:=20Mon,=203=20Feb=202025=2015:37:17=20+0530=0ASubject:=20[PATCH=20= v19=202/3]=20Function=20to=20report=20memory=20context=20statistics=0A=0A= This=20function=20sends=20a=20signal=20to=20a=20backend=20to=20publish=0A= statistics=20of=20all=20its=20memory=20contexts.=20Signal=20handler=0A= running=20in=20the=20backend=20process,=20sets=20a=20flag,=20which=20= causes=0Ait=20to=20copy=20its=20MemoryContextStats=20to=20a=20DSA,=20= during=20the=0Anext=20call=20to=20CHECK_FOR_INTERRUPTS().=0AIf=20there=20= are=20more=20statistics=20than=20that=20fit=20in=2016MB,=20the=0A= remaining=20statistics=20are=20copied=20as=20a=20cumulative=0Atotal=20of=20= the=20remaining=20contexts.=0AOnce=20its=20done,=20it=20signals=20the=20= client=20backend=20using=0Aa=20condition=20variable.=20The=20client=20= backend=20wakes=20up,=20reads=0Athe=20shared=20memory=20and=20returns=20= these=20values=20in=20the=20form=0Aof=20set=20of=20records,=20one=20for=20= each=20memory=20context,=20to=20the=0Auser,=20followed=20by=20a=20= cumulative=20total=20of=20the=20remaining=0Acontexts,=20if=20any.=0AIf=20= get_summary=20is=20true=20return=20statistics=20of=20all=20children=0Aof=20= TopMemoryContext=20with=20aggregated=20statistics=20of=20their=0A= children.=0AUser=20can=20pass=20num_of_tries=20which=20determines=20the=20= total=0Anumber=20of=20wait=20cycles=20in=20a=20client=20backend=20for=20= latest=0Astatistics.=0AEach=20cycle=20wait=20timeout=20is=20set=20to=201=20= seconds.=20Post=20this=0Athe=20client=20displays=20previously=20= published=20statistics=20or=0Areturns=20without=20results.=0AEach=20= backend=20and=20auxiliary=20process=20has=20its=20own=20slot=20for=0A= reporting=20the=20stats.=20There=20is=20an=20array=20of=20such=20memory=20= slots=0Aof=20size=20MaxBackends+NumofAuxiliary=0Aprocesses=20in=20fixed=20= shared=20memory.=20Each=20of=20these=20slots=20point=0Ato=20a=20smaller=20= dsa=20allocations=20within=20a=20single=20DSA,=0Awhich=20contains=20the=20= stats=20to=20be=20shared=20by=20the=20corresponding=0Aprocess.=0AEach=20= slot=20has=20its=20own=20LW=20lock=20and=20condition=20variable=20for=0A= synchronization=20and=20communication=20between=20the=20publishing=0A= process=20and=20the=20client=20backend.=0A---=0A=20= doc/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=2061=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|=20415=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|=20568=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=2070=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,=201167=20insertions(+),=2041=20= deletions(-)=0A=0Adiff=20--git=20a/doc/src/sgml/func.sgml=20= b/doc/src/sgml/func.sgml=0Aindex=206fa1d6586b8..1ab2ce12662=20100644=0A= ---=20a/doc/src/sgml/func.sgml=0A+++=20b/doc/src/sgml/func.sgml=0A@@=20= -28570,6=20+28570,50=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= get_summary=20boolean,=20= num_of_tries=20integer=20)=0A+=20=20=20= =20=20=20=20=20setof=20record=0A+=20=20=20=20=20= =20=20=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=20= This=20function=20handles=20requests=20to=20display=20the=20memory=20= contexts=20of=20a=0A+=20=20=20=20=20=20=20=20PostgreSQL=20process=20with=20= the=20specified=20process=20ID=20(PID).=20It=20takes=20three=0A+=20=20=20= =20=20=20=20=20arguments:=20PID,=20= get_summary=0A+=20=20=20=20=20=20=20=20and=20= num_of_tries.=20The=20function=20can=20send=20= requests=0A+=20=20=20=20=20=20=20=20to=20both=20backend=20and=20= auxiliary=20processes.=0A+=0A+=20=20=20=20=20=20=20=20After=20receiving=20= memory=20context=20statistics=20from=20the=20target=20process,=20it=0A+=20= =20=20=20=20=20=20=20returns=20the=20results=20as=20one=20row=20per=20= context.=20If=20all=20the=20contexts=20don't=0A+=20=20=20=20=20=20=20=20= fit=20within=20the=20pre-determined=20size=20limit,=20the=20remaining=20= context=20statistics=0A+=20=20=20=20=20=20=20=20are=20aggregated=20and=20= a=20cumulative=20total=20is=20displayed.=20The=20num_agg_contexts=0A+=20=20= =20=20=20=20=20=20column=20indicates=20the=20number=20of=20contexts=20= aggregated=20in=20the=20displayed=0A+=20=20=20=20=20=20=20=20statistics.=20= The=20num_agg_contexts=20value=20is=20typically=201,=20meaning=20that=20= each=0A+=20=20=20=20=20=20=20=20context's=20statistics=20are=20displayed=20= separately.=0A+=0A+=20=20=20=20=20=20=20=20When=20= get_summary=20is=20set=20to=20true,=20statistics=0A= +=20=20=20=20=20=20=20=20for=20memory=20contexts=20at=20levels=201=20and=20= 2=20are=20displayed,=20with=20level=201=0A+=20=20=20=20=20=20=20=20= representing=20the=20root=20node=20(i.e.,=20TopMemoryContext).=0A+=20=20=20= =20=20=20=20=20Each=20level=202=20context's=20statistics=20represent=20= an=20aggregate=20of=20all=20its=0A+=20=20=20=20=20=20=20=20child=20= contexts'=20statistics,=20with=20num_agg_contexts=20indicating=20the=20= number=0A+=20=20=20=20=20=20=20=20of=20these=20aggregated=20child=20= contexts.=0A+=0A+=20=20=20=20=20=20=20=20When=20= get_summary=20is=20set=20to=20false,=20the=0A+=20=20= =20=20=20=20=20=20num_agg_contexts=20value=20is=201,=20indicating=20that=20= individual=20statistics=20are=0A+=20=20=20=20=20=20=20=20being=20= displayed.=0A+=0A+=20=20=20=20=20=20=20=20= num_of_tries=20indicates=20the=20number=20of=20= times=0A+=20=20=20=20=20=20=20=20the=20client=20will=20wait=20for=20the=20= latest=20statistics.=20The=20wait=20per=20try=20is=201=0A+=20=20=20=20=20= =20=20=20second.=20This=20parameter=20can=20be=20increased=20if=20the=20= user=20anticipates=20a=20delay=0A+=20=20=20=20=20=20=20=20in=20the=20= response=20from=20the=20reporting=20process.=20Conversely,=20if=20users=20= are=0A+=20=20=20=20=20=20=20=20frequently=20and=20periodically=20= querying=20the=20process=20for=20statistics,=20or=20if=0A+=20=20=20=20=20= =20=20=20there=20are=20concurrent=20requests=20for=20statistics=20of=20= the=20same=20process,=0A+=20=20=20=20=20=20=20=20lowering=20the=20= parameter=20might=20help=20achieve=20a=20faster=20response.=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-28688,6=20+28732,23=20@@=20LOG:=20=20= Grand=20total:=201651920=20bytes=20in=20201=20blocks;=20622360=20free=20= (88=20chunks);=201029560=0A=20=20=20=20=20because=20it=20may=20generate=20= a=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=20,=20false,=205)=20LIMIT=20= 1;=0A+=20=20=20=20=20=20=20name=20=20=20=20=20=20=20|=20ident=20|=20=20=20= type=20=20=20|=20path=20|=20total_bytes=20|=20total_nblocks=20|=20= free_bytes=20|=20free_chunks=20|=20used_bytes=20|=20num_=0A+agg_contexts=20= |=20=20=20=20=20=20=20=20=20stats_timestamp=0A= +------------------+-------+----------+------+-------------+--------------= -+------------+-------------+------------+-----=0A= +-------------+----------------------------------=0A+=20TopMemoryContext=20= |=20=20=20=20=20=20=20|=20AllocSet=20|=20{1}=20=20|=20=20=20=20=20=20= 102664=20|=20=20=20=20=20=20=20=20=20=20=20=20=204=20|=20=20=20=20=20=20=20= 3008=20|=20=20=20=20=20=20=20=20=20=20=202=20|=20=20=20=20=20=2099656=20= |=0A+=20=20=20=20=20=20=20=20=20=20=201=20|=202025-03-04=20= 10:01:57.590543+05:30=0A+=0A+=20=20=20=0A+=0A=20=20= =20=0A=20=0A=20=20=20=0A= diff=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= 7d201965503..b59034fdc38=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=20e4ca861a8e6..c50dcbc4914=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-497,6=20+498,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-671,6=20+679,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=204d2edb10658..08d17a19316=20= 100644=0A---=20a/src/backend/tcop/postgres.c=0A+++=20= b/src/backend/tcop/postgres.c=0A@@=20-3531,6=20+3531,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= 9fa12a555e8..e014e895bfb=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-160,6=20+160,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=20backend=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..462c4e48cf0=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);=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,32=20@@=20PutMemoryContextsStatsTupleStore(Tuplestorestate=20= *tupstore,=0A=20=09list_free(path);=0A=20}=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=20(context_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-305,3=20+312,353=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=20that=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=0A+=20*=20backend.=0A+=20*=20= Once=20condition=20variable=20is=20signalled,=20check=20if=20the=20= latest=20memory=20context=0A+=20*=20information=20is=20available=20and=20= display.=0A+=20*=0A+=20*=20If=20the=20publishing=20backend=20does=20not=20= respond=20before=20the=20condition=20variable=0A+=20*=20times=20out,=20= which=20is=20set=20to=20MEMSTATS_WAIT_TIMEOUT,=20retry=20for=20max_tries=0A= +=20*=20number=20of=20times,=20which=20is=20defined=20by=20user,=20= before=20giving=20up=20and=0A+=20*=20returning=20previously=20published=20= statistics,=20if=20any.=20If=20previous=20statistics=0A+=20*=20do=20not=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+=09ReturnSetInfo=20*rsinfo=20= =3D=20(ReturnSetInfo=20*)=20fcinfo->resultinfo;=0A+=09dsa_area=20=20=20= *area;=0A+=09MemoryContextEntry=20*memctx_info;=0A+=09int=09=09=09= num_retries=20=3D=200;=0A+=09TimestampTz=20curr_timestamp;=0A+=09int=09=09= =09max_tries=20=3D=20PG_GETARG_INT32(2);=0A+=0A+=09/*=0A+=09=20*=20Only=20= superusers=20or=20users=20with=20pg_read_all_stats=20privileges=20can=20= view=20the=0A+=09=20*=20memory=20context=20statistics=20of=20another=20= process=0A+=09=20*/=0A+=09if=20(!has_privs_of_role(GetUserId(),=20= ROLE_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("memory=20context=20statistics=20privilege=20error"));=0A+=0A+=09= InitMaterializedSRF(fcinfo,=200);=0A+=0A+=09/*=0A+=09=20*=20See=20if=20= the=20process=20with=20given=20pid=20is=20a=20backend=20or=20an=20= auxiliary=20process.=0A+=09=20*/=0A+=09proc=20=3D=20= BackendPidGetProc(pid);=0A+=09if=20(proc=20=3D=3D=20NULL)=0A+=09=09proc=20= =3D=20AuxiliaryPidGetProc(pid);=0A+=0A+=09/*=0A+=09=20*=20= BackendPidGetProc()=20and=20AuxiliaryPidGetProc()=20return=20NULL=20if=20= the=20pid=0A+=09=20*=20isn't=20valid;=20but=20by=20the=20time=20we=20= reach=20kill(),=20a=20process=20for=20which=20we=0A+=09=20*=20get=20a=20= valid=20proc=20here=20might=20have=20terminated=20on=20its=20own.=20=20= There's=20no=20way=0A+=09=20*=20to=20acquire=20a=20lock=20on=20an=20= arbitrary=20process=20to=20prevent=20that.=20But=20since=0A+=09=20*=20= this=20mechanism=20is=20usually=20used=20to=20debug=20a=20backend=20or=20= an=20auxiliary=0A+=09=20*=20process=20running=20and=20consuming=20lots=20= of=20memory,=20that=20it=20might=20end=20on=20its=0A+=09=20*=20own=20= first=20and=20its=20memory=20contexts=20are=20not=20logged=20is=20not=20= a=20problem.=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=20= loop-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",=0A+=09=09=09=09=09=09pid)));=0A+=09=09= PG_RETURN_NULL();=0A+=09}=0A+=0A+=09procNumber=20=3D=20= GetNumberFromPGProc(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=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_tries=20*=0A= +=09=20*=20MEMSTATS_WAIT_TIMEOUT,=20following=20which=20display=20old=20= statistics=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=20the=20= requested=20process=20has=0A+=09=09=20*=20finished=20publishing=20the=20= statistics,=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+=09=09msecs=20=3D=0A+=09=09=09= TimestampDifferenceMilliseconds(curr_timestamp,=0A+=09=09=09=09=09=09=09=09= =09=09=09memCtxState[procNumber].stats_timestamp);=0A+=0A+=09=09/*=0A+=09= =09=20*=20Note=20in=20procnumber.h=20file=20says=20that=20a=20procNumber=20= can=20be=20re-used=20for=0A+=09=09=20*=20a=20different=20backend=20= immediately=20after=20a=20backend=20exits.=20In=20case=20an=0A+=09=09=20= *=20old=20process'=20data=20was=20there=20and=20not=20updated=20by=20the=20= current=20process=0A+=09=09=20*=20in=20the=20slot=20identified=20by=20= the=20procNumber,=20the=20pid=20of=20the=20requested=0A+=09=09=20*=20= process=20and=20the=20proc_id=20might=20not=20match.=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=20the=20latest=20stats=20have=20= been=20read,=20indicated=20by=0A+=09=09=09=20*=20statistics=20timestamp=20= being=20newer=20than=20the=20current=20request=0A+=09=09=09=20*=20= timestamp.=0A+=09=09=09=20*/=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+=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=0A+=09=09=20*/=0A+=09=09= proc=20=3D=20BackendPidGetProc(pid);=0A+=0A+#define=20= MEMSTATS_WAIT_TIMEOUT=201000=0A+=09=09if=20(proc=20=3D=3D=20NULL)=0A+=09=09= =09proc=20=3D=20AuxiliaryPidGetProc(pid);=0A+=09=09if=20(proc=20=3D=3D=20= NULL)=0A+=09=09{=0A+=09=09=09ereport(WARNING,=0A+=09=09=09=09=09= errmsg("PID=20%d=20is=20not=20a=20PostgreSQL=20server=20process",=0A+=09=09= =09=09=09=09=20=20=20pid));=0A+=09=09=09PG_RETURN_NULL();=0A+=09=09}=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_tries=20defined=20by=20user,=20display=20= previously=0A+=09=09=09=20*=20published=20statistics=20if=20any,=20when=20= max_tries=20are=20over.=0A+=09=09=09=20*/=0A+=09=09=09if=20(num_retries=20= >=20max_tries)=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=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(LOG,=0A+=09=09=09=09=09errmsg("Wait=20for=20%d=20process=20to=20= publish=20stats=20timed=20out,=20trying=20again",=0A+=09=09=09=09=09=09=20= =20=20pid));=0A+=09=09=09num_retries=20=3D=20num_retries=20+=201;=0A+=09=09= }=0A+=0A+=09}=0A+=09/*=20We=20should=20land=20here=20only=20with=20a=20= valid=20DSA=20handle=20*/=0A+=09Assert(memCtxArea->memstats_dsa_handle=20= !=3D=20DSA_HANDLE_INVALID);=0A+=09area=20=3D=20= dsa_attach(memCtxArea->memstats_dsa_handle);=0A+=0A+=09/*=0A+=09=20*=20= Backend=20has=20finished=20publishing=20the=20stats,=20read=20them=0A+=09= =20*=0A+=09=20*=20Read=20statistics=20of=20top=20level=201=20and=202=20= contexts,=20if=20get_summary=20is=20true.=0A+=09=20*/=0A+=09memctx_info=20= =3D=20(MemoryContextEntry=20*)=20dsa_get_address(area,=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=09=09=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_array;=0A+=0A+=09=09memset(values,=200,=20sizeof(values));=0A= +=09=09memset(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+=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+=0A+=09=09if=20= (DsaPointerIsValid(memctx_info[i].path))=0A+=09=09{=0A+=09=09=09= path_datum_array=20=3D=20(Datum=20*)=20dsa_get_address(area,=20= memctx_info[i].path);=0A+=09=09=09path_array=20=3D=20= construct_array_builtin(path_datum_array,=0A+=09=09=09=09=09=09=09=09=09=09= =09=09=20path_length,=20INT4OID);=0A+=0A+=09=09=09values[3]=20=3D=20= PointerGetDatum(path_array);=0A+=09=09}=0A+=09=09else=0A+=09=09=09= nulls[3]=20=3D=20true;=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*=20Shared=20memory=20sizing=20= for=20reporting=20memory=20context=20information.=0A+=20*/=0A+static=20= Size=0A+MemCtxShmemSize(void)=0A+{=0A+=09Size=09=09TotalProcs=20=3D=0A+=09= =09add_size(MaxBackends,=20add_size(NUM_AUXILIARY_PROCS,=20= max_prepared_xacts));=0A+=0A+=09return=20mul_size(TotalProcs,=20= sizeof(MemoryContextBackendState));=0A+}=0A+=0A+/*=0A+=20*=20Init=20= shared=20memory=20for=20reporting=20memory=20context=20information.=0A+=20= */=0A+void=0A+MemCtxBackendShmemInit(void)=0A+{=0A+=09bool=09=09found;=0A= +=09Size=09=09TotalProcs=20=3D=0A+=09=09add_size(MaxBackends,=20= add_size(NUM_AUXILIARY_PROCS,=20max_prepared_xacts));=0A+=0A+=09= memCtxState=20=3D=20(MemoryContextBackendState=20*)=20= ShmemInitStruct("MemoryContextBackendState",=0A+=09=09=09=09=09=09=09=09=09= =09=09=09=09=09=09=09MemCtxShmemSize(),=0A+=09=09=09=09=09=09=09=09=09=09= =09=09=09=09=09=09&found);=0A+=09if=20(!IsUnderPostmaster)=0A+=09{=0A+=09= =09Assert(!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,=0A+=09=09=09=09=09=09=09=20= LWLockNewTrancheId());=0A+=09=09=09= LWLockRegisterTranche(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=0A= +=20*=20context=20statistics=0A+=20*/=0A+void=0A+MemCtxShmemInit(void)=0A= +{=0A+=09bool=09=09found;=0A+=0A+=09memCtxArea=20=3D=20= (MemoryContextState=20*)=20ShmemInitStruct("MemoryContextState",=20= sizeof(MemoryContextState),=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=09= &found);=0A+=09if=20(!IsUnderPostmaster)=0A+=09{=0A+=09=09= Assert(!found);=0A+=0A+=09=09LWLockInitialize(&memCtxArea->lw_lock,=0A+=09= =09=09=09=09=09=20LWLockNewTrancheId());=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=20b844f9fdaef..13938ccb0f5=20100644=0A---=20= a/src/backend/utils/init/globals.c=0A+++=20= b/src/backend/utils/init/globals.c=0A@@=20-38,6=20+38,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=2034cdcdf2fd3..214330aa7a5=20100644=0A---=20= a/src/backend/utils/mmgr/mcxt.c=0A+++=20b/src/backend/utils/mmgr/mcxt.c=0A= @@=20-19,10=20+19,18=20@@=0A=20=20= *-------------------------------------------------------------------------= =0A=20=20*/=0A=20=0A+#include=20=0A=20#include=20"postgres.h"=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= -177,6=20+185,16=20@@=20static=20void=20= MemoryContextStatsInternal(MemoryContext=20context,=20int=20level,=0A=20= static=20void=20MemoryContextStatsPrint(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+static=20void=20= dsa_free_previous_stats(dsa_area=20*area,=20int=20total_stats,=20= dsa_pointer=20prev_dsa_pointer);=0A=20=0A=20/*=0A=20=20*=20You=20should=20= not=20do=20memory=20allocations=20within=20a=20critical=20section,=20= because=0A@@=20-889,7=20+907,8=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= -899,38=20+918,43=20@@=20MemoryContextStatsInternal(MemoryContext=20= context,=20int=20level,=0A=20{=0A=20=09MemoryContext=20child;=0A=20=09= int=09=09=09ichild;=0A-=09bool=09=09print_to_stderr=20=3D=20true;=0A=20=0A= =20=09check_stack_depth();=0A=20=09= Assert(MemoryContextIsValid(context));=0A=20=0A=20=09if=20= (print_location=20=3D=3D=20PRINT_STATS_TO_STDERR)=0A-=09=09= print_to_stderr=20=3D=20true;=0A+=09{=0A+=09=09/*=20Examine=20the=20= context=20itself=20*/=0A+=09=09context->methods->stats(context,=0A+=09=09= =09=09=09=09=09=09MemoryContextStatsPrint,=0A+=09=09=09=09=09=09=09=09= &level,=0A+=09=09=09=09=09=09=09=09totals,=20true);=0A+=09}=0A=20=09else=20= if=20(print_location=20=3D=3D=20PRINT_STATS_TO_LOGS)=0A-=09=09= print_to_stderr=20=3D=20false;=0A-=0A-=09if=20(print_location=20!=3D=20= PRINT_STATS_NONE)=0A=20=09{=0A+=0A=20=09=09/*=20Examine=20the=20context=20= itself=20*/=0A=20=09=09context->methods->stats(context,=0A=20=09=09=09=09= =09=09=09=09MemoryContextStatsPrint,=0A=20=09=09=09=09=09=09=09=09= &level,=0A-=09=09=09=09=09=09=09=09totals,=20print_to_stderr);=0A+=09=09=09= =09=09=09=09=09totals,=20false);=0A=20=09}=0A=20=0A=20=09/*=0A=20=09=20*=20= Do=20not=20print=20the=20statistics=20if=20print_to_stderr=20is=20= PRINT_STATS_NONE,=0A-=09=20*=20only=20compute=20totals.=0A+=09=20*=20= only=20compute=20totals.=20This=20is=20used=20in=20reporting=20of=20= memory=20context=0A+=09=20*=20statistics=20via=20a=20sql=20function.=20= Last=20parameter=20is=20not=20relevant.=0A=20=09=20*/=0A=20=09else=0A=20=09= {=0A+=09=09Assert(print_location=20=3D=3D=20PRINT_STATS_NONE);=0A=20=09=09= /*=20Examine=20the=20context=20itself=20*/=0A=20=09=09= context->methods->stats(context,=0A=20=09=09=09=09=09=09=09=09NULL,=0A=20= =09=09=09=09=09=09=09=09NULL,=0A-=09=09=09=09=09=09=09=09totals,=20= print_to_stderr);=0A+=09=09=09=09=09=09=09=09totals,=20false);=0A=20=09}=0A= -=09/*=20Increment=20the=20context=20count=20*/=0A+=09/*=20Increment=20= the=20context=20count=20for=20each=20of=20the=20recursive=20call=20*/=0A=20= =09*num_contexts=20=3D=20*num_contexts=20+=201;=0A=20=0A=20=09/*=0A@@=20= -969,9=20+993,14=20@@=20MemoryContextStatsInternal(MemoryContext=20= context,=20int=20level,=0A=20=09=09=09ichild++;=0A=20=09=09=09child=20=3D=20= MemoryContextTraverseNext(child,=20context);=0A=20=09=09}=0A+=0A+=09=09= /*=0A+=09=09=20*=20Add=20the=20count=20of=20children=20contexts=20which=20= are=20traversed=20in=20the=0A+=09=09=20*=20non-recursive=20manner.=0A+=09= =09=20*/=0A=20=09=09*num_contexts=20=3D=20*num_contexts=20+=20ichild;=0A=20= =0A-=09=09if=20(print_to_stderr)=0A+=09=09if=20(print_location=20=3D=3D=20= PRINT_STATS_TO_STDERR)=0A=20=09=09{=0A=20=09=09=09for=20(int=20i=20=3D=20= 0;=20i=20<=3D=20level;=20i++)=0A=20=09=09=09=09fprintf(stderr,=20"=20=20= ");=0A@@=20-984,7=20+1013,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=20if=20(print_location=20!=3D=20PRINT_STATS_NONE)=0A+=09=09else=20= if=20(print_location=20=3D=3D=20PRINT_STATS_TO_LOGS)=0A=20=09=09=09= ereport(LOG_SERVER_ONLY,=0A=20=09=09=09=09=09(errhidestmt(true),=0A=20=09= =09=09=09=09=20errhidecontext(true),=0A@@=20-1321,6=20+1350,21=20@@=20= HandleLogMemoryContextInterrupt(void)=0A=20=09/*=20latch=20will=20be=20= set=20by=20procsignal_sigusr1_handler=20*/=0A=20}=0A=20=0A+/*=0A+=20*=20= HandleGetMemoryContextInterrupt=0A+=20*=09=09Handle=20receipt=20of=20an=20= interrupt=20indicating=20publishing=20of=20memory=0A+=20*=09=09contexts.=0A= +=20*=0A+=20*=20All=20the=20actual=20work=20is=20deferred=20to=20= ProcessLogMemoryContextInterrupt()=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= -1358,6=20+1402,506=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=20children=20in=20the=20monitoring=20function=20= output.=0A+=20*=0A+=20*=20Statistics=20for=20all=20the=20processes=20are=20= shared=20via=20the=20same=20dynamic=20shared=20area.=0A+=20*=0A+=20*=20= We=20calculate=20maximum=20number=20of=20context's=20statistics=20that=20= can=20be=20displayed=0A+=20*=20using=20a=20pre-determined=20limit=20for=20= memory=20available=20per=20process=20for=20this=20utility=0A+=20*=20and=20= the=20estimate=20of=20the=20size=20of=20statistics=20for=20each=20= context.=0A+=20*=20The=20remaining=20context=20statistics=20if=20any=20= are=20captured=20as=20a=20cumulative=20total=0A+=20*=20at=20the=20end=20= of=20individual=20context's=20statistics.=0A+=20*=0A+=20*=20If=20= get_summary=20is=20true,=20we=20display=20the=20level=201=20and=20level=20= 2=20contexts.=20For=20that=0A+=20*=20we=20traverse=20the=20memory=20= context=20tree=20recursively=20in=20depth=20first=20search=20manner=0A+=20= *=20to=20cover=20all=20the=20children=20of=20a=20parent=20context,=20to=20= be=20able=20to=20display=20a=0A+=20*=20cumulative=20total=20of=20memory=20= consumption=20by=20a=20parent=20at=20level=202.=0A+=20*/=0A+void=0A= +ProcessGetMemoryContextInterrupt(void)=0A+{=0A+=09List=09=20=20=20= *contexts;=0A+=0A+=09HASHCTL=09=09ctl;=0A+=09HTAB=09=20=20=20= *context_id_lookup;=0A+=09int=09=09=09context_id=20=3D=200;=0A+=09= MemoryContext=20stat_cxt;=0A+=09MemoryContextEntry=20*meminfo;=0A+=09= bool=09=09get_summary=20=3D=20false;=0A+=0A+=09dsa_area=20=20=20*area=20= =3D=20NULL;=0A+=09int=09=09=09max_stats;=0A+=09int=09=09=09idx=20=3D=20= MyProcNumber;=0A+=09int=09=09=09stats_count=20=3D=200;=0A+=09= MemoryContextCounters=20stat;=0A+=09int=09=09=09num_individual_stats=20=3D= =200;=0A+=0A+=09PublishMemoryContextPending=20=3D=20false;=0A+=0A+=09/*=0A= +=09=20*=20Make=20a=20new=20context=20that=20will=20contain=20the=20hash=20= table,=20to=20ease=20the=0A+=09=20*=20cleanup.=0A+=09=20*/=0A+=09= stat_cxt=20=3D=20AllocSetContextCreate(CurrentMemoryContext,=0A+=09=09=09= =09=09=09=09=09=09=20"Memory=20context=20statistics",=0A+=09=09=09=09=09=09= =09=09=09=20ALLOCSET_DEFAULT_SIZES);=0A+=0A+=09/*=0A+=09=20*=20The=20= hash=20table=20is=20used=20for=20constructing=20"path"=20column=20of=20= the=20view,=0A+=09=20*=20similar=20to=20its=20local=20backend=20= counterpart.=0A+=09=20*/=0A+=09ctl.keysize=20=3D=20= sizeof(MemoryContext);=0A+=09ctl.entrysize=20=3D=20= sizeof(MemoryContextId);=0A+=09ctl.hcxt=20=3D=20stat_cxt;=0A+=0A+=09= context_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(sizeof(MemoryContextEntry)=20= +=20(MEM_CONTEXT_MAX_LEVEL=0A+=09=09=09=09=09=09=09=09=09=09=20*=20= sizeof(Datum))=20+=20(2=20*=20MEMORY_CONTEXT_IDENT_SHMEM_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=20(stats_count=20>=20= max_stats)=20?=20max_stats=20:=20stats_count;=0A+=0A+=09= LWLockAcquire(&memCtxArea->lw_lock,=20LW_EXCLUSIVE);=0A+=0A+=09/*=0A+=09=20= *=20Create=20a=20DSA=20and=20send=20handle=20to=20the=20the=20client=20= process=20after=20storing=0A+=09=20*=20the=20context=20statistics.=20If=20= number=20of=20contexts=20exceed=20a=20predefined=0A+=09=20*=20= limit(8MB),=20a=20cumulative=20total=20is=20stored=20for=20such=20= contexts.=0A+=09=20*/=0A+=09if=20(memCtxArea->memstats_dsa_handle=20=3D=3D= =20DSA_HANDLE_INVALID)=0A+=09{=0A+=09=09MemoryContext=20oldcontext=20=3D=20= CurrentMemoryContext;=0A+=09=09dsa_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=20a=20waiting=0A+=09=09=20*=20client=20gets=20the=20= stats=20even=20after=20a=20process=20exits.=0A+=09=09=20*/=0A+=09=09= dsa_pin(area);=0A+=0A+=09=09/*=20Set=20the=20handle=20in=20shared=20= memory=20*/=0A+=09=09memCtxArea->memstats_dsa_handle=20=3D=20handle;=0A+=09= }=0A+=0A+=09/*=0A+=09=20*=20If=20DSA=20exists,=20created=20by=20another=20= process=20publishing=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+=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=20dsa_allocate0(area,=0A= +=09=09=09=09=09=09=09=09=09=09=09=09=09=09=20=20stats_count=20*=20= sizeof(MemoryContextEntry));=0A+=0A+=09meminfo=20=3D=20= (MemoryContextEntry=20*)=20dsa_get_address(area,=0A+=09=09=09=09=09=09=09= =09=09=09=09=09=09=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+=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= 0,=20100,=20100,=20&grand_totals,=0A+=09=09=09=09=09=09=09=09=09=20=20=20= PRINT_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= PublishMemoryContext(meminfo,=20ctx_id,=20c,=20path,=0A+=09=09=09=09=09=09= =09=09=20grand_totals,=20num_contexts,=20area);=0A+=09=09=09ctx_id=20=3D=20= ctx_id=20+=201;=0A+=09=09}=0A+=09=09memCtxState[idx].total_stats=20=3D=20= ctx_id;=0A+=09=09goto=20cleanup;=0A+=09}=0A+=09= foreach_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=20context_id=20of=20= this=20context=20and=20each=20of=20its=0A+=09=09=20*=20ancestors,=20to=20= compute=20a=20path=20for=20this=20context.=0A+=09=09=20*/=0A+=09=09path=20= =3D=20compute_context_path(cur,=20context_id_lookup);=0A+=0A+=09=09if=20= (context_id=20<=3D=20(max_stats=20-=202))=0A+=09=09{=0A+=09=09=09/*=20= Examine=20the=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+=09=09=09/*=20Copy=20statistics=20to=20DSA=20= memory=20*/=0A+=09=09=09PublishMemoryContext(meminfo,=20context_id,=20= cur,=20path,=20stat,=201,=20area);=0A+=09=09}=0A+=09=09else=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+=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=09if=20(context_id=20=3D=3D=20= (max_stats=20-=202)=20&&=20context_id=20<=20(stats_count=20-=201))=0A+=09= =09{=0A+=09=09=09num_individual_stats=20=3D=20context_id=20+=201;=0A+=09=09= =09meminfo[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/*=20No=20aggregated=20contexts,=20= individual=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+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/*=20= Delete=20the=20hash=20table=20memory=20context=20*/=0A+=09= MemoryContextDelete(stat_cxt);=0A+=0A+=09dsa_detach(area);=0A+}=0A+=0A= +/*=0A+=20*=20Append=20the=20transient=20context_id=20of=20this=20= context=20and=20each=20of=0A+=20*=20its=20ancestors=20to=20a=20list,=20= in=20order=20to=20compute=20a=20path.=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+=0A= +=09for=20(MemoryContext=20cur_context=20=3D=20c;=20cur_context=20!=3D=20= NULL;=20cur_context=20=3D=20cur_context->parent)=0A+=09{=0A+=09=09= MemoryContextId=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{=0A+=09=09=09ereport(LOG,=0A+=09=09=09= =09=09errmsg("hash=20table=20corrupted,=20can't=20construct=20path=20= value"));=0A+=09=09=09break;=0A+=09=09}=0A+=09=09path=20=3D=20= lcons_int(cur_entry->context_id,=20path);=0A+=09}=0A+=09return=20path;=0A= +}=0A+=0A+/*=0A+=20*=20Return=20the=20number=20of=20contexts=20allocated=20= currently=20by=20the=20backend=0A+=20*=20Assign=20context=20ids=20to=20= each=20of=20the=20contexts.=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(from=20= top)=20contexts=20are=0A+=09=09=20*=20displayed=0A+=09=09=20*/=0A+=09=09= if=20(get_summary)=0A+=09=09=09break;=0A+=09}=0A+=0A+}=0A+=0A+/*=20Copy=20= the=20memory=20context=20statistics=20of=20a=20single=20context=20to=20a=20= dsa=20memory=20*/=0A+static=20void=0A= +PublishMemoryContext(MemoryContextEntry=20*memctx_info,=20int=20= curr_id,=0A+=09=09=09=09=09=20MemoryContext=20context,=20List=20*path,=0A= +=09=09=09=09=09=20MemoryContextCounters=20stat,=20int=20num_contexts,=0A= +=09=09=09=09=09=20dsa_area=20*area)=0A+{=0A+=09char=09=09= clipped_ident[MEMORY_CONTEXT_IDENT_SHMEM_SIZE];=0A+=09char=09=20=20=20= *name;=0A+=09char=09=20=20=20*ident;=0A+=09Datum=09=20=20=20*path_array;=0A= +=0A+=09if=20(context->name=20!=3D=20NULL)=0A+=09{=0A+=09=09= Assert(strlen(context->name)=20<=20MEMORY_CONTEXT_IDENT_SHMEM_SIZE);=0A+=09= =09memctx_info[curr_id].name=20=3D=20dsa_allocate0(area,=20= strlen(context->name)=20+=201);=0A+=09=09name=20=3D=20(char=20*)=20= dsa_get_address(area,=20memctx_info[curr_id].name);=0A+=09=09= strncpy(name,=20context->name,=20strlen(context->name));=0A+=09}=0A+=09= else=0A+=09=09memctx_info[curr_id].name=20=3D=20InvalidDsaPointer;=0A+=0A= +=09/*=20Trim=20and=20copy=20the=20identifier=20if=20it=20is=20not=20set=20= to=20NULL=20*/=0A+=09if=20(context->ident=20!=3D=20NULL)=0A+=09{=0A+=09=09= int=09=09=09idlen=20=3D=20strlen(context->ident);=0A+=0A+=09=09/*=0A+=09=09= =20*=20Some=20identifiers=20such=20as=20SQL=20query=20string=20can=20be=20= very=20long,=0A+=09=09=20*=20truncate=20oversize=20identifiers.=0A+=09=09= =20*/=0A+=09=09if=20(idlen=20>=3D=20MEMORY_CONTEXT_IDENT_SHMEM_SIZE)=0A+=09= =09=09idlen=20=3D=20pg_mbcliplen(context->ident,=20idlen,=0A+=09=09=09=09= =09=09=09=09=20MEMORY_CONTEXT_IDENT_SHMEM_SIZE=20-=201);=0A+=0A+=09=09= memcpy(clipped_ident,=20context->ident,=20idlen);=0A+=09=09= clipped_ident[idlen]=20=3D=20'\0';=0A+=0A+=09=09/*=0A+=09=09=20*=20To=20= be=20consistent=20with=20logging=20output,=20we=20label=20dynahash=20= contexts=0A+=09=09=20*=20with=20just=20the=20hash=20table=20name=20as=20= with=20MemoryContextStatsPrint().=0A+=09=09=20*/=0A+=09=09if=20= (!strncmp(context->name,=20"dynahash",=208))=0A+=09=09{=0A+=09=09=09= dsa_free(area,=20memctx_info[curr_id].name);=0A+=09=09=09= memctx_info[curr_id].name=20=3D=20dsa_allocate0(area,=0A+=09=09=09=09=09=09= =09=09=09=09=09=09=09=20=20strlen(clipped_ident)=20+=201);=0A+=09=09=09= name=20=3D=20(char=20*)=20dsa_get_address(area,=0A+=09=09=09=09=09=09=09=09= =09=09=09memctx_info[curr_id].name);=0A+=09=09=09strlcpy(name,=0A+=09=09=09= =09=09clipped_ident,=20idlen=20+=201);=0A+=09=09=09= memctx_info[curr_id].ident=20=3D=20InvalidDsaPointer;=0A+=09=09}=0A+=09=09= else=0A+=09=09{=0A+=0A+=09=09=09memctx_info[curr_id].ident=20=3D=20= dsa_allocate0(area,=0A+=09=09=09=09=09=09=09=09=09=09=09=09=09=20=20=20= strlen(clipped_ident)=20+=201);=0A+=09=09=09ident=20=3D=20(char=20*)=20= dsa_get_address(area,=0A+=09=09=09=09=09=09=09=09=09=09=09=20= memctx_info[curr_id].ident);=0A+=09=09=09strlcpy(ident,=0A+=09=09=09=09=09= clipped_ident,=20idlen=20+=201);=0A+=09=09}=0A+=09}=0A+=09else=0A+=09=09= memctx_info[curr_id].ident=20=3D=20InvalidDsaPointer;=0A+=09/*=20= Allocate=20dsa=20memory=20for=20storing=20path=20information=20*/=0A+=09= if=20(path=20=3D=3D=20NIL)=0A+=09=09memctx_info[curr_id].path=20=3D=20= InvalidDsaPointer;=0A+=09else=0A+=09{=0A+=09=09= memctx_info[curr_id].path_length=20=3D=20list_length(path);=0A+=09=09= memctx_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=0A+=09=09=09=09=09= =09=09=09=09=09=09=09=20=20*=20sizeof(Datum));=0A+=09=09path_array=20=3D=20= (Datum=20*)=20dsa_get_address(area,=20memctx_info[curr_id].path);=0A+=09=09= foreach_int(i,=20path)=0A+=09=09=09path_array[foreach_current_index(i)]=20= =3D=20Int32GetDatum(i);=0A+=09}=0A+=09memctx_info[curr_id].type=20=3D=20= ContextTypeToString(context->type);=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= +static=20void=0A+dsa_free_previous_stats(dsa_area=20*area,=20int=20= total_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= +=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=20= DSA_HANDLE_INVALID)=0A+=09=09dsm_seg=20=3D=20= dsm_find_mapping(memCtxArea->memstats_dsa_handle);=0A+=09else=0A+=09=09= return;=0A+=0A+=09LWLockAcquire(&memCtxState[idx].lw_lock,=20= LW_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=3D=20NULL)=0A+=09= =09area=20=3D=20dsa_attach(memCtxArea->memstats_dsa_handle);=0A+=09else=0A= +=09=09return;=0A+=0A+=09/*=0A+=09=20*=20Free=20the=20memory=20context=20= statistics,=20free=20the=20name,=20ident=20and=20path=0A+=09=20*=20= pointers=20before=20freeing=20the=20pointer=20that=20contains=20these=20= pointers=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=200d29ef50ff2..e2957c3906d=20100644=0A---=20= a/src/include/catalog/pg_proc.dat=0A+++=20= b/src/include/catalog/pg_proc.dat=0A@@=20-8509,6=20+8509,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'{oid,=20= summary,=20num_of_tries,=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= 603d0424354..d3c44df6e13=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=20022fd8ed933..5d4b2fbfc9c=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..10fab7e5804=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,7=20+51,10=20@@=0A=20=0A=20#define=20AllocHugeSizeIsValid(size)=09= ((Size)=20(size)=20<=3D=20MaxAllocHugeSize)=0A=20=0A+#define=20= MEMORY_CONTEXT_IDENT_SHMEM_SIZE=20128=0A=20=0A+#define=20= MEM_CONTEXT_MAX_LEVEL=0964=0A+#define=20MAX_SEGMENTS_PER_BACKEND=208=0A=20= /*=0A=20=20*=20Standard=20top-level=20memory=20contexts.=0A=20=20*=0A@@=20= -319,4=20+325,68=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=0A+=20*=20created=20for=20memory=20context=20statistics=20= reporting.=0A+=20*=20Single=20DSA=20area=20is=20created=20and=20used=20= by=20all=20the=20processes,=0A+=20*=20each=20having=20its=20specific=20= dsa=20allocations=20for=20sharing=20memory=0A+=20*=20statistics,=20= tracked=20by=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=0A+=20*=20context=20statistics=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= 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+}=20MemoryContextId;=0A+=0A+extern=20= PGDLLIMPORT=20MemoryContextBackendState=20*memCtxState;=0A+extern=20= PGDLLIMPORT=20MemoryContextState=20*memCtxArea;=0A+extern=20void=20= ProcessGetMemoryContextInterrupt(void);=0A+extern=20const=20char=20= *ContextTypeToString(NodeTag=20type);=0A+extern=20void=20= HandleGetMemoryContextInterrupt(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=203fbf5a4c212..6cd7a30e0be=20= 100644=0A---=20a/src/tools/pgindent/typedefs.list=0A+++=20= b/src/tools/pgindent/typedefs.list=0A@@=20-1649,12=20+1649,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=_85513A8F-54AD-4F62-B91C-5F6D88A33786 Content-Disposition: attachment; filename=v19-0003-Review-comments-and-fixups.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="v19-0003-Review-comments-and-fixups.patch" Content-Transfer-Encoding: quoted-printable =46rom=20d9e8a1488472db17bcb3b275488232e5db94d018=20Mon=20Sep=2017=20= 00:00:00=202001=0AFrom:=20Daniel=20Gustafsson=20= =0ADate:=20Tue,=2025=20Mar=202025=2013:47:52=20= +0100=0ASubject:=20[PATCH=20v19=203/3]=20Review=20comments=20and=20= fixups=0A=0A---=0A=20doc/src/sgml/func.sgml=20=20=20=20=20=20=20=20=20=20= =20=20|=20=2062=20+++++++++++-------=0A=20= src/backend/utils/adt/mcxtfuncs.c=20|=20103=20= +++++++++++++++---------------=0A=20src/backend/utils/mmgr/mcxt.c=20=20=20= =20=20|=20=2078=20+++++++++++-----------=0A=203=20files=20changed,=20131=20= insertions(+),=20112=20deletions(-)=0A=0Adiff=20--git=20= a/doc/src/sgml/func.sgml=20b/doc/src/sgml/func.sgml=0Aindex=20= 1ab2ce12662..f8a3b9d0cf6=20100644=0A---=20a/doc/src/sgml/func.sgml=0A+++=20= b/doc/src/sgml/func.sgml=0A@@=20-28580,34=20+28580,36=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=20=0A=20=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=20PostgreSQL=20= process=20with=20the=20specified=20process=20ID=20(PID).=20It=20takes=20= three=0A-=20=20=20=20=20=20=20=20arguments:=20= PID,=20get_summary=0A-=20=20= =20=20=20=20=20=20and=20num_of_tries.=20The=20= function=20can=20send=20requests=0A+=20=20=20=20=20=20=20=20= PostgreSQL=20process=20with=20the=20specified=20= process=20ID.=20=20It=20takes=20three=0A+=20=20=20=20=20=20=20=20= arguments:=20pid,=20= get_summary=0A+=20=20=20=20=20=20=20=20and=20= num_of_tries.=20=20The=20function=20can=20send=20= requests=0A=20=20=20=20=20=20=20=20=20to=20both=20backend=20and=20= auxiliary=20processes.=0A-=0A+=20=20=20=20=20=20=20=0A+=20=20=20=20= =20=20=20=0A=20=20=20=20=20=20=20=20=20After=20receiving=20memory=20= context=20statistics=20from=20the=20target=20process,=20it=0A-=20=20=20=20= =20=20=20=20returns=20the=20results=20as=20one=20row=20per=20context.=20= If=20all=20the=20contexts=20don't=0A+=20=20=20=20=20=20=20=20returns=20= the=20results=20as=20one=20row=20per=20context.=20=20If=20all=20the=20= contexts=20don't=0A=20=20=20=20=20=20=20=20=20fit=20within=20the=20= pre-determined=20size=20limit,=20the=20remaining=20context=20statistics=0A= -=20=20=20=20=20=20=20=20are=20aggregated=20and=20a=20cumulative=20total=20= is=20displayed.=20The=20num_agg_contexts=0A+=20=20=20=20=20=20=20=20are=20= aggregated=20and=20a=20cumulative=20total=20is=20displayed.=20=20The=20= num_agg_contexts=0A=20=20=20=20=20=20=20=20=20column=20= indicates=20the=20number=20of=20contexts=20aggregated=20in=20the=20= displayed=0A-=20=20=20=20=20=20=20=20statistics.=20The=20= num_agg_contexts=20value=20is=20typically=201,=20meaning=20that=20each=0A= +=20=20=20=20=20=20=20=20statistics.=20=20The=20= num_agg_contexts=20value=20is=20typically=201,=20= meaning=20that=20each=0A=20=20=20=20=20=20=20=20=20context's=20= statistics=20are=20displayed=20separately.=0A-=0A-=20=20=20=20=20=20=20=20= When=20get_summary=20is=20set=20to=20true,=20= statistics=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=20= get_summary=20is=20set=20to=20= true,=20statistics=0A=20=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=20=20representing=20the=20root=20node=20= (i.e.,=20TopMemoryContext).=0A=20=20=20=20=20=20=20=20=20Each=20level=20= 2=20context's=20statistics=20represent=20an=20aggregate=20of=20all=20its=0A= -=20=20=20=20=20=20=20=20child=20contexts'=20statistics,=20with=20= num_agg_contexts=20indicating=20the=20number=0A+=20=20=20=20=20=20=20=20= child=20contexts'=20statistics,=20with=20= num_agg_contexts=20indicating=20the=20number=0A=20=20=20= =20=20=20=20=20=20of=20these=20aggregated=20child=20contexts.=0A-=0A-=20=20= =20=20=20=20=20=20When=20get_summary=20is=20set=20= to=20false,=20the=0A+=20=20=20=20=20=20=20=20When=20= get_summary=20is=20set=20to=20= false,=20the=0A=20=20=20=20=20=20=20=20=20= num_agg_contexts=20value=20is=201,=20indicating=20that=20individual=20= statistics=20are=0A=20=20=20=20=20=20=20=20=20being=20displayed.=0A-=0A+=20= =20=20=20=20=20=20=0A+=20=20=20=20=20=20=20=0A=20=20=20=20=20= =20=20=20=20num_of_tries=20indicates=20the=20= number=20of=20times=0A-=20=20=20=20=20=20=20=20the=20client=20will=20= wait=20for=20the=20latest=20statistics.=20The=20wait=20per=20try=20is=20= 1=0A-=20=20=20=20=20=20=20=20second.=20This=20parameter=20can=20be=20= increased=20if=20the=20user=20anticipates=20a=20delay=0A-=20=20=20=20=20=20= =20=20in=20the=20response=20from=20the=20reporting=20process.=20= Conversely,=20if=20users=20are=0A+=20=20=20=20=20=20=20=20the=20client=20= will=20wait=20for=20the=20latest=20statistics.=20=20The=20wait=20per=20= try=20is=201=0A+=20=20=20=20=20=20=20=20second.=20=20This=20parameter=20= can=20be=20increased=20if=20the=20user=20anticipates=20a=20delay=0A+=20=20= =20=20=20=20=20=20in=20the=20response=20from=20the=20reporting=20= process.=20=20Conversely,=20if=20users=20are=0A=20=20=20=20=20=20=20=20=20= frequently=20and=20periodically=20querying=20the=20process=20for=20= statistics,=20or=20if=0A=20=20=20=20=20=20=20=20=20there=20are=20= concurrent=20requests=20for=20statistics=20of=20the=20same=20process,=0A=20= =20=20=20=20=20=20=20=20lowering=20the=20parameter=20might=20help=20= achieve=20a=20faster=20response.=0A@@=20-28740,13=20+28742,29=20@@=20= postgres=3D#=20SELECT=20*=20FROM=20pg_get_process_memory_contexts(=0A=20=20= =20(SELECT=20pid=20FROM=20pg_stat_activity=0A=20=20=20=20=20WHERE=20= backend_type=20=3D=20'checkpointer')=0A=20=20=20,=20false,=205)=20LIMIT=20= 1;=0A-=20=20=20=20=20=20=20name=20=20=20=20=20=20=20|=20ident=20|=20=20=20= type=20=20=20|=20path=20|=20total_bytes=20|=20total_nblocks=20|=20= free_bytes=20|=20free_chunks=20|=20used_bytes=20|=20num_=0A-agg_contexts=20= |=20=20=20=20=20=20=20=20=20stats_timestamp=0A= -------------------+-------+----------+------+-------------+--------------= -+------------+-------------+------------+-----=0A= --------------+----------------------------------=0A-=20TopMemoryContext=20= |=20=20=20=20=20=20=20|=20AllocSet=20|=20{1}=20=20|=20=20=20=20=20=20= 102664=20|=20=20=20=20=20=20=20=20=20=20=20=20=204=20|=20=20=20=20=20=20=20= 3008=20|=20=20=20=20=20=20=20=20=20=20=202=20|=20=20=20=20=20=2099656=20= |=0A-=20=20=20=20=20=20=20=20=20=20=201=20|=202025-03-04=20= 10:01:57.590543+05:30=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|=20= 2880=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|=20= 2025-03-24=2013:55:47.796698+01=0A=20=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=20=0A=20= =0A=20=20=20=0Adiff=20--git=20= a/src/backend/utils/adt/mcxtfuncs.c=20= b/src/backend/utils/adt/mcxtfuncs.c=0Aindex=20462c4e48cf0..f9145b9faaa=20= 100644=0A---=20a/src/backend/utils/adt/mcxtfuncs.c=0A+++=20= b/src/backend/utils/adt/mcxtfuncs.c=0A@@=20-330,7=20+330,7=20@@=20= pg_log_backend_memory_contexts(PG_FUNCTION_ARGS)=0A=20=20*=20to=20a=20= dynamic=20shared=20memory=20space.=0A=20=20*=0A=20=20*=20We=20have=20= defined=20a=20limit=20on=20dsa=20memory=20that=20could=20be=20allocated=20= per=20process=20-=0A-=20*=20if=20the=20process=20has=20more=20memory=20= contexts=20than=20that=20can=20fit=20in=20the=20allocated=0A+=20*=20if=20= the=20process=20has=20more=20memory=20contexts=20than=20what=20can=20fit=20= in=20the=20allocated=0A=20=20*=20size,=20the=20excess=20contexts=20are=20= summarized=20and=20represented=20as=20cumulative=20total=0A=20=20*=20at=20= the=20end=20of=20the=20buffer.=0A=20=20*=0A@@=20-354,6=20+354,7=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09bool=09=09= get_summary=20=3D=20PG_GETARG_BOOL(1);=0A=20=09PGPROC=09=20=20=20*proc;=0A= =20=09ProcNumber=09procNumber=20=3D=20INVALID_PROC_NUMBER;=0A+=09bool=09=09= proc_is_aux=20=3D=20false;=0A=20=09ReturnSetInfo=20*rsinfo=20=3D=20= (ReturnSetInfo=20*)=20fcinfo->resultinfo;=0A=20=09dsa_area=20=20=20= *area;=0A=20=09MemoryContextEntry=20*memctx_info;=0A@@=20-368,25=20= +369,25=20@@=20pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09= if=20(!has_privs_of_role(GetUserId(),=20ROLE_PG_READ_ALL_STATS))=0A=20=09= =09ereport(ERROR,=0A=20=09=09=09=09= errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),=0A-=09=09=09=09= errmsg("memory=20context=20statistics=20privilege=20error"));=0A+=09=09=09= =09errmsg("permission=20denied=20to=20extract=20memory=20context=20= statistics"));=0A=20=0A=20=09InitMaterializedSRF(fcinfo,=200);=0A=20=0A=20= =09/*=0A-=09=20*=20See=20if=20the=20process=20with=20given=20pid=20is=20= a=20backend=20or=20an=20auxiliary=20process.=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=20=09=20*/=0A=20=09proc=20=3D=20= BackendPidGetProc(pid);=0A=20=09if=20(proc=20=3D=3D=20NULL)=0A+=09{=0A=20= =09=09proc=20=3D=20AuxiliaryPidGetProc(pid);=0A+=09=09proc_is_aux=20=3D=20= true;=0A+=09}=0A=20=0A=20=09/*=0A=20=09=20*=20BackendPidGetProc()=20and=20= AuxiliaryPidGetProc()=20return=20NULL=20if=20the=20pid=0A-=09=20*=20= isn't=20valid;=20but=20by=20the=20time=20we=20reach=20kill(),=20a=20= process=20for=20which=20we=0A-=09=20*=20get=20a=20valid=20proc=20here=20= might=20have=20terminated=20on=20its=20own.=20=20There's=20no=20way=0A-=09= =20*=20to=20acquire=20a=20lock=20on=20an=20arbitrary=20process=20to=20= prevent=20that.=20But=20since=0A-=09=20*=20this=20mechanism=20is=20= usually=20used=20to=20debug=20a=20backend=20or=20an=20auxiliary=0A-=09=20= *=20process=20running=20and=20consuming=20lots=20of=20memory,=20that=20= it=20might=20end=20on=20its=0A-=09=20*=20own=20first=20and=20its=20= memory=20contexts=20are=20not=20logged=20is=20not=20a=20problem.=0A+=09=20= *=20isn't=20valid;=20this=20is=20however=20not=20a=20problem=20and=20= leave=20with=20a=20WARNING.=0A+=09=20*=20See=20comment=20in=20= pg_log_backend_memory_contexts=20for=20a=20discussion=20on=20this.=0A=20=09= =20*/=0A=20=09if=20(proc=20=3D=3D=20NULL)=0A=20=09{=0A@@=20-395,8=20= +396,7=20@@=20pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09=09= =20*=20if=20one=20backend=20terminated=20on=20its=20own=20during=20the=20= run.=0A=20=09=09=20*/=0A=20=09=09ereport(WARNING,=0A-=09=09=09=09= (errmsg("PID=20%d=20is=20not=20a=20PostgreSQL=20server=20process",=0A-=09= =09=09=09=09=09pid)));=0A+=09=09=09=09(errmsg("PID=20%d=20is=20not=20a=20= PostgreSQL=20server=20process",=20pid)));=0A=20=09=09PG_RETURN_NULL();=0A= =20=09}=0A=20=0A@@=20-409,8=20+409,8=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09curr_timestamp=20= =3D=20GetCurrentTimestamp();=0A=20=0A=20=09/*=0A-=09=20*=20Send=20a=20= signal=20to=20a=20postgresql=20process,=20informing=20it=20we=20want=20= it=20to=0A-=09=20*=20produce=20information=20about=20memory=20contexts.=0A= +=09=20*=20Send=20a=20signal=20to=20a=20PostgreSQL=20process,=20= informing=20it=20we=20want=20it=20to=0A+=09=20*=20produce=20information=20= about=20its=20memory=20contexts.=0A=20=09=20*/=0A=20=09if=20= (SendProcSignal(pid,=20PROCSIG_GET_MEMORY_CONTEXT,=20procNumber)=20<=20= 0)=0A=20=09{=0A@@=20-442,9=20+442,6=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09=09=20*=20= process=20to=20finish=20publishing=20statistics.=0A=20=09=09=20*/=0A=20=09= =09LWLockAcquire(&memCtxState[procNumber].lw_lock,=20LW_EXCLUSIVE);=0A-=09= =09msecs=20=3D=0A-=09=09=09= TimestampDifferenceMilliseconds(curr_timestamp,=0A-=09=09=09=09=09=09=09=09= =09=09=09memCtxState[procNumber].stats_timestamp);=0A=20=0A=20=09=09/*=0A= =20=09=09=20*=20Note=20in=20procnumber.h=20file=20says=20that=20a=20= procNumber=20can=20be=20re-used=20for=0A@@=20-460,29=20+457,38=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09=09=09=20*=20= statistics=20timestamp=20being=20newer=20than=20the=20current=20request=0A= =20=09=09=09=20*=20timestamp.=0A=20=09=09=09=20*/=0A+=09=09=09msecs=20=3D=20= TimestampDifferenceMilliseconds(curr_timestamp,=0A+=09=09=09=09=09=09=09=09= =09=09=09=09=09memCtxState[procNumber].stats_timestamp);=0A+=0A=20=09=09=09= if=20(DsaPointerIsValid(memCtxState[procNumber].memstats_dsa_pointer)=0A=20= =09=09=09=09&&=20msecs=20>=200)=0A=20=09=09=09=09break;=0A-=0A=20=09=09}=0A= =20=09=09LWLockRelease(&memCtxState[procNumber].lw_lock);=0A=20=0A=20=09=09= /*=0A=20=09=09=20*=20Recheck=20the=20state=20of=20the=20backend=20before=20= sleeping=20on=20the=20condition=0A-=09=09=20*=20variable=0A+=09=09=20*=20= variable=20to=20ensure=20the=20process=20is=20still=20alive.=20=20Only=20= check=20the=0A+=09=09=20*=20relevant=20process=20type=20based=20on=20the=20= earlier=20PID=20check.=0A=20=09=09=20*/=0A-=09=09proc=20=3D=20= BackendPidGetProc(pid);=0A-=0A-#define=20MEMSTATS_WAIT_TIMEOUT=201000=0A= -=09=09if=20(proc=20=3D=3D=20NULL)=0A+=09=09if=20(proc_is_aux)=0A=20=09=09= =09proc=20=3D=20AuxiliaryPidGetProc(pid);=0A+=09=09else=0A+=09=09=09proc=20= =3D=20BackendPidGetProc(pid);=0A+=0A+=09=09/*=0A+=09=09=20*=20The=20= process=20ending=20during=20memory=20context=20processing=20is=20not=20= an=0A+=09=09=20*=20error.=0A+=09=09=20*/=0A=20=09=09if=20(proc=20=3D=3D=20= NULL)=0A=20=09=09{=0A=20=09=09=09ereport(WARNING,=0A-=09=09=09=09=09= errmsg("PID=20%d=20is=20not=20a=20PostgreSQL=20server=20process",=0A-=09=09= =09=09=09=09=20=20=20pid));=0A+=09=09=09=09=09errmsg("PID=20%d=20is=20= not=20a=20PostgreSQL=20server=20process",=20pid));=0A=20=09=09=09= PG_RETURN_NULL();=0A=20=09=09}=0A+=0A+#define=20MEMSTATS_WAIT_TIMEOUT=20= 1000=0A+=0A=20=09=09if=20= (ConditionVariableTimedSleep(&memCtxState[procNumber].memctx_cv,=0A=20=09= =09=09=09=09=09=09=09=09=09MEMSTATS_WAIT_TIMEOUT,=0A=20=09=09=09=09=09=09= =09=09=09=09WAIT_EVENT_MEM_CTX_PUBLISH))=0A@@=20-503,12=20+509,11=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09=09=09=09=09= PG_RETURN_NULL();=0A=20=09=09=09=09}=0A=20=09=09=09}=0A-=09=09=09= ereport(LOG,=0A-=09=09=09=09=09errmsg("Wait=20for=20%d=20process=20to=20= publish=20stats=20timed=20out,=20trying=20again",=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=20=09=09= =09=09=09=09=20=20=20pid));=0A=20=09=09=09num_retries=20=3D=20= num_retries=20+=201;=0A=20=09=09}=0A-=0A=20=09}=0A=20=09/*=20We=20should=20= land=20here=20only=20with=20a=20valid=20DSA=20handle=20*/=0A=20=09= Assert(memCtxArea->memstats_dsa_handle=20!=3D=20DSA_HANDLE_INVALID);=0A= @@=20-519,8=20+524,8=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09=20*=0A=20=09=20= *=20Read=20statistics=20of=20top=20level=201=20and=202=20contexts,=20if=20= get_summary=20is=20true.=0A=20=09=20*/=0A-=09memctx_info=20=3D=20= (MemoryContextEntry=20*)=20dsa_get_address(area,=0A-=09=09=09=09=09=09=09= =09=09=09=09=09=09=09=20memCtxState[procNumber].memstats_dsa_pointer);=0A= +=09memctx_info=20=3D=20(MemoryContextEntry=20*)=0A+=09=09= dsa_get_address(area,=20memCtxState[procNumber].memstats_dsa_pointer);=0A= =20=0A=20#define=20PG_GET_PROCESS_MEMORY_CONTEXTS_COLS=0912=0A=20=09for=20= (int=20i=20=3D=200;=20i=20<=20memCtxState[procNumber].total_stats;=20= i++)=0A@@=20-543,6=20+548,7=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09=09}=0A=20=09=09= else=0A=20=09=09=09nulls[0]=20=3D=20true;=0A+=0A=20=09=09if=20= (DsaPointerIsValid(memctx_info[i].ident))=0A=20=09=09{=0A=20=09=09=09= ident=20=3D=20(char=20*)=20dsa_get_address(area,=20= memctx_info[i].ident);=0A@@=20-563,11=20+569,11=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09=09=09= path_datum_array=20=3D=20(Datum=20*)=20dsa_get_address(area,=20= memctx_info[i].path);=0A=20=09=09=09path_array=20=3D=20= construct_array_builtin(path_datum_array,=0A=20=09=09=09=09=09=09=09=09=09= =09=09=09=20path_length,=20INT4OID);=0A-=0A=20=09=09=09values[3]=20=3D=20= PointerGetDatum(path_array);=0A=20=09=09}=0A=20=09=09else=0A=20=09=09=09= nulls[3]=20=3D=20true;=0A+=0A=20=09=09values[4]=20=3D=20= Int32GetDatum(path_length);=20/*=20level=20*/=0A=20=09=09values[5]=20=3D=20= Int64GetDatum(memctx_info[i].totalspace);=0A=20=09=09values[6]=20=3D=20= Int64GetDatum(memctx_info[i].nblocks);=0A@@=20-589,18=20+595,6=20@@=20= pg_get_process_memory_contexts(PG_FUNCTION_ARGS)=0A=20=09= PG_RETURN_NULL();=0A=20}=0A=20=0A-/*=0A-=20*=20Shared=20memory=20sizing=20= for=20reporting=20memory=20context=20information.=0A-=20*/=0A-static=20= Size=0A-MemCtxShmemSize(void)=0A-{=0A-=09Size=09=09TotalProcs=20=3D=0A-=09= =09add_size(MaxBackends,=20add_size(NUM_AUXILIARY_PROCS,=20= max_prepared_xacts));=0A-=0A-=09return=20mul_size(TotalProcs,=20= sizeof(MemoryContextBackendState));=0A-}=0A-=0A=20/*=0A=20=20*=20Init=20= shared=20memory=20for=20reporting=20memory=20context=20information.=0A=20= =20*/=0A@@=20-608,12=20+602,16=20@@=20void=0A=20= MemCtxBackendShmemInit(void)=0A=20{=0A=20=09bool=09=09found;=0A-=09Size=09= =09TotalProcs=20=3D=0A-=09=09add_size(MaxBackends,=20= add_size(NUM_AUXILIARY_PROCS,=20max_prepared_xacts));=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=20=0A-=09memCtxState=20=3D=20= (MemoryContextBackendState=20*)=20= ShmemInitStruct("MemoryContextBackendState",=0A-=09=09=09=09=09=09=09=09=09= =09=09=09=09=09=09=09MemCtxShmemSize(),=0A-=09=09=09=09=09=09=09=09=09=09= =09=09=09=09=09=09&found);=0A=20=09if=20(!IsUnderPostmaster)=0A=20=09{=0A= =20=09=09Assert(!found);=0A@@=20-622,8=20+620,7=20@@=20= MemCtxBackendShmemInit(void)=0A=20=09=09{=0A=20=09=09=09= ConditionVariableInit(&memCtxState[i].memctx_cv);=0A=20=0A-=09=09=09= LWLockInitialize(&memCtxState[i].lw_lock,=0A-=09=09=09=09=09=09=09=20= LWLockNewTrancheId());=0A+=09=09=09= LWLockInitialize(&memCtxState[i].lw_lock,=20LWLockNewTrancheId());=0A=20=09= =09=09LWLockRegisterTranche(memCtxState[i].lw_lock.tranche,=0A=20=09=09=09= =09=09=09=09=09=20=20"mem_context_backend_stats_reporting");=0A=20=0A@@=20= -637,16=20+634,16=20@@=20MemCtxBackendShmemInit(void)=0A=20}=0A=20=0A=20= /*=0A-=20*=20Initialize=20shared=20memory=20for=20displaying=20memory=0A= -=20*=20context=20statistics=0A+=20*=20Initialize=20shared=20memory=20= for=20displaying=20memory=20context=20statistics=0A=20=20*/=0A=20void=0A=20= MemCtxShmemInit(void)=0A=20{=0A=20=09bool=09=09found;=0A=20=0A-=09= memCtxArea=20=3D=20(MemoryContextState=20*)=20= ShmemInitStruct("MemoryContextState",=20sizeof(MemoryContextState),=0A-=09= =09=09=09=09=09=09=09=09=09=09=09=09=09&found);=0A+=09memCtxArea=20=3D=20= (MemoryContextState=20*)=0A+=09=09ShmemInitStruct("MemoryContextState",=20= sizeof(MemoryContextState),=20&found);=0A+=0A=20=09if=20= (!IsUnderPostmaster)=0A=20=09{=0A=20=09=09Assert(!found);=0Adiff=20--git=20= a/src/backend/utils/mmgr/mcxt.c=20b/src/backend/utils/mmgr/mcxt.c=0A= index=20214330aa7a5..4db48230241=20100644=0A---=20= a/src/backend/utils/mmgr/mcxt.c=0A+++=20b/src/backend/utils/mmgr/mcxt.c=0A= @@=20-19,7=20+19,6=20@@=0A=20=20= *-------------------------------------------------------------------------= =0A=20=20*/=0A=20=0A-#include=20=0A=20#include=20"postgres.h"=0A=20= =0A=20#include=20"mb/pg_wchar.h"=0A@@=20-922,38=20+921,39=20@@=20= MemoryContextStatsInternal(MemoryContext=20context,=20int=20level,=0A=20=09= check_stack_depth();=0A=20=09Assert(MemoryContextIsValid(context));=0A=20= =0A-=09if=20(print_location=20=3D=3D=20PRINT_STATS_TO_STDERR)=0A-=09{=0A= -=09=09/*=20Examine=20the=20context=20itself=20*/=0A-=09=09= context->methods->stats(context,=0A-=09=09=09=09=09=09=09=09= MemoryContextStatsPrint,=0A-=09=09=09=09=09=09=09=09&level,=0A-=09=09=09=09= =09=09=09=09totals,=20true);=0A-=09}=0A-=09else=20if=20(print_location=20= =3D=3D=20PRINT_STATS_TO_LOGS)=0A+=09switch=20(print_location)=0A=20=09{=0A= +=09=09case=20PRINT_STATS_TO_STDERR:=0A+=09=09=09/*=20Examine=20the=20= context=20itself=20*/=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,=20true);=0A+=09=09=09= break;=0A=20=0A-=09=09/*=20Examine=20the=20context=20itself=20*/=0A-=09=09= context->methods->stats(context,=0A-=09=09=09=09=09=09=09=09= MemoryContextStatsPrint,=0A-=09=09=09=09=09=09=09=09&level,=0A-=09=09=09=09= =09=09=09=09totals,=20false);=0A-=09}=0A+=09=09case=20= PRINT_STATS_TO_LOGS:=0A+=09=09=09/*=20Examine=20the=20context=20itself=20= */=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=09break;=0A=20=0A-=09/*=0A= -=09=20*=20Do=20not=20print=20the=20statistics=20if=20print_to_stderr=20= is=20PRINT_STATS_NONE,=0A-=09=20*=20only=20compute=20totals.=20This=20is=20= used=20in=20reporting=20of=20memory=20context=0A-=09=20*=20statistics=20= via=20a=20sql=20function.=20Last=20parameter=20is=20not=20relevant.=0A-=09= =20*/=0A-=09else=0A-=09{=0A-=09=09Assert(print_location=20=3D=3D=20= PRINT_STATS_NONE);=0A-=09=09/*=20Examine=20the=20context=20itself=20*/=0A= -=09=09context->methods->stats(context,=0A-=09=09=09=09=09=09=09=09NULL,=0A= -=09=09=09=09=09=09=09=09NULL,=0A-=09=09=09=09=09=09=09=09totals,=20= false);=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=20=09}=0A+=0A=20=09/*=20Increment=20the=20= context=20count=20for=20each=20of=20the=20recursive=20call=20*/=0A=20=09= *num_contexts=20=3D=20*num_contexts=20+=201;=0A=20=0A@@=20-1601,6=20= +1601,7=20@@=20ProcessGetMemoryContextInterrupt(void)=0A=20=09=09= memCtxState[idx].total_stats=20=3D=20ctx_id;=0A=20=09=09goto=20cleanup;=0A= =20=09}=0A+=0A=20=09foreach_ptr(MemoryContextData,=20cur,=20contexts)=0A=20= =09{=0A=20=09=09List=09=20=20=20*path=20=3D=20NIL;=0A@@=20-1665,6=20= +1666,7=20@@=20ProcessGetMemoryContextInterrupt(void)=0A=20=09=09=20*/=0A= =20=09=09memCtxState[idx].total_stats=20=3D=20num_individual_stats=20+=20= 1;=0A=20=09}=0A+=0A=20cleanup:=0A=20=0A=20=09/*=0A@@=20-1680,8=20+1682,8=20= @@=20cleanup:=0A=20}=0A=20=0A=20/*=0A-=20*=20Append=20the=20transient=20= context_id=20of=20this=20context=20and=20each=20of=0A-=20*=20its=20= ancestors=20to=20a=20list,=20in=20order=20to=20compute=20a=20path.=0A+=20= *=20Append=20the=20transient=20context_id=20of=20this=20context=20and=20= each=20of=20its=20ancestors=0A+=20*=20to=20a=20list,=20in=20order=20to=20= compute=20a=20path.=0A=20=20*/=0A=20static=20List=20*=0A=20= compute_context_path(MemoryContext=20c,=20HTAB=20*context_id_lookup)=0A= @@=20-1763,6=20+1765,8=20@@=20PublishMemoryContext(MemoryContextEntry=20= *memctx_info,=20int=20curr_id,=0A=20=09char=09=20=20=20*ident;=0A=20=09= Datum=09=20=20=20*path_array;=0A=20=0A+=09= Assert(MemoryContextIsValid(context));=0A+=0A=20=09if=20(context->name=20= !=3D=20NULL)=0A=20=09{=0A=20=09=09Assert(strlen(context->name)=20<=20= MEMORY_CONTEXT_IDENT_SHMEM_SIZE);=0A@@=20-1817,6=20+1821,7=20@@=20= PublishMemoryContext(MemoryContextEntry=20*memctx_info,=20int=20curr_id,=0A= =20=09}=0A=20=09else=0A=20=09=09memctx_info[curr_id].ident=20=3D=20= InvalidDsaPointer;=0A+=0A=20=09/*=20Allocate=20dsa=20memory=20for=20= storing=20path=20information=20*/=0A=20=09if=20(path=20=3D=3D=20NIL)=0A=20= =09=09memctx_info[curr_id].path=20=3D=20InvalidDsaPointer;=0A@@=20= -1869,11=20+1874,11=20@@=20AtProcExit_memstats_dsa_free(int=20code,=20= Datum=20arg)=0A=20=09dsm_segment=20*dsm_seg=20=3D=20NULL;=0A=20=09= dsa_area=20=20=20*area=20=3D=20NULL;=0A=20=0A-=09if=20= (memCtxArea->memstats_dsa_handle=20!=3D=20DSA_HANDLE_INVALID)=0A-=09=09= dsm_seg=20=3D=20dsm_find_mapping(memCtxArea->memstats_dsa_handle);=0A-=09= else=0A+=09if=20(memCtxArea->memstats_dsa_handle=20=3D=3D=20= DSA_HANDLE_INVALID)=0A=20=09=09return;=0A=20=0A+=09dsm_seg=20=3D=20= dsm_find_mapping(memCtxArea->memstats_dsa_handle);=0A+=0A=20=09= LWLockAcquire(&memCtxState[idx].lw_lock,=20LW_EXCLUSIVE);=0A=20=0A=20=09= if=20(!DsaPointerIsValid(memCtxState[idx].memstats_dsa_pointer))=0A@@=20= -1883,10=20+1888,9=20@@=20AtProcExit_memstats_dsa_free(int=20code,=20= Datum=20arg)=0A=20=09}=0A=20=0A=20=09/*=20If=20the=20dsm=20mapping=20= could=20not=20be=20found,=20attach=20to=20the=20area=20*/=0A-=09if=20= (dsm_seg=20=3D=3D=20NULL)=0A-=09=09area=20=3D=20= dsa_attach(memCtxArea->memstats_dsa_handle);=0A-=09else=0A+=09if=20= (dsm_seg=20!=3D=20NULL)=0A=20=09=09return;=0A+=09area=20=3D=20= dsa_attach(memCtxArea->memstats_dsa_handle);=0A=20=0A=20=09/*=0A=20=09=20= *=20Free=20the=20memory=20context=20statistics,=20free=20the=20name,=20= ident=20and=20path=0A--=20=0A2.39.3=20(Apple=20Git-146)=0A=0A= --Apple-Mail=_85513A8F-54AD-4F62-B91C-5F6D88A33786 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=us-ascii --Apple-Mail=_85513A8F-54AD-4F62-B91C-5F6D88A33786--