Generate automatically code and documentation related to wait events
authorMichael Paquier <michael@paquier.xyz>
Wed, 5 Jul 2023 01:53:11 +0000 (10:53 +0900)
committerMichael Paquier <michael@paquier.xyz>
Wed, 5 Jul 2023 01:53:11 +0000 (10:53 +0900)
The documentation and the code is generated automatically from a new
file called wait_event_names.txt, formatted in sections dedicated to
each wait event class (Timeout, Lock, IO, etc.) with three tab-separated
fields:
- C symbol in enums
- Format in the system views
- Description in the docs

Using this approach has several advantages, as we have proved to be
rather bad in maintaining this area of the tree across the years:
- The order of each item in the documentation and the code, which should
be alphabetical, has become incorrect multiple times, and the script
generating the code and documentation has a few rules to enforce that,
making the maintenance a no-brainer.
- Some wait events were added to the code, but not documented, so this
cannot be missed now.
- The order of the tables for each wait event class is enforced in the
documentation (the input .txt file does so as well for clarity, though
this is not mandatory).
- Less code, shaving 1.2k lines from the tree, with 1/3 of the savings
coming from the code, the rest from the documentation.

The wait event types "Lock" and "LWLock" still have their own code path
for their code, hence only the documentation is created for them.  These
classes are listed with a special marker called WAIT_EVENT_DOCONLY in
the input file.

Adding a new wait event now requires only an update of
wait_event_names.txt, with "Lock" and "LWLock" treated as exceptions.

This commit has been tested with configure/Makefile, the CI and VPATH
build.  clean, distclean and maintainer-clean were working fine.

Author: Bertrand Drouvot, Michael Paquier
Discussion: https://postgr.es/m/77a86b3a-c4a8-5f5d-69b9-d70bbf2e9b98@gmail.com

22 files changed:
doc/src/sgml/.gitignore
doc/src/sgml/Makefile
doc/src/sgml/filelist.sgml
doc/src/sgml/meson.build
doc/src/sgml/monitoring.sgml
src/backend/Makefile
src/backend/storage/lmgr/lwlocknames.txt
src/backend/utils/activity/.gitignore [new file with mode: 0644]
src/backend/utils/activity/Makefile
src/backend/utils/activity/generate-wait_event_types.pl [new file with mode: 0644]
src/backend/utils/activity/meson.build
src/backend/utils/activity/wait_event.c
src/backend/utils/activity/wait_event_names.txt [new file with mode: 0644]
src/backend/utils/adt/lockfuncs.c
src/common/meson.build
src/include/Makefile
src/include/utils/.gitignore
src/include/utils/meson.build
src/include/utils/wait_event.h
src/test/ssl/t/002_scram.pl
src/tools/msvc/Solution.pm
src/tools/msvc/clean.bat

index d8e3dab3380a806d996e617132ac81acc1fa4f05..1ccb72227e2e95e1f001ffccebeb555fddbc8413 100644 (file)
@@ -17,6 +17,7 @@
 /errcodes-table.sgml
 /keywords-table.sgml
 /version.sgml
+/wait_event_types.sgml
 # Assorted byproducts from building the above
 /postgres-full.xml
 /INSTALL.html
index 71cbef230f34a6ad6b41a667c7d2977fb6560378..1e55e531dbfd9a4b64c654ce5f9c45da1f547b3d 100644 (file)
@@ -58,7 +58,7 @@ override XSLTPROCFLAGS += --stringparam pg.version '$(VERSION)'
 
 GENERATED_SGML = version.sgml \
        features-supported.sgml features-unsupported.sgml errcodes-table.sgml \
-       keywords-table.sgml
+       keywords-table.sgml wait_event_types.sgml
 
 ALLSGML := $(wildcard $(srcdir)/*.sgml $(srcdir)/ref/*.sgml) $(GENERATED_SGML)
 
@@ -111,6 +111,8 @@ errcodes-table.sgml: $(top_srcdir)/src/backend/utils/errcodes.txt generate-errco
 keywords-table.sgml: $(top_srcdir)/src/include/parser/kwlist.h $(wildcard $(srcdir)/keywords/sql*.txt) generate-keywords-table.pl
        $(PERL) $(srcdir)/generate-keywords-table.pl $(srcdir) > $@
 
+wait_event_types.sgml: $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl
+       $(PERL) $(top_srcdir)/src/backend/utils/activity/generate-wait_event_types.pl --docs $<
 
 ##
 ## Generation of some text files.
index 5465f9a46d6e0ba14906d4c4b12e302bddaabf85..63b0fc2a469de6106376346674b41996fe0191fa 100644 (file)
@@ -42,6 +42,7 @@
 <!ENTITY maintenance   SYSTEM "maintenance.sgml">
 <!ENTITY manage-ag     SYSTEM "manage-ag.sgml">
 <!ENTITY monitoring    SYSTEM "monitoring.sgml">
+<!ENTITY wait_event_types    SYSTEM "wait_event_types.sgml">
 <!ENTITY regress       SYSTEM "regress.sgml">
 <!ENTITY runtime       SYSTEM "runtime.sgml">
 <!ENTITY config        SYSTEM "config.sgml">
index c6d77b5a1504c9f8b8d25aaac4db403064938dc5..16c1aa980c90cceee801ab1c9a78fc9963a02d01 100644 (file)
@@ -46,6 +46,18 @@ doc_generated += custom_target('errcodes-table.sgml',
   capture: true,
 )
 
+doc_generated += custom_target('wait_event_types.sgml',
+  input: files(
+    '../../../src/backend/utils/activity/wait_event_names.txt'),
+  output: 'wait_event_types.sgml',
+  command: [perl,
+    files('../../../src/backend/utils/activity/generate-wait_event_types.pl'),
+    '--outdir', '@OUTDIR@', '--docs', '@INPUT@'],
+  build_by_default: false,
+  install: false,
+  capture: false,
+)
+
 # FIXME: this actually has further inputs, adding depfile support to
 # generate-keywords-table.pl is probably the best way to address that
 # robustly.
index 5cfdc70c03fd1a1cf7511406251740fe7492924c..506aeaa87999349be717180da69a5482c35e4686 100644 (file)
@@ -1100,1266 +1100,7 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
    </tgroup>
   </table>
 
-  <table id="wait-event-activity-table">
-   <title>Wait Events of Type <literal>Activity</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Activity</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>ArchiverMain</literal></entry>
-      <entry>Waiting in main loop of archiver process.</entry>
-     </row>
-     <row>
-      <entry><literal>AutoVacuumMain</literal></entry>
-      <entry>Waiting in main loop of autovacuum launcher process.</entry>
-     </row>
-     <row>
-      <entry><literal>BgWriterHibernate</literal></entry>
-      <entry>Waiting in background writer process, hibernating.</entry>
-     </row>
-     <row>
-      <entry><literal>BgWriterMain</literal></entry>
-      <entry>Waiting in main loop of background writer process.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointerMain</literal></entry>
-      <entry>Waiting in main loop of checkpointer process.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalApplyMain</literal></entry>
-      <entry>Waiting in main loop of logical replication apply process.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalLauncherMain</literal></entry>
-      <entry>Waiting in main loop of logical replication launcher process.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalParallelApplyMain</literal></entry>
-      <entry>Waiting in main loop of logical replication parallel apply
-       process.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryWalStream</literal></entry>
-      <entry>Waiting in main loop of startup process for WAL to arrive, during
-       streaming recovery.</entry>
-     </row>
-     <row>
-      <entry><literal>SysLoggerMain</literal></entry>
-      <entry>Waiting in main loop of syslogger process.</entry>
-     </row>
-     <row>
-      <entry><literal>WalReceiverMain</literal></entry>
-      <entry>Waiting in main loop of WAL receiver process.</entry>
-     </row>
-     <row>
-      <entry><literal>WalSenderMain</literal></entry>
-      <entry>Waiting in main loop of WAL sender process.</entry>
-     </row>
-     <row>
-      <entry><literal>WalWriterMain</literal></entry>
-      <entry>Waiting in main loop of WAL writer process.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-bufferpin-table">
-   <title>Wait Events of Type <literal>BufferPin</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>BufferPin</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>BufferPin</literal></entry>
-      <entry>Waiting to acquire an exclusive pin on a buffer.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-client-table">
-   <title>Wait Events of Type <literal>Client</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Client</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>ClientRead</literal></entry>
-      <entry>Waiting to read data from the client.</entry>
-     </row>
-     <row>
-      <entry><literal>ClientWrite</literal></entry>
-      <entry>Waiting to write data to the client.</entry>
-     </row>
-     <row>
-      <entry><literal>GSSOpenServer</literal></entry>
-      <entry>Waiting to read data from the client while establishing a GSSAPI
-       session.</entry>
-     </row>
-     <row>
-      <entry><literal>LibPQWalReceiverConnect</literal></entry>
-      <entry>Waiting in WAL receiver to establish connection to remote
-       server.</entry>
-     </row>
-     <row>
-      <entry><literal>LibPQWalReceiverReceive</literal></entry>
-      <entry>Waiting in WAL receiver to receive data from remote server.</entry>
-     </row>
-     <row>
-      <entry><literal>SSLOpenServer</literal></entry>
-      <entry>Waiting for SSL while attempting connection.</entry>
-     </row>
-     <row>
-      <entry><literal>WalSenderWaitForWAL</literal></entry>
-      <entry>Waiting for WAL to be flushed in WAL sender process.</entry>
-     </row>
-     <row>
-      <entry><literal>WalSenderWriteData</literal></entry>
-      <entry>Waiting for any activity when processing replies from WAL
-       receiver in WAL sender process.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-extension-table">
-   <title>Wait Events of Type <literal>Extension</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Extension</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>Extension</literal></entry>
-      <entry>Waiting in an extension.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-io-table">
-   <title>Wait Events of Type <literal>IO</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>IO</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>BaseBackupRead</literal></entry>
-      <entry>Waiting for base backup to read from a file.</entry>
-     </row>
-     <row>
-      <entry><literal>BaseBackupSync</literal></entry>
-      <entry>Waiting for data written by a base backup to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>BaseBackupWrite</literal></entry>
-      <entry>Waiting for base backup to write to a file.</entry>
-     </row>
-     <row>
-      <entry><literal>BufFileRead</literal></entry>
-      <entry>Waiting for a read from a buffered file.</entry>
-     </row>
-     <row>
-      <entry><literal>BufFileTruncate</literal></entry>
-      <entry>Waiting for a buffered file to be truncated.</entry>
-     </row>
-     <row>
-      <entry><literal>BufFileWrite</literal></entry>
-      <entry>Waiting for a write to a buffered file.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileRead</literal></entry>
-      <entry>Waiting for a read from the <filename>pg_control</filename>
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileSync</literal></entry>
-      <entry>Waiting for the <filename>pg_control</filename> file to reach
-       durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileSyncUpdate</literal></entry>
-      <entry>Waiting for an update to the <filename>pg_control</filename> file
-       to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileWrite</literal></entry>
-      <entry>Waiting for a write to the <filename>pg_control</filename>
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFileWriteUpdate</literal></entry>
-      <entry>Waiting for a write to update the <filename>pg_control</filename>
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>CopyFileRead</literal></entry>
-      <entry>Waiting for a read during a file copy operation.</entry>
-     </row>
-     <row>
-      <entry><literal>CopyFileWrite</literal></entry>
-      <entry>Waiting for a write during a file copy operation.</entry>
-     </row>
-     <row>
-      <entry><literal>DSMAllocate</literal></entry>
-      <entry>Waiting for a dynamic shared memory segment to be
-       allocated.</entry>
-     </row>
-     <row>
-      <entry><literal>DSMFillZeroWrite</literal></entry>
-      <entry>Waiting to fill a dynamic shared memory backing file with
-       zeroes.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileExtend</literal></entry>
-      <entry>Waiting for a relation data file to be extended.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileFlush</literal></entry>
-      <entry>Waiting for a relation data file to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileImmediateSync</literal></entry>
-      <entry>Waiting for an immediate synchronization of a relation data file to
-       durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFilePrefetch</literal></entry>
-      <entry>Waiting for an asynchronous prefetch from a relation data
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileRead</literal></entry>
-      <entry>Waiting for a read from a relation data file.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileSync</literal></entry>
-      <entry>Waiting for changes to a relation data file to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileTruncate</literal></entry>
-      <entry>Waiting for a relation data file to be truncated.</entry>
-     </row>
-     <row>
-      <entry><literal>DataFileWrite</literal></entry>
-      <entry>Waiting for a write to a relation data file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileAddToDataDirRead</literal></entry>
-      <entry>Waiting for a read while adding a line to the data directory lock
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileAddToDataDirSync</literal></entry>
-      <entry>Waiting for data to reach durable storage while adding a line to the
-       data directory lock file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileAddToDataDirWrite</literal></entry>
-      <entry>Waiting for a write while adding a line to the data directory
-       lock file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileCreateRead</literal></entry>
-      <entry>Waiting to read while creating the data directory lock
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileCreateSync</literal></entry>
-      <entry>Waiting for data to reach durable storage while creating the data
-       directory lock file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileCreateWrite</literal></entry>
-      <entry>Waiting for a write while creating the data directory lock
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFileReCheckDataDirRead</literal></entry>
-      <entry>Waiting for a read during recheck of the data directory lock
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteCheckpointSync</literal></entry>
-      <entry>Waiting for logical rewrite mappings to reach durable storage
-       during a checkpoint.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteMappingSync</literal></entry>
-      <entry>Waiting for mapping data to reach durable storage during a logical
-       rewrite.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteMappingWrite</literal></entry>
-      <entry>Waiting for a write of mapping data during a logical
-       rewrite.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteSync</literal></entry>
-      <entry>Waiting for logical rewrite mappings to reach durable
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteTruncate</literal></entry>
-      <entry>Waiting for truncate of mapping data during a logical
-       rewrite.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRewriteWrite</literal></entry>
-      <entry>Waiting for a write of logical rewrite mappings.</entry>
-     </row>
-     <row>
-      <entry><literal>RelationMapRead</literal></entry>
-      <entry>Waiting for a read of the relation map file.</entry>
-     </row>
-     <row>
-      <entry><literal>RelationMapReplace</literal></entry>
-      <entry>Waiting for durable replacement of a relation map file.</entry>
-     </row>
-     <row>
-      <entry><literal>RelationMapWrite</literal></entry>
-      <entry>Waiting for a write to the relation map file.</entry>
-     </row>
-     <row>
-      <entry><literal>ReorderBufferRead</literal></entry>
-      <entry>Waiting for a read during reorder buffer management.</entry>
-     </row>
-     <row>
-      <entry><literal>ReorderBufferWrite</literal></entry>
-      <entry>Waiting for a write during reorder buffer management.</entry>
-     </row>
-     <row>
-      <entry><literal>ReorderLogicalMappingRead</literal></entry>
-      <entry>Waiting for a read of a logical mapping during reorder buffer
-       management.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotRead</literal></entry>
-      <entry>Waiting for a read from a replication slot control file.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotRestoreSync</literal></entry>
-      <entry>Waiting for a replication slot control file to reach durable storage
-       while restoring it to memory.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotSync</literal></entry>
-      <entry>Waiting for a replication slot control file to reach durable
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotWrite</literal></entry>
-      <entry>Waiting for a write to a replication slot control file.</entry>
-     </row>
-     <row>
-      <entry><literal>SLRUFlushSync</literal></entry>
-      <entry>Waiting for SLRU data to reach durable storage during a checkpoint
-       or database shutdown.</entry>
-     </row>
-     <row>
-      <entry><literal>SLRURead</literal></entry>
-      <entry>Waiting for a read of an SLRU page.</entry>
-     </row>
-     <row>
-      <entry><literal>SLRUSync</literal></entry>
-      <entry>Waiting for SLRU data to reach durable storage following a page
-       write.</entry>
-     </row>
-     <row>
-      <entry><literal>SLRUWrite</literal></entry>
-      <entry>Waiting for a write of an SLRU page.</entry>
-     </row>
-     <row>
-      <entry><literal>SnapbuildRead</literal></entry>
-      <entry>Waiting for a read of a serialized historical catalog
-       snapshot.</entry>
-     </row>
-     <row>
-      <entry><literal>SnapbuildSync</literal></entry>
-      <entry>Waiting for a serialized historical catalog snapshot to reach
-       durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>SnapbuildWrite</literal></entry>
-      <entry>Waiting for a write of a serialized historical catalog
-       snapshot.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistoryFileSync</literal></entry>
-      <entry>Waiting for a timeline history file received via streaming
-       replication to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistoryFileWrite</literal></entry>
-      <entry>Waiting for a write of a timeline history file received via
-       streaming replication.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistoryRead</literal></entry>
-      <entry>Waiting for a read of a timeline history file.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistorySync</literal></entry>
-      <entry>Waiting for a newly created timeline history file to reach durable
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>TimelineHistoryWrite</literal></entry>
-      <entry>Waiting for a write of a newly created timeline history
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>TwophaseFileRead</literal></entry>
-      <entry>Waiting for a read of a two phase state file.</entry>
-     </row>
-     <row>
-      <entry><literal>TwophaseFileSync</literal></entry>
-      <entry>Waiting for a two phase state file to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>TwophaseFileWrite</literal></entry>
-      <entry>Waiting for a write of a two phase state file.</entry>
-     </row>
-     <row>
-      <entry><literal>VersionFileWrite</literal></entry>
-      <entry>Waiting for the version file to be written while creating a database.</entry>
-     </row>
-     <row>
-      <entry><literal>WALBootstrapSync</literal></entry>
-      <entry>Waiting for WAL to reach durable storage during
-       bootstrapping.</entry>
-     </row>
-     <row>
-      <entry><literal>WALBootstrapWrite</literal></entry>
-      <entry>Waiting for a write of a WAL page during bootstrapping.</entry>
-     </row>
-     <row>
-      <entry><literal>WALCopyRead</literal></entry>
-      <entry>Waiting for a read when creating a new WAL segment by copying an
-       existing one.</entry>
-     </row>
-     <row>
-      <entry><literal>WALCopySync</literal></entry>
-      <entry>Waiting for a new WAL segment created by copying an existing one to
-       reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>WALCopyWrite</literal></entry>
-      <entry>Waiting for a write when creating a new WAL segment by copying an
-       existing one.</entry>
-     </row>
-     <row>
-      <entry><literal>WALInitSync</literal></entry>
-      <entry>Waiting for a newly initialized WAL file to reach durable
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>WALInitWrite</literal></entry>
-      <entry>Waiting for a write while initializing a new WAL file.</entry>
-     </row>
-     <row>
-      <entry><literal>WALRead</literal></entry>
-      <entry>Waiting for a read from a WAL file.</entry>
-     </row>
-     <row>
-      <entry><literal>WALSenderTimelineHistoryRead</literal></entry>
-      <entry>Waiting for a read from a timeline history file during a walsender
-       timeline command.</entry>
-     </row>
-     <row>
-      <entry><literal>WALSync</literal></entry>
-      <entry>Waiting for a WAL file to reach durable storage.</entry>
-     </row>
-     <row>
-      <entry><literal>WALSyncMethodAssign</literal></entry>
-      <entry>Waiting for data to reach durable storage while assigning a new
-       WAL sync method.</entry>
-     </row>
-     <row>
-      <entry><literal>WALWrite</literal></entry>
-      <entry>Waiting for a write to a WAL file.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-ipc-table">
-   <title>Wait Events of Type <literal>IPC</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>IPC</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>AppendReady</literal></entry>
-      <entry>Waiting for subplan nodes of an <literal>Append</literal> plan
-       node to be ready.</entry>
-     </row>
-     <row>
-      <entry><literal>ArchiveCleanupCommand</literal></entry>
-      <entry>Waiting for <xref linkend="guc-archive-cleanup-command"/> to
-       complete.</entry>
-     </row>
-     <row>
-      <entry><literal>ArchiveCommand</literal></entry>
-      <entry>Waiting for <xref linkend="guc-archive-command"/> to
-       complete.</entry>
-     </row>
-     <row>
-      <entry><literal>BackendTermination</literal></entry>
-      <entry>Waiting for the termination of another backend.</entry>
-     </row>
-     <row>
-      <entry><literal>BackupWaitWalArchive</literal></entry>
-      <entry>Waiting for WAL files required for a backup to be successfully
-       archived.</entry>
-     </row>
-     <row>
-      <entry><literal>BgWorkerShutdown</literal></entry>
-      <entry>Waiting for background worker to shut down.</entry>
-     </row>
-     <row>
-      <entry><literal>BgWorkerStartup</literal></entry>
-      <entry>Waiting for background worker to start up.</entry>
-     </row>
-     <row>
-      <entry><literal>BtreePage</literal></entry>
-      <entry>Waiting for the page number needed to continue a parallel B-tree
-       scan to become available.</entry>
-     </row>
-     <row>
-      <entry><literal>BufferIO</literal></entry>
-      <entry>Waiting for buffer I/O to complete.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointDone</literal></entry>
-      <entry>Waiting for a checkpoint to complete.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointStart</literal></entry>
-      <entry>Waiting for a checkpoint to start.</entry>
-     </row>
-     <row>
-      <entry><literal>ExecuteGather</literal></entry>
-      <entry>Waiting for activity from a child process while
-       executing a <literal>Gather</literal> plan node.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBatchAllocate</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to allocate a hash
-       table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBatchElect</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to allocate a hash
-       table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBatchLoad</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish loading a
-       hash table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBuildAllocate</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to allocate the
-       initial hash table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBuildElect</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to allocate the
-       initial hash table.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBuildHashInner</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish hashing the
-       inner relation.</entry>
-     </row>
-     <row>
-      <entry><literal>HashBuildHashOuter</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish partitioning
-       the outer relation.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesDecide</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to decide on future
-       batch growth.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesElect</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to allocate more
-       batches.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesFinish</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to decide on
-       future batch growth.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesReallocate</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to allocate more
-       batches.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBatchesRepartition</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish
-       repartitioning.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBucketsElect</literal></entry>
-      <entry>Waiting to elect a Parallel Hash participant to allocate more
-       buckets.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBucketsReallocate</literal></entry>
-      <entry>Waiting for an elected Parallel Hash participant to finish
-       allocating more buckets.</entry>
-     </row>
-     <row>
-      <entry><literal>HashGrowBucketsReinsert</literal></entry>
-      <entry>Waiting for other Parallel Hash participants to finish inserting
-       tuples into new buckets.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalApplySendData</literal></entry>
-      <entry>Waiting for a logical replication leader apply process to send
-       data to a parallel apply process.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalParallelApplyStateChange</literal></entry>
-      <entry>Waiting for a logical replication parallel apply process to change
-       state.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalSyncData</literal></entry>
-      <entry>Waiting for a logical replication remote server to send data for
-       initial table synchronization.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalSyncStateChange</literal></entry>
-      <entry>Waiting for a logical replication remote server to change
-       state.</entry>
-     </row>
-     <row>
-      <entry><literal>MessageQueueInternal</literal></entry>
-      <entry>Waiting for another process to be attached to a shared message
-       queue.</entry>
-     </row>
-     <row>
-      <entry><literal>MessageQueuePutMessage</literal></entry>
-      <entry>Waiting to write a protocol message to a shared message queue.</entry>
-     </row>
-     <row>
-      <entry><literal>MessageQueueReceive</literal></entry>
-      <entry>Waiting to receive bytes from a shared message queue.</entry>
-     </row>
-     <row>
-      <entry><literal>MessageQueueSend</literal></entry>
-      <entry>Waiting to send bytes to a shared message queue.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelBitmapScan</literal></entry>
-      <entry>Waiting for parallel bitmap scan to become initialized.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelCreateIndexScan</literal></entry>
-      <entry>Waiting for parallel <command>CREATE INDEX</command> workers to
-       finish heap scan.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelFinish</literal></entry>
-      <entry>Waiting for parallel workers to finish computing.</entry>
-     </row>
-     <row>
-      <entry><literal>ProcArrayGroupUpdate</literal></entry>
-      <entry>Waiting for the group leader to clear the transaction ID at
-       end of a parallel operation.</entry>
-     </row>
-     <row>
-      <entry><literal>ProcSignalBarrier</literal></entry>
-      <entry>Waiting for a barrier event to be processed by all
-       backends.</entry>
-     </row>
-     <row>
-      <entry><literal>Promote</literal></entry>
-      <entry>Waiting for standby promotion.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryConflictSnapshot</literal></entry>
-      <entry>Waiting for recovery conflict resolution for a vacuum
-       cleanup.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryConflictTablespace</literal></entry>
-      <entry>Waiting for recovery conflict resolution for dropping a
-       tablespace.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryEndCommand</literal></entry>
-      <entry>Waiting for <xref linkend="guc-recovery-end-command"/> to
-       complete.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryPause</literal></entry>
-      <entry>Waiting for recovery to be resumed.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationOriginDrop</literal></entry>
-      <entry>Waiting for a replication origin to become inactive so it can be
-       dropped.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotDrop</literal></entry>
-      <entry>Waiting for a replication slot to become inactive so it can be
-       dropped.</entry>
-     </row>
-     <row>
-      <entry><literal>RestoreCommand</literal></entry>
-      <entry>Waiting for <xref linkend="guc-restore-command"/> to
-       complete.</entry>
-     </row>
-     <row>
-      <entry><literal>SafeSnapshot</literal></entry>
-      <entry>Waiting to obtain a valid snapshot for a <literal>READ ONLY
-       DEFERRABLE</literal> transaction.</entry>
-     </row>
-     <row>
-      <entry><literal>SyncRep</literal></entry>
-      <entry>Waiting for confirmation from a remote server during synchronous
-       replication.</entry>
-     </row>
-     <row>
-      <entry><literal>WalReceiverExit</literal></entry>
-      <entry>Waiting for the WAL receiver to exit.</entry>
-     </row>
-     <row>
-      <entry><literal>WalReceiverWaitStart</literal></entry>
-      <entry>Waiting for startup process to send initial data for streaming
-       replication.</entry>
-     </row>
-     <row>
-      <entry><literal>XactGroupUpdate</literal></entry>
-      <entry>Waiting for the group leader to update transaction status at
-       end of a parallel operation.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-lock-table">
-   <title>Wait Events of Type <literal>Lock</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Lock</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>advisory</literal></entry>
-      <entry>Waiting to acquire an advisory user lock.</entry>
-     </row>
-     <row>
-      <entry><literal>applytransaction</literal></entry>
-      <entry>Waiting to acquire a lock on a remote transaction being applied
-      by a logical replication subscriber.</entry>
-     </row>
-     <row>
-      <entry><literal>extend</literal></entry>
-      <entry>Waiting to extend a relation.</entry>
-     </row>
-     <row>
-      <entry><literal>frozenid</literal></entry>
-      <entry>Waiting to
-       update <structname>pg_database</structname>.<structfield>datfrozenxid</structfield>
-       and <structname>pg_database</structname>.<structfield>datminmxid</structfield>.</entry>
-     </row>
-     <row>
-      <entry><literal>object</literal></entry>
-      <entry>Waiting to acquire a lock on a non-relation database object.</entry>
-     </row>
-     <row>
-      <entry><literal>page</literal></entry>
-      <entry>Waiting to acquire a lock on a page of a relation.</entry>
-     </row>
-     <row>
-      <entry><literal>relation</literal></entry>
-      <entry>Waiting to acquire a lock on a relation.</entry>
-     </row>
-     <row>
-      <entry><literal>spectoken</literal></entry>
-      <entry>Waiting to acquire a speculative insertion lock.</entry>
-     </row>
-     <row>
-      <entry><literal>transactionid</literal></entry>
-      <entry>Waiting for a transaction to finish.</entry>
-     </row>
-     <row>
-      <entry><literal>tuple</literal></entry>
-      <entry>Waiting to acquire a lock on a tuple.</entry>
-     </row>
-     <row>
-      <entry><literal>userlock</literal></entry>
-      <entry>Waiting to acquire a user lock.</entry>
-     </row>
-     <row>
-      <entry><literal>virtualxid</literal></entry>
-      <entry>Waiting to acquire a virtual transaction ID lock;  see
-      <xref linkend="transaction-id"/>.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-  <table id="wait-event-lwlock-table">
-   <title>Wait Events of Type <literal>LWLock</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>LWLock</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>AddinShmemInit</literal></entry>
-      <entry>Waiting to manage an extension's space allocation in shared
-       memory.</entry>
-     </row>
-     <row>
-      <entry><literal>AutoFile</literal></entry>
-      <entry>Waiting to update the <filename>postgresql.auto.conf</filename>
-       file.</entry>
-     </row>
-     <row>
-      <entry><literal>Autovacuum</literal></entry>
-      <entry>Waiting to read or update the current state of autovacuum
-       workers.</entry>
-     </row>
-     <row>
-      <entry><literal>AutovacuumSchedule</literal></entry>
-      <entry>Waiting to ensure that a table selected for autovacuum
-       still needs vacuuming.</entry>
-     </row>
-     <row>
-      <entry><literal>BackgroundWorker</literal></entry>
-      <entry>Waiting to read or update background worker state.</entry>
-     </row>
-     <row>
-      <entry><literal>BtreeVacuum</literal></entry>
-      <entry>Waiting to read or update vacuum-related information for a
-       B-tree index.</entry>
-     </row>
-     <row>
-      <entry><literal>BufferContent</literal></entry>
-      <entry>Waiting to access a data page in memory.</entry>
-     </row>
-     <row>
-      <entry><literal>BufferMapping</literal></entry>
-      <entry>Waiting to associate a data block with a buffer in the buffer
-       pool.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointerComm</literal></entry>
-      <entry>Waiting to manage fsync requests.</entry>
-     </row>
-     <row>
-      <entry><literal>CommitTs</literal></entry>
-      <entry>Waiting to read or update the last value set for a
-       transaction commit timestamp.</entry>
-     </row>
-     <row>
-      <entry><literal>CommitTsBuffer</literal></entry>
-      <entry>Waiting for I/O on a commit timestamp SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>CommitTsSLRU</literal></entry>
-      <entry>Waiting to access the commit timestamp SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>ControlFile</literal></entry>
-      <entry>Waiting to read or update the <filename>pg_control</filename>
-       file or create a new WAL file.</entry>
-     </row>
-     <row>
-      <entry><literal>DynamicSharedMemoryControl</literal></entry>
-      <entry>Waiting to read or update dynamic shared memory allocation
-       information.</entry>
-     </row>
-     <row>
-      <entry><literal>LockFastPath</literal></entry>
-      <entry>Waiting to read or update a process' fast-path lock
-       information.</entry>
-     </row>
-     <row>
-      <entry><literal>LockManager</literal></entry>
-      <entry>Waiting to read or update information
-       about <quote>heavyweight</quote> locks.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRepLauncherDSA</literal></entry>
-      <entry>Waiting to access logical replication launcher's dynamic shared
-       memory allocator.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRepLauncherHash</literal></entry>
-      <entry>Waiting to access logical replication launcher's shared
-       hash table.</entry>
-     </row>
-     <row>
-      <entry><literal>LogicalRepWorker</literal></entry>
-      <entry>Waiting to read or update the state of logical replication
-       workers.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactGen</literal></entry>
-      <entry>Waiting to read or update shared multixact state.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactMemberBuffer</literal></entry>
-      <entry>Waiting for I/O on a multixact member SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactMemberSLRU</literal></entry>
-      <entry>Waiting to access the multixact member SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactOffsetBuffer</literal></entry>
-      <entry>Waiting for I/O on a multixact offset SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactOffsetSLRU</literal></entry>
-      <entry>Waiting to access the multixact offset SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>MultiXactTruncation</literal></entry>
-      <entry>Waiting to read or truncate multixact information.</entry>
-     </row>
-     <row>
-      <entry><literal>NotifyBuffer</literal></entry>
-      <entry>Waiting for I/O on a <command>NOTIFY</command> message SLRU
-       buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>NotifyQueue</literal></entry>
-      <entry>Waiting to read or update <command>NOTIFY</command> messages.</entry>
-     </row>
-     <row>
-      <entry><literal>NotifyQueueTail</literal></entry>
-      <entry>Waiting to update limit on <command>NOTIFY</command> message
-       storage.</entry>
-     </row>
-     <row>
-      <entry><literal>NotifySLRU</literal></entry>
-      <entry>Waiting to access the <command>NOTIFY</command> message SLRU
-       cache.</entry>
-     </row>
-     <row>
-      <entry><literal>OidGen</literal></entry>
-      <entry>Waiting to allocate a new OID.</entry>
-     </row>
-     <row>
-      <entry><literal>OldSnapshotTimeMap</literal></entry>
-      <entry>Waiting to read or update old snapshot control information.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelAppend</literal></entry>
-      <entry>Waiting to choose the next subplan during Parallel Append plan
-       execution.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelHashJoin</literal></entry>
-      <entry>Waiting to synchronize workers during Parallel Hash Join plan
-       execution.</entry>
-     </row>
-     <row>
-      <entry><literal>ParallelQueryDSA</literal></entry>
-      <entry>Waiting for parallel query dynamic shared memory allocation.</entry>
-     </row>
-     <row>
-      <entry><literal>PerSessionDSA</literal></entry>
-      <entry>Waiting for parallel query dynamic shared memory allocation.</entry>
-     </row>
-     <row>
-      <entry><literal>PerSessionRecordType</literal></entry>
-      <entry>Waiting to access a parallel query's information about composite
-       types.</entry>
-     </row>
-     <row>
-      <entry><literal>PerSessionRecordTypmod</literal></entry>
-      <entry>Waiting to access a parallel query's information about type
-       modifiers that identify anonymous record types.</entry>
-     </row>
-     <row>
-      <entry><literal>PerXactPredicateList</literal></entry>
-      <entry>Waiting to access the list of predicate locks held by the current
-       serializable transaction during a parallel query.</entry>
-     </row>
-     <row>
-      <entry><literal>PgStatsData</literal></entry>
-      <entry>Waiting for shared memory stats data access</entry>
-     </row>
-     <row>
-      <entry><literal>PgStatsDSA</literal></entry>
-      <entry>Waiting for stats dynamic shared memory allocator access</entry>
-     </row>
-     <row>
-      <entry><literal>PgStatsHash</literal></entry>
-      <entry>Waiting for stats shared memory hash table access</entry>
-     </row>
-     <row>
-      <entry><literal>PredicateLockManager</literal></entry>
-      <entry>Waiting to access predicate lock information used by
-       serializable transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>ProcArray</literal></entry>
-      <entry>Waiting to access the shared per-process data structures
-       (typically, to get a snapshot or report a session's transaction
-       ID).</entry>
-     </row>
-     <row>
-      <entry><literal>RelationMapping</literal></entry>
-      <entry>Waiting to read or update
-       a <filename>pg_filenode.map</filename> file (used to track the
-       filenode assignments of certain system catalogs).</entry>
-     </row>
-     <row>
-      <entry><literal>RelCacheInit</literal></entry>
-      <entry>Waiting to read or update a <filename>pg_internal.init</filename>
-       relation cache initialization file.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationOrigin</literal></entry>
-      <entry>Waiting to create, drop or use a replication origin.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationOriginState</literal></entry>
-      <entry>Waiting to read or update the progress of one replication
-       origin.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotAllocation</literal></entry>
-      <entry>Waiting to allocate or free a replication slot.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotControl</literal></entry>
-      <entry>Waiting to read or update replication slot state.</entry>
-     </row>
-     <row>
-      <entry><literal>ReplicationSlotIO</literal></entry>
-      <entry>Waiting for I/O on a replication slot.</entry>
-     </row>
-     <row>
-      <entry><literal>SerialBuffer</literal></entry>
-      <entry>Waiting for I/O on a serializable transaction conflict SLRU
-       buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>SerializableFinishedList</literal></entry>
-      <entry>Waiting to access the list of finished serializable
-       transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>SerializablePredicateList</literal></entry>
-      <entry>Waiting to access the list of predicate locks held by
-       serializable transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>SerializableXactHash</literal></entry>
-      <entry>Waiting to read or update information about serializable
-       transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>SerialSLRU</literal></entry>
-      <entry>Waiting to access the serializable transaction conflict SLRU
-       cache.</entry>
-     </row>
-     <row>
-      <entry><literal>SharedTidBitmap</literal></entry>
-      <entry>Waiting to access a shared TID bitmap during a parallel bitmap
-       index scan.</entry>
-     </row>
-     <row>
-      <entry><literal>SharedTupleStore</literal></entry>
-      <entry>Waiting to access a shared tuple store during parallel
-       query.</entry>
-     </row>
-     <row>
-      <entry><literal>ShmemIndex</literal></entry>
-      <entry>Waiting to find or allocate space in shared memory.</entry>
-     </row>
-     <row>
-      <entry><literal>SInvalRead</literal></entry>
-      <entry>Waiting to retrieve messages from the shared catalog invalidation
-       queue.</entry>
-     </row>
-     <row>
-      <entry><literal>SInvalWrite</literal></entry>
-      <entry>Waiting to add a message to the shared catalog invalidation
-      queue.</entry>
-     </row>
-     <row>
-      <entry><literal>SubtransBuffer</literal></entry>
-      <entry>Waiting for I/O on a sub-transaction SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>SubtransSLRU</literal></entry>
-      <entry>Waiting to access the sub-transaction SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>SyncRep</literal></entry>
-      <entry>Waiting to read or update information about the state of
-       synchronous replication.</entry>
-     </row>
-     <row>
-      <entry><literal>SyncScan</literal></entry>
-      <entry>Waiting to select the starting location of a synchronized table
-       scan.</entry>
-     </row>
-     <row>
-      <entry><literal>TablespaceCreate</literal></entry>
-      <entry>Waiting to create or drop a tablespace.</entry>
-     </row>
-     <row>
-      <entry><literal>TwoPhaseState</literal></entry>
-      <entry>Waiting to read or update the state of prepared transactions.</entry>
-     </row>
-     <row>
-      <entry><literal>WALBufMapping</literal></entry>
-      <entry>Waiting to replace a page in WAL buffers.</entry>
-     </row>
-     <row>
-      <entry><literal>WALInsert</literal></entry>
-      <entry>Waiting to insert WAL data into a memory buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>WALWrite</literal></entry>
-      <entry>Waiting for WAL buffers to be written to disk.</entry>
-     </row>
-     <row>
-      <entry><literal>WrapLimitsVacuum</literal></entry>
-      <entry>Waiting to update limits on transaction id and multixact
-       consumption.</entry>
-     </row>
-     <row>
-      <entry><literal>XactBuffer</literal></entry>
-      <entry>Waiting for I/O on a transaction status SLRU buffer.</entry>
-     </row>
-     <row>
-      <entry><literal>XactSLRU</literal></entry>
-      <entry>Waiting to access the transaction status SLRU cache.</entry>
-     </row>
-     <row>
-      <entry><literal>XactTruncation</literal></entry>
-      <entry>Waiting to execute <function>pg_xact_status</function> or update
-       the oldest transaction ID available to it.</entry>
-     </row>
-     <row>
-      <entry><literal>XidGen</literal></entry>
-      <entry>Waiting to allocate a new transaction ID.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
-
-   <note>
-    <para>
-     Extensions can add <literal>LWLock</literal> types to the list shown in
-     <xref linkend="wait-event-lwlock-table"/>.  In some cases, the name
-     assigned by an extension will not be available in all server processes;
-     so an <literal>LWLock</literal> wait event might be reported as
-     just <quote><literal>extension</literal></quote> rather than the
-     extension-assigned name.
-    </para>
-   </note>
-
-  <table id="wait-event-timeout-table">
-   <title>Wait Events of Type <literal>Timeout</literal></title>
-   <tgroup cols="2">
-    <thead>
-     <row>
-      <entry><literal>Timeout</literal> Wait Event</entry>
-      <entry>Description</entry>
-     </row>
-    </thead>
-
-    <tbody>
-     <row>
-      <entry><literal>BaseBackupThrottle</literal></entry>
-      <entry>Waiting during base backup when throttling activity.</entry>
-     </row>
-     <row>
-      <entry><literal>CheckpointWriteDelay</literal></entry>
-      <entry>Waiting between writes while performing a checkpoint.</entry>
-     </row>
-     <row>
-      <entry><literal>PgSleep</literal></entry>
-      <entry>Waiting due to a call to <function>pg_sleep</function> or
-       a sibling function.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryApplyDelay</literal></entry>
-      <entry>Waiting to apply WAL during recovery because of a delay
-       setting.</entry>
-     </row>
-     <row>
-      <entry><literal>RecoveryRetrieveRetryInterval</literal></entry>
-      <entry>Waiting during recovery when WAL data is not available from any
-       source (<filename>pg_wal</filename>, archive or stream).</entry>
-     </row>
-     <row>
-      <entry><literal>RegisterSyncRequest</literal></entry>
-      <entry>Waiting while sending synchronization requests to the
-       checkpointer, because the request queue is full.</entry>
-     </row>
-     <row>
-      <entry><literal>SpinDelay</literal></entry>
-      <entry>Waiting while acquiring a contended spinlock.</entry>
-     </row>
-     <row>
-      <entry><literal>VacuumDelay</literal></entry>
-      <entry>Waiting in a cost-based vacuum delay point.</entry>
-     </row>
-     <row>
-      <entry><literal>VacuumTruncate</literal></entry>
-      <entry>Waiting to acquire an exclusive lock to truncate off any
-       empty pages at the end of a table vacuumed.</entry>
-     </row>
-    </tbody>
-   </tgroup>
-  </table>
+  &wait_event_types;
 
    <para>
      Here is an example of how wait events can be viewed:
@@ -2374,6 +1115,16 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
 </programlisting>
    </para>
 
+   <note>
+    <para>
+     Extensions can add <literal>LWLock</literal> types to the list shown in
+     <xref linkend="wait-event-lwlock-table"/>.  In some cases, the name
+     assigned by an extension will not be available in all server processes;
+     so an <literal>LWLock</literal> wait event might be reported as
+     just <quote><literal>extension</literal></quote> rather than the
+     extension-assigned name.
+    </para>
+   </note>
  </sect2>
 
  <sect2 id="monitoring-pg-stat-replication-view">
index 3c420031759d1569084999dea0e51bd813f7d73f..1c929383c44d617c9405c78e97d18cba0840cf58 100644 (file)
@@ -133,6 +133,9 @@ parser/gram.h: parser/gram.y
 storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lwlocknames.txt
        $(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
 
+utils/activity/wait_event_types.h: utils/activity/generate-wait_event_types.pl utils/activity/wait_event_names.txt
+       $(MAKE) -C utils/activity wait_event_types.h pgstat_wait_event.c
+
 # run this unconditionally to avoid needing to know its dependencies here:
 submake-catalog-headers:
        $(MAKE) -C catalog distprep generated-header-symlinks
@@ -160,13 +163,18 @@ submake-utils-headers:
 
 .PHONY: generated-headers
 
-generated-headers: $(top_builddir)/src/include/storage/lwlocknames.h submake-catalog-headers submake-nodes-headers submake-utils-headers
+generated-headers: $(top_builddir)/src/include/storage/lwlocknames.h $(top_builddir)/src/include/utils/wait_event_types.h submake-catalog-headers submake-nodes-headers submake-utils-headers
 
 $(top_builddir)/src/include/storage/lwlocknames.h: storage/lmgr/lwlocknames.h
        prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
          cd '$(dir $@)' && rm -f $(notdir $@) && \
          $(LN_S) "$$prereqdir/$(notdir $<)" .
 
+$(top_builddir)/src/include/utils/wait_event_types.h: utils/activity/wait_event_types.h
+       prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
+         cd '$(dir $@)' && rm -f $(notdir $@) && \
+         $(LN_S) "$$prereqdir/$(notdir $<)" .
+
 utils/probes.o: utils/probes.d $(SUBDIROBJS)
        $(DTRACE) $(DTRACEFLAGS) -C -G -s $(call expand_subsys,$^) -o $@
 
@@ -182,6 +190,7 @@ distprep:
        $(MAKE) -C replication  repl_gram.c repl_gram.h repl_scanner.c syncrep_gram.c syncrep_gram.h syncrep_scanner.c
        $(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
        $(MAKE) -C utils        distprep
+       $(MAKE) -C utils/activity       wait_event_types.h pgstat_wait_event.c
        $(MAKE) -C utils/adt    jsonpath_gram.c jsonpath_gram.h jsonpath_scan.c
        $(MAKE) -C utils/misc   guc-file.c
 
@@ -301,6 +310,8 @@ maintainer-clean: distclean
              replication/syncrep_scanner.c \
              storage/lmgr/lwlocknames.c \
              storage/lmgr/lwlocknames.h \
+             utils/activity/pgstat_wait_event.c \
+             utils/activity/wait_event_types.h \
              utils/adt/jsonpath_gram.c \
              utils/adt/jsonpath_gram.h \
              utils/adt/jsonpath_scan.c \
index 6c7cf6c2956613df1dab332189ed89195afdba21..b34b6afecde9738206b81554052e16a1678c0e78 100644 (file)
@@ -2,8 +2,8 @@
 # these are defined here.  If you add a lock, add it to the end to avoid
 # renumbering the existing locks; if you remove a lock, consider leaving a gap
 # in the numbering sequence for the benefit of DTrace and other external
-# debugging scripts.  Also, do not forget to update the list of wait events
-# in the user documentation.
+# debugging scripts.  Also, do not forget to update the section
+# WaitEventLWLock of src/backend/utils/activity/wait_event_names.txt.
 
 # 0 is available; was formerly BufFreelistLock
 ShmemIndexLock                                         1
diff --git a/src/backend/utils/activity/.gitignore b/src/backend/utils/activity/.gitignore
new file mode 100644 (file)
index 0000000..d770792
--- /dev/null
@@ -0,0 +1,2 @@
+/pgstat_wait_event.c
+/wait_event_types.h
index 7d7482dde02753d36fa7dd6f829ac692cee61a69..f1117745d4b0a3f5f8bf1947d7745767d614d4fd 100644 (file)
@@ -13,6 +13,8 @@ subdir = src/backend/utils/activity
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
+override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
+
 OBJS = \
        backend_progress.o \
        backend_status.o \
@@ -33,3 +35,13 @@ OBJS = \
        wait_event.o
 
 include $(top_srcdir)/src/backend/common.mk
+
+wait_event.o: pgstat_wait_event.c
+pgstat_wait_event.c: wait_event_types.h
+       touch $@
+
+wait_event_types.h: $(top_srcdir)/src/backend/utils/activity/wait_event_names.txt generate-wait_event_types.pl
+       $(PERL) $(srcdir)/generate-wait_event_types.pl --code $<
+
+maintainer-clean: clean
+       rm -f wait_event_types.h pgstat_wait_event.c
diff --git a/src/backend/utils/activity/generate-wait_event_types.pl b/src/backend/utils/activity/generate-wait_event_types.pl
new file mode 100644 (file)
index 0000000..1602a40
--- /dev/null
@@ -0,0 +1,263 @@
+#!/usr/bin/perl
+#----------------------------------------------------------------------
+#
+# Generate wait events support files from wait_event_names.txt:
+# - wait_event_types.h (if --code is passed)
+# - pgstat_wait_event.c (if --code is passed)
+# - wait_event_types.sgml (if --docs is passed)
+#
+# Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+# Portions Copyright (c) 1994, Regents of the University of California
+#
+# src/backend/utils/activity/generate-wait_event_types.pl
+#
+#----------------------------------------------------------------------
+
+use strict;
+use warnings;
+use Getopt::Long;
+
+my $output_path = '.';
+my $gen_docs = 0;
+my $gen_code = 0;
+
+my $continue = "\n";
+my %hashwe;
+
+GetOptions(
+       'outdir:s' => \$output_path,
+       'docs' => \$gen_docs,
+       'code' => \$gen_code) || usage();
+
+die "Needs to specify --docs or --code"
+  if (!$gen_docs && !$gen_code);
+
+die "Not possible to specify --docs and --code simultaneously"
+  if ($gen_docs && $gen_code);
+
+open my $wait_event_names, '<', $ARGV[0] or die;
+
+my @lines;
+my $section_name;
+my $note;
+my $note_name;
+
+# Remove comments and empty lines and add waitclassname based on the section
+while (<$wait_event_names>)
+{
+       chomp;
+
+       # Skip comments
+       next if /^#/;
+
+       # Skip empty lines
+       next if /^\s*$/;
+
+       # Get waitclassname based on the section
+       if (/^Section: ClassName(.*)/)
+       {
+               $section_name = $_;
+               $section_name =~ s/^.*- //;
+               next;
+       }
+
+       push(@lines, $section_name . "\t" . $_);
+}
+
+# Sort the lines based on the third column.
+# uc() is being used to force the comparison to be case-insensitive.
+my @lines_sorted =
+  sort { uc((split(/\t/, $a))[2]) cmp uc((split(/\t/, $b))[2]) } @lines;
+
+# Read the sorted lines and populate the hash table
+foreach my $line (@lines_sorted)
+{
+       die "unable to parse wait_event_names.txt"
+         unless $line =~ /^(\w+)\t+(\w+)\t+("\w+")\t+("\w.*\.")$/;
+
+       (   my $waitclassname,
+               my $waiteventenumname,
+               my $waiteventdescription,
+               my $waitevendocsentence) = split(/\t/, $line);
+
+       my @waiteventlist =
+         [ $waiteventenumname, $waiteventdescription, $waitevendocsentence ];
+       my $trimmedwaiteventname = $waiteventenumname;
+       $trimmedwaiteventname =~ s/^WAIT_EVENT_//;
+
+       # An exception is required for LWLock and Lock as these don't require
+       # any C and header files generated.
+       die "wait event names must start with 'WAIT_EVENT_'"
+         if ( $trimmedwaiteventname eq $waiteventenumname
+               && $waiteventenumname !~ /^LWLock/
+               && $waiteventenumname !~ /^Lock/);
+       $continue = ",\n";
+       push(@{ $hashwe{$waitclassname} }, @waiteventlist);
+}
+
+
+# Generate the .c and .h files.
+if ($gen_code)
+{
+       # Include PID in suffix in case parallel make runs this script
+       # multiple times.
+       my $htmp = "$output_path/wait_event_types.h.tmp$$";
+       my $ctmp = "$output_path/pgstat_wait_event.c.tmp$$";
+       open my $h, '>', $htmp or die "Could not open $htmp: $!";
+       open my $c, '>', $ctmp or die "Could not open $ctmp: $!";
+
+       my $header_comment =
+         '/*-------------------------------------------------------------------------
+ *
+ * %s
+ *    Generated wait events infrastructure code
+ *
+ * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * NOTES
+ *  ******************************
+ *  *** DO NOT EDIT THIS FILE! ***
+ *  ******************************
+ *
+ *  It has been GENERATED by src/backend/utils/activity/generate-wait_event_types.pl
+ *
+ *-------------------------------------------------------------------------
+ */
+
+';
+
+       printf $h $header_comment, 'wait_event_types.h';
+       printf $h "#ifndef WAIT_EVENT_TYPES_H\n";
+       printf $h "#define WAIT_EVENT_TYPES_H\n\n";
+       printf $h "#include \"utils/wait_event.h\"\n\n";
+
+       printf $c $header_comment, 'pgstat_wait_event.c';
+
+       # uc() is being used to force the comparison to be case-insensitive.
+       foreach my $waitclass (sort { uc($a) cmp uc($b) } keys %hashwe)
+       {
+
+               # Don't generate .c and .h files for LWLock and Lock, these are
+               # handled independently.
+               next
+                 if ( $waitclass =~ /^WaitEventLWLock$/
+                       || $waitclass =~ /^WaitEventLock$/);
+
+               my $last = $waitclass;
+               $last =~ s/^WaitEvent//;
+               my $lastuc = uc $last;
+               my $lastlc = lc $last;
+               my $firstpass = 1;
+               my $pg_wait_class;
+
+               printf $c
+                 "static const char *\npgstat_get_wait_$lastlc($waitclass w)\n{\n";
+               printf $c "\tconst char *event_name = \"unknown wait event\";\n\n";
+               printf $c "\tswitch (w)\n\t{\n";
+
+               foreach my $wev (@{ $hashwe{$waitclass} })
+               {
+                       if ($firstpass)
+                       {
+                               printf $h "typedef enum\n{\n";
+                               $pg_wait_class = "PG_WAIT_" . $lastuc;
+                               printf $h "\t%s = %s", $wev->[0], $pg_wait_class;
+                               $continue = ",\n";
+                       }
+                       else
+                       {
+                               printf $h "%s\t%s", $continue, $wev->[0];
+                               $continue = ",\n";
+                       }
+                       $firstpass = 0;
+
+                       printf $c "\t\t case %s:\n", $wev->[0];
+                       printf $c "\t\t\t event_name = %s;\n\t\t\t break;\n", $wev->[1];
+               }
+
+               printf $h "\n} $waitclass;\n\n";
+
+               printf $c
+                 "\t\t\t /* no default case, so that compiler will warn */\n";
+               printf $c "\t}\n\n";
+               printf $c "\treturn event_name;\n";
+               printf $c "}\n\n";
+       }
+
+       printf $h "#endif                          /* WAIT_EVENT_TYPES_H */";
+       close $h;
+       close $c;
+
+       rename($htmp, "$output_path/wait_event_types.h")
+         || die "rename: $htmp to $output_path/wait_event_types.h: $!";
+       rename($ctmp, "$output_path/pgstat_wait_event.c")
+         || die "rename: $ctmp to $output_path/pgstat_wait_event.c: $!";
+}
+# Generate the .sgml file.
+elsif ($gen_docs)
+{
+       # Include PID in suffix in case parallel make runs this multiple times.
+       my $stmp = "$output_path/wait_event_names.s.tmp$$";
+       open my $s, '>', $stmp or die "Could not open $stmp: $!";
+
+       # uc() is being used to force the comparison to be case-insensitive.
+       foreach my $waitclass (sort { uc($a) cmp uc($b) } keys %hashwe)
+       {
+               my $last = $waitclass;
+               $last =~ s/^WaitEvent//;
+               my $lastlc = lc $last;
+
+               printf $s "  <table id=\"wait-event-%s-table\">\n", $lastlc;
+               printf $s
+                 "   <title>Wait Events of Type <literal>%s</literal></title>\n",
+                 ucfirst($lastlc);
+               printf $s "   <tgroup cols=\"2\">\n";
+               printf $s "    <thead>\n";
+               printf $s "     <row>\n";
+               printf $s
+                 "      <entry><literal>$last</literal> Wait Event</entry>\n";
+               printf $s "      <entry>Description</entry>\n";
+               printf $s "     </row>\n";
+               printf $s "    </thead>\n\n";
+               printf $s "    <tbody>\n";
+
+               foreach my $wev (@{ $hashwe{$waitclass} })
+               {
+                       printf $s "     <row>\n";
+                       printf $s "      <entry><literal>%s</literal></entry>\n",
+                         substr $wev->[1], 1, -1;
+                       printf $s "      <entry>%s</entry>\n", substr $wev->[2], 1, -1;
+                       printf $s "     </row>\n";
+               }
+
+               printf $s "    </tbody>\n";
+               printf $s "   </tgroup>\n";
+               printf $s "  </table>\n\n";
+       }
+
+       close $s;
+
+       rename($stmp, "$output_path/wait_event_types.sgml")
+         || die "rename: $stmp to $output_path/wait_event_types.sgml: $!";
+}
+
+close $wait_event_names;
+
+sub usage
+{
+       die <<EOM;
+Usage: perl  [--output <path>] [--code ] [ --sgml ] input_file
+
+Options:
+    --outdir         Output directory (default '.')
+    --code           Generate wait_event_types.h and pgstat_wait_event.c.
+    --sgml           Generate wait_event_types.sgml.
+
+generate-wait_event_types.pl generates the SGML documentation and code
+related to wait events.  This should use wait_event_names.txt in input, or
+an input file with a compatible format.
+
+Report bugs to <pgsql-bugs\@lists.postgresql.org>.
+EOM
+}
index 518ee3f798e2b638a126afafa9abf4a71582e41f..9633f3623c4ecd5c561ce3e8431603c36418bf21 100644 (file)
@@ -17,5 +17,19 @@ backend_sources += files(
   'pgstat_subscription.c',
   'pgstat_wal.c',
   'pgstat_xact.c',
+)
+
+# this includes a .c file with contents generated in ../../../include/activity,
+# seems nicer to not add that as an include path for the whole backend.
+waitevent_sources = files(
   'wait_event.c',
 )
+
+wait_event = static_library('wait_event_names',
+  waitevent_sources,
+  dependencies: [backend_code],
+  include_directories: include_directories('../../../include/utils'),
+  kwargs: internal_lib_args,
+)
+
+backend_link_with += wait_event
index 8572cf169ea0bf56d6619df323ac5291ebb310f0..4aad11c111301de9b7e7a9c49c6a36914d07659c 100644 (file)
@@ -206,613 +206,4 @@ pgstat_get_wait_event(uint32 wait_event_info)
        return event_name;
 }
 
-/* ----------
- * pgstat_get_wait_activity() -
- *
- * Convert WaitEventActivity to string.
- * ----------
- */
-static const char *
-pgstat_get_wait_activity(WaitEventActivity w)
-{
-       const char *event_name = "unknown wait event";
-
-       switch (w)
-       {
-               case WAIT_EVENT_ARCHIVER_MAIN:
-                       event_name = "ArchiverMain";
-                       break;
-               case WAIT_EVENT_AUTOVACUUM_MAIN:
-