On Wed, Sep 28, 2016 at 9:45 PM, Robert Haas <[email protected]> wrote:
> On Wed, Sep 28, 2016 at 8:38 AM, Michael Paquier
> <[email protected]> wrote:
>> So should I change back the patch to have only one argument for the
>> eventId, and guess classId from it?
>
> Why would you need to guess?
Incorrect wording from me perhaps? i just meant that processing needs
to know what is the classId coming for a specific eventId.
> But, yes, I think one argument is much preferable.
OK. Here is the wanted patch. I have reduced the routines of WaitLatch
& friends to use only one argument, and added what is the classId
associated with a given eventId in an array of multiple fields, giving
something like that:
+ const struct wait_event_entry WaitEventEntries[] = {
+ /* Activity */
+ {WAIT_ACTIVITY, "ArchiverMain"},
[...]
I have cleaned up as well the inclusions of pgstat.h that I added
previously. Patch is attached.
--
Michael
diff --git a/contrib/postgres_fdw/connection.c b/contrib/postgres_fdw/connection.c
index 8ca1c1c..9265e00 100644
--- a/contrib/postgres_fdw/connection.c
+++ b/contrib/postgres_fdw/connection.c
@@ -496,7 +496,8 @@ pgfdw_get_result(PGconn *conn, const char *query)
wc = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_SOCKET_READABLE,
PQsocket(conn),
- -1L);
+ -1L,
+ WE_EXTENSION);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index f400785..bb975c1 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -679,6 +679,42 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
buffer in question.
</para>
</listitem>
+ <listitem>
+ <para>
+ <literal>Activity</>: The server process is idle. This is used by
+ system processes waiting for activity in their main processing loop.
+ <literal>wait_event</> will identify the specific wait point.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Extension</>: The server process is waiting for activity
+ in an extension module. This category is useful for modules to
+ track custom waiting points.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Client</>: The server process is waiting for some activity
+ on a socket from user applications, and that the server expects
+ something to happen that is independent from its internal processes.
+ <literal>wait_event</> will identify the specific wait point.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>IPC</>: The server process is waiting for some activity
+ from another process in the server. <literal>wait_event</> will
+ identify the specific wait point.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <literal>Timeout</>: The server process is waiting for a timeout
+ to expire. <literal>wait_event</> will identify the specific wait
+ point.
+ </para>
+ </listitem>
</itemizedlist>
</entry>
</row>
@@ -1085,6 +1121,143 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
<entry><literal>BufferPin</></entry>
<entry>Waiting to acquire a pin on a buffer.</entry>
</row>
+ <row>
+ <entry morerows="11"><literal>Activity</></entry>
+ <entry><literal>ArchiverMain</></entry>
+ <entry>Waiting in main loop of the archiver process.</entry>
+ </row>
+ <row>
+ <entry><literal>AutoVacuumMain</></entry>
+ <entry>Waiting in main loop of autovacuum launcher process.</entry>
+ </row>
+ <row>
+ <entry><literal>BgWriterHibernate</></entry>
+ <entry>Waiting in background writer process, hibernating.</entry>
+ </row>
+ <row>
+ <entry><literal>BgWriterMain</></entry>
+ <entry>Waiting in main loop of background writer process background worker.</entry>
+ </row>
+ <row>
+ <entry><literal>CheckpointerMain</></entry>
+ <entry>Waiting in main loop of checkpointer process.</entry>
+ </row>
+ <row>
+ <entry><literal>PgStatMain</></entry>
+ <entry>Waiting in main loop of the statistics collector process.</entry>
+ </row>
+ <row>
+ <entry><literal>RecoveryWalAll</></entry>
+ <entry>Waiting for WAL from any kind of source (local, archive or stream) at recovery.</entry>
+ </row>
+ <row>
+ <entry><literal>RecoveryWalStream</></entry>
+ <entry>Waiting for WAL from a stream at recovery.</entry>
+ </row>
+ <row>
+ <entry><literal>SysLoggerMain</></entry>
+ <entry>Waiting in main loop of syslogger process.</entry>
+ </row>
+ <row>
+ <entry><literal>WalReceiverMain</></entry>
+ <entry>Waiting in main loop of WAL receiver process.</entry>
+ </row>
+ <row>
+ <entry><literal>WalSenderMain</></entry>
+ <entry>Waiting in main loop of WAL sender process.</entry>
+ </row>
+ <row>
+ <entry><literal>WalWriterMain</></entry>
+ <entry>Waiting in main loop of WAL writer process.</entry>
+ </row>
+ <row>
+ <entry morerows="5"><literal>Client</></entry>
+ <entry><literal>SecureRead</></entry>
+ <entry>Waiting to read data from a secure connection.</entry>
+ </row>
+ <row>
+ <entry><literal>SecureWrite</></entry>
+ <entry>Waiting to write data to a secure connection.</entry>
+ </row>
+ <row>
+ <entry><literal>SSLOpenServer</></entry>
+ <entry>Waiting for SSL while attempting connection.</entry>
+ </row>
+ <row>
+ <entry><literal>WalReceiverWaitStart</></entry>
+ <entry>Waiting for startup process to send initial data for streaming replication.</entry>
+ </row>
+ <row>
+ <entry><literal>WalSenderWaitForWAL</></entry>
+ <entry>Waiting for WAL to be flushed in WAL sender process.</entry>
+ </row>
+ <row>
+ <entry><literal>WalSenderWriteData</></entry>
+ <entry>Waiting for any activity when processing replies from WAL receiver in WAL sender process.</entry>
+ </row>
+ <row>
+ <entry><literal>Extension</></entry>
+ <entry><literal>Extension</></entry>
+ <entry>Waiting in the code path of an extension, should be used by custom plugins and modules</entry>
+ </row>
+ <row>
+ <entry morerows="10"><literal>IPC</></entry>
+ <entry><literal>BgWorkerShutdown</></entry>
+ <entry>Waiting for background worker to shut down.</entry>
+ </row>
+ <row>
+ <entry><literal>BgWorkerStartup</></entry>
+ <entry>Waiting for background worker to start up.</entry>
+ </row>
+ <row>
+ <entry><literal>ExecuteGather</></entry>
+ <entry>Waiting for activity from child process when executing <literal>Gather</> node.</entry>
+ </row>
+ <row>
+ <entry><literal>MessageQueueInternal</></entry>
+ <entry>Waiting for other process to be attached in shared message queue.</entry>
+ </row>
+ <row>
+ <entry><literal>MessageQueuePutMessage</></entry>
+ <entry>Waiting to put new message in shared message queue.</entry>
+ </row>
+ <row>
+ <entry><literal>MessageQueueReceive</></entry>
+ <entry>Waiting to receive bytes in shared message queue.</entry>
+ </row>
+ <row>
+ <entry><literal>MessageQueueSend</></entry>
+ <entry>Waiting to send bytes in shared message queue.</entry>
+ </row>
+ <row>
+ <entry><literal>ParallelFinish</></entry>
+ <entry>Waiting for parallel workers to finish computing.</entry>
+ </row>
+ <row>
+ <entry><literal>ProcSignal</></entry>
+ <entry>Waiting for signal from another backend.</entry>
+ </row>
+ <row>
+ <entry><literal>ProcSleep</></entry>
+ <entry>Waiting for a specific lock.</entry>
+ </row>
+ <row>
+ <entry><literal>SyncRep</></entry>
+ <entry>Waiting for WAL commit during synchronous replication.</entry>
+ </row>
+ <row>
+ <entry morerows="2"><literal>Timeout</></entry>
+ <entry><literal>BaseBackupThrottle</></entry>
+ <entry>Waiting during base backup when throttling activity.</entry>
+ </row>
+ <row>
+ <entry><literal>PgSleep</></entry>
+ <entry>Waiting in process that called <function>pg_sleep</>.</entry>
+ </row>
+ <row>
+ <entry><literal>RecoveryApplyDelay</></entry>
+ <entry>Waiting to apply WAL at recovery because it is delayed.</entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index cde0ed3..60d5c9c 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -540,7 +540,8 @@ WaitForParallelWorkersToFinish(ParallelContext *pcxt)
if (!anyone_alive)
break;
- WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1);
+ WaitLatch(&MyProc->procLatch, WL_LATCH_SET, -1,
+ WE_PARALLEL_FINISH);
ResetLatch(&MyProc->procLatch);
}
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index c1b9a97..65fe014 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -5827,7 +5827,8 @@ recoveryApplyDelay(XLogReaderState *record)
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- secs * 1000L + microsecs / 1000);
+ secs * 1000L + microsecs / 1000,
+ WE_RECOVERY_APPLY_DELAY);
}
return true;
}
@@ -11387,7 +11388,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- wait_time);
+ wait_time, WE_RECOVERY_WAL_STREAM);
ResetLatch(&XLogCtl->recoveryWakeupLatch);
now = GetCurrentTimestamp();
}
@@ -11550,7 +11551,7 @@ WaitForWALToBecomeAvailable(XLogRecPtr RecPtr, bool randAccess,
*/
WaitLatch(&XLogCtl->recoveryWakeupLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- 5000L);
+ 5000L, WE_RECOVERY_WAL_ALL);
ResetLatch(&XLogCtl->recoveryWakeupLatch);
break;
}
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index 438d1b2..b832d91 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -387,7 +387,7 @@ gather_readnext(GatherState *gatherstate)
return NULL;
/* Nothing to do except wait for developments. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WE_EXECUTE_GATHER);
ResetLatch(MyLatch);
nvisited = 0;
}
diff --git a/src/backend/libpq/be-secure-openssl.c b/src/backend/libpq/be-secure-openssl.c
index fedb02c..571d4d6 100644
--- a/src/backend/libpq/be-secure-openssl.c
+++ b/src/backend/libpq/be-secure-openssl.c
@@ -419,7 +419,8 @@ aloop:
else
waitfor = WL_SOCKET_WRITEABLE;
- WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0);
+ WaitLatchOrSocket(MyLatch, waitfor, port->sock, 0,
+ WE_SSL_OPEN_SERVER);
goto aloop;
case SSL_ERROR_SYSCALL:
if (r < 0)
diff --git a/src/backend/libpq/be-secure.c b/src/backend/libpq/be-secure.c
index cdd07d5..4e16073 100644
--- a/src/backend/libpq/be-secure.c
+++ b/src/backend/libpq/be-secure.c
@@ -146,7 +146,8 @@ retry:
ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
- WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1);
+ WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
+ WE_SECURE_READ);
/*
* If the postmaster has died, it's not safe to continue running,
@@ -247,7 +248,8 @@ retry:
ModifyWaitEvent(FeBeWaitSet, 0, waitfor, NULL);
- WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1);
+ WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
+ WE_SECURE_WRITE);
/* See comments in secure_read. */
if (event.events & WL_POSTMASTER_DEATH)
diff --git a/src/backend/libpq/pqmq.c b/src/backend/libpq/pqmq.c
index bfe66c6..280ea80 100644
--- a/src/backend/libpq/pqmq.c
+++ b/src/backend/libpq/pqmq.c
@@ -171,7 +171,8 @@ mq_putmessage(char msgtype, const char *s, size_t len)
if (result != SHM_MQ_WOULD_BLOCK)
break;
- WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0);
+ WaitLatch(&MyProc->procLatch, WL_LATCH_SET, 0,
+ WE_MQ_PUT_MESSAGE);
ResetLatch(&MyProc->procLatch);
CHECK_FOR_INTERRUPTS();
}
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1a92ca1..019075e 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -598,7 +598,8 @@ AutoVacLauncherMain(int argc, char *argv[])
*/
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L));
+ (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L),
+ WE_AUTOVACUUM_MAIN);
ResetLatch(MyLatch);
diff --git a/src/backend/postmaster/bgworker.c b/src/backend/postmaster/bgworker.c
index 699c934..7da01df 100644
--- a/src/backend/postmaster/bgworker.c
+++ b/src/backend/postmaster/bgworker.c
@@ -969,7 +969,8 @@ WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
break;
rc = WaitLatch(MyLatch,
- WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ WE_BGWORKER_STARTUP);
if (rc & WL_POSTMASTER_DEATH)
{
@@ -1008,7 +1009,8 @@ WaitForBackgroundWorkerShutdown(BackgroundWorkerHandle *handle)
break;
rc = WaitLatch(&MyProc->procLatch,
- WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ WE_BGWORKER_SHUTDOWN);
if (rc & WL_POSTMASTER_DEATH)
{
diff --git a/src/backend/postmaster/bgwriter.c b/src/backend/postmaster/bgwriter.c
index 1002034..a89d39d 100644
--- a/src/backend/postmaster/bgwriter.c
+++ b/src/backend/postmaster/bgwriter.c
@@ -345,7 +345,8 @@ BackgroundWriterMain(void)
*/
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- BgWriterDelay /* ms */ );
+ BgWriterDelay /* ms */,
+ WE_BGWRITER_MAIN);
/*
* If no latch event and BgBufferSync says nothing's happening, extend
@@ -372,7 +373,8 @@ BackgroundWriterMain(void)
/* Sleep ... */
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- BgWriterDelay * HIBERNATE_FACTOR);
+ BgWriterDelay * HIBERNATE_FACTOR,
+ WE_BGWRITER_HIBERNATE);
/* Reset the notification request in case we timed out */
StrategyNotifyBgWriter(-1);
}
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index d702a48..e18ef9f 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -556,7 +556,8 @@ CheckpointerMain(void)
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- cur_timeout * 1000L /* convert to ms */ );
+ cur_timeout * 1000L /* convert to ms */,
+ WE_CHECKPOINTER_MAIN);
/*
* Emergency bailout if postmaster has died. This is to avoid the
diff --git a/src/backend/postmaster/pgarch.c b/src/backend/postmaster/pgarch.c
index 1aa6466..018878c 100644
--- a/src/backend/postmaster/pgarch.c
+++ b/src/backend/postmaster/pgarch.c
@@ -390,7 +390,7 @@ pgarch_MainLoop(void)
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- timeout * 1000L);
+ timeout * 1000L, WE_ARCHIVER_MAIN);
if (rc & WL_TIMEOUT)
wakened = true;
}
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 96578dc..9679b91 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -3155,6 +3155,18 @@ pgstat_get_wait_event_type(uint32 wait_event_info)
case WAIT_BUFFER_PIN:
event_type = "BufferPin";
break;
+ case WAIT_ACTIVITY:
+ event_type = "Activity";
+ break;
+ case WAIT_CLIENT:
+ event_type = "Client";
+ break;
+ case WAIT_IPC:
+ event_type = "IPC";
+ break;
+ case WAIT_TIMEOUT:
+ event_type = "Timeout";
+ break;
default:
event_type = "???";
break;
@@ -3196,6 +3208,13 @@ pgstat_get_wait_event(uint32 wait_event_info)
case WAIT_BUFFER_PIN:
event_name = "BufferPin";
break;
+ case WAIT_ACTIVITY:
+ case WAIT_CLIENT:
+ case WAIT_EXTENSION:
+ case WAIT_IPC:
+ case WAIT_TIMEOUT:
+ event_name = GetWaitEventIdentifier(eventId);
+ break;
default:
event_name = "unknown wait event";
break;
@@ -3684,8 +3703,7 @@ PgstatCollectorMain(int argc, char *argv[])
#ifndef WIN32
wr = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE,
- pgStatSock,
- -1L);
+ pgStatSock, -1L, WE_PGSTAT_MAIN);
#else
/*
@@ -3701,7 +3719,8 @@ PgstatCollectorMain(int argc, char *argv[])
wr = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_POSTMASTER_DEATH | WL_SOCKET_READABLE | WL_TIMEOUT,
pgStatSock,
- 2 * 1000L /* msec */ );
+ 2 * 1000L /* msec */,
+ WE_PGSTAT_MAIN);
#endif
/*
diff --git a/src/backend/postmaster/syslogger.c b/src/backend/postmaster/syslogger.c
index e7e488a..c081224 100644
--- a/src/backend/postmaster/syslogger.c
+++ b/src/backend/postmaster/syslogger.c
@@ -424,7 +424,8 @@ SysLoggerMain(int argc, char *argv[])
rc = WaitLatchOrSocket(MyLatch,
WL_LATCH_SET | WL_SOCKET_READABLE | cur_flags,
syslogPipe[0],
- cur_timeout);
+ cur_timeout,
+ WE_SYSLOGGER_MAIN);
if (rc & WL_SOCKET_READABLE)
{
@@ -475,7 +476,8 @@ SysLoggerMain(int argc, char *argv[])
(void) WaitLatch(MyLatch,
WL_LATCH_SET | cur_flags,
- cur_timeout);
+ cur_timeout,
+ WE_SYSLOGGER_MAIN);
EnterCriticalSection(&sysloggerSection);
#endif /* WIN32 */
diff --git a/src/backend/postmaster/walwriter.c b/src/backend/postmaster/walwriter.c
index 11ec56a..5b6fa15 100644
--- a/src/backend/postmaster/walwriter.c
+++ b/src/backend/postmaster/walwriter.c
@@ -290,7 +290,8 @@ WalWriterMain(void)
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- cur_timeout);
+ cur_timeout,
+ WE_WAL_WRITER_MAIN);
/*
* Emergency bailout if postmaster has died. This is to avoid the
diff --git a/src/backend/replication/basebackup.c b/src/backend/replication/basebackup.c
index da9b7a6..82e8d03 100644
--- a/src/backend/replication/basebackup.c
+++ b/src/backend/replication/basebackup.c
@@ -1286,7 +1286,8 @@ throttle(size_t increment)
*/
wait_result = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- (long) (sleep / 1000));
+ (long) (sleep / 1000),
+ WE_BASE_BACKUP_THROTTLE);
if (wait_result & WL_LATCH_SET)
CHECK_FOR_INTERRUPTS();
diff --git a/src/backend/replication/syncrep.c b/src/backend/replication/syncrep.c
index b442d06..f1acb4a 100644
--- a/src/backend/replication/syncrep.c
+++ b/src/backend/replication/syncrep.c
@@ -258,7 +258,8 @@ SyncRepWaitForLSN(XLogRecPtr lsn, bool commit)
* Wait on latch. Any condition that should wake us up will set the
* latch, so no need for timeout.
*/
- WaitLatch(MyLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1);
+ WaitLatch(MyLatch, WL_LATCH_SET | WL_POSTMASTER_DEATH, -1,
+ WE_SYNC_REP);
}
/*
diff --git a/src/backend/replication/walreceiver.c b/src/backend/replication/walreceiver.c
index 413ee3a..046a760 100644
--- a/src/backend/replication/walreceiver.c
+++ b/src/backend/replication/walreceiver.c
@@ -486,7 +486,8 @@ WalReceiverMain(void)
WL_POSTMASTER_DEATH | WL_SOCKET_READABLE |
WL_TIMEOUT | WL_LATCH_SET,
wait_fd,
- NAPTIME_PER_CYCLE);
+ NAPTIME_PER_CYCLE,
+ WE_WAL_RECEIVER_MAIN);
if (rc & WL_LATCH_SET)
{
ResetLatch(&walrcv->latch);
@@ -685,7 +686,8 @@ WalRcvWaitForStartPosition(XLogRecPtr *startpoint, TimeLineID *startpointTLI)
}
SpinLockRelease(&walrcv->mutex);
- WaitLatch(&walrcv->latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
+ WaitLatch(&walrcv->latch, WL_LATCH_SET | WL_POSTMASTER_DEATH, 0,
+ WE_WAL_RECEIVER_WAIT_START);
}
if (update_process_title)
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index c7743da..3cac83b 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -1146,7 +1146,8 @@ WalSndWriteData(LogicalDecodingContext *ctx, XLogRecPtr lsn, TransactionId xid,
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ WE_WAL_SENDER_WRITE_DATA);
}
/* reactivate latch so WalSndLoop knows to continue */
@@ -1272,7 +1273,8 @@ WalSndWaitForWal(XLogRecPtr loc)
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ WE_WAL_SENDER_WAIT_WAL);
}
/* reactivate latch so WalSndLoop knows to continue */
@@ -1924,7 +1926,8 @@ WalSndLoop(WalSndSendDataCallback send_data)
/* Sleep until something happens or we time out */
WaitLatchOrSocket(MyLatch, wakeEvents,
- MyProcPort->sock, sleeptime);
+ MyProcPort->sock, sleeptime,
+ WE_WAL_SENDER_MAIN);
}
}
return;
diff --git a/src/backend/storage/ipc/latch.c b/src/backend/storage/ipc/latch.c
index 9def8a1..a0be2a7 100644
--- a/src/backend/storage/ipc/latch.c
+++ b/src/backend/storage/ipc/latch.c
@@ -55,6 +55,7 @@
#endif
#include "miscadmin.h"
+#include "pgstat.h"
#include "portability/instr_time.h"
#include "postmaster/postmaster.h"
#include "storage/barrier.h"
@@ -122,6 +123,50 @@ struct WaitEventSet
#endif
};
+/*
+ * This must match enum WaitEventIdentifier!
+ */
+const struct wait_event_entry WaitEventEntries[] = {
+ /* Activity */
+ {WAIT_ACTIVITY, "ArchiverMain"},
+ {WAIT_ACTIVITY, "AutoVacuumMain"},
+ {WAIT_ACTIVITY, "BgWriterHibernate"},
+ {WAIT_ACTIVITY, "BgWriterMain"},
+ {WAIT_ACTIVITY, "CheckpointerMain"},
+ {WAIT_ACTIVITY, "PgStatMain"},
+ {WAIT_ACTIVITY, "RecoveryWalAll"},
+ {WAIT_ACTIVITY, "RecoveryWalStream"},
+ {WAIT_ACTIVITY, "SysLoggerMain"},
+ {WAIT_ACTIVITY, "WalReceiverMain"},
+ {WAIT_ACTIVITY, "WalSenderMain"},
+ {WAIT_ACTIVITY, "WalWriterMain"},
+ /* Client */
+ {WAIT_CLIENT, "SecureRead"},
+ {WAIT_CLIENT, "SecureWrite"},
+ {WAIT_CLIENT, "SSLOpenServer"},
+ {WAIT_CLIENT, "WalReceiverWaitStart"},
+ {WAIT_CLIENT, "WalSenderWaitForWAL"},
+ {WAIT_CLIENT, "WalSenderWriteData"},
+ /* Extension */
+ {WAIT_EXTENSION, "Extension"},
+ /* IPC */
+ {WAIT_IPC, "BgWorkerShutdown"},
+ {WAIT_IPC, "BgWorkerStartup"},
+ {WAIT_IPC, "ExecuteGather"},
+ {WAIT_IPC, "MessageQueueInternal"},
+ {WAIT_IPC, "MessageQueuePutMessage"},
+ {WAIT_IPC, "MessageQueueReceive"},
+ {WAIT_IPC, "MessageQueueSend"},
+ {WAIT_IPC, "ParallelFinish"},
+ {WAIT_IPC, "ProcSignal"},
+ {WAIT_IPC, "ProcSleep"},
+ {WAIT_IPC, "SyncRep"},
+ /* Timeout */
+ {WAIT_TIMEOUT, "BaseBackupThrottle"},
+ {WAIT_TIMEOUT, "PgSleep"},
+ {WAIT_TIMEOUT, "RecoveryApplyDelay"},
+};
+
#ifndef WIN32
/* Are we currently in WaitLatch? The signal handler would like to know. */
static volatile sig_atomic_t waiting = false;
@@ -297,9 +342,11 @@ DisownLatch(volatile Latch *latch)
* we return all of them in one call, but we will return at least one.
*/
int
-WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
+WaitLatch(volatile Latch *latch, int wakeEvents, long timeout,
+ uint16 eventId)
{
- return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout);
+ return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout,
+ eventId);
}
/*
@@ -316,7 +363,7 @@ WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
*/
int
WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
- long timeout)
+ long timeout, uint16 eventId)
{
int ret = 0;
int rc;
@@ -344,7 +391,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
AddWaitEventToSet(set, ev, sock, NULL, NULL);
}
- rc = WaitEventSetWait(set, timeout, &event, 1);
+ rc = WaitEventSetWait(set, timeout, &event, 1, eventId);
if (rc == 0)
ret |= WL_TIMEOUT;
@@ -863,7 +910,8 @@ WaitEventAdjustWin32(WaitEventSet *set, WaitEvent *event)
*/
int
WaitEventSetWait(WaitEventSet *set, long timeout,
- WaitEvent *occurred_events, int nevents)
+ WaitEvent *occurred_events, int nevents,
+ uint16 eventId)
{
int returned_events = 0;
instr_time start_time;
@@ -872,6 +920,8 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
Assert(nevents > 0);
+ pgstat_report_wait_start(GetWaitEventClass(eventId), eventId);
+
/*
* Initialize timeout if requested. We must record the current time so
* that we can determine the remaining timeout if interrupted.
@@ -960,6 +1010,8 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
waiting = false;
#endif
+ pgstat_report_wait_end();
+
return returned_events;
}
@@ -1491,6 +1543,37 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
}
#endif
+
+/*
+ * Return an event name for a WaitEventSet event depending on the ID
+ * provided by caller, ID used for the statistics collector.
+ */
+const char *
+GetWaitEventIdentifier(uint16 eventId)
+{
+ StaticAssertStmt(lengthof(WaitEventEntries) == WE_LAST_TYPE + 1,
+ "WaitEventEntries must match WaitEventIdentifiers");
+ if (eventId > WE_LAST_TYPE)
+ return "???";
+ return WaitEventEntries[eventId].name;
+}
+
+
+/*
+ * Determine the class ID of a WaitEventSet event depending on the ID
+ * provided by caller, ID used for the statistics collector.
+ */
+uint8
+GetWaitEventClass(uint16 eventId)
+{
+ StaticAssertStmt(lengthof(WaitEventEntries) == WE_LAST_TYPE + 1,
+ "WaitEventEntries must match WaitEventIdentifiers");
+ if (eventId > WE_LAST_TYPE)
+ return WAIT_UNDEFINED;
+ return WaitEventEntries[eventId].classId;
+}
+
+
/*
* SetLatch uses SIGUSR1 to wake up the process waiting on the latch.
*
diff --git a/src/backend/storage/ipc/shm_mq.c b/src/backend/storage/ipc/shm_mq.c
index 5b32782..c47cf2b 100644
--- a/src/backend/storage/ipc/shm_mq.c
+++ b/src/backend/storage/ipc/shm_mq.c
@@ -894,7 +894,7 @@ shm_mq_send_bytes(shm_mq_handle *mqh, Size nbytes, const void *data,
* at top of loop, because setting an already-set latch is much
* cheaper than setting one that has been reset.
*/
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WE_MQ_SEND);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
@@ -991,7 +991,7 @@ shm_mq_receive_bytes(shm_mq *mq, Size bytes_needed, bool nowait,
* loop, because setting an already-set latch is much cheaper than
* setting one that has been reset.
*/
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WE_MQ_RECEIVE);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
@@ -1090,7 +1090,7 @@ shm_mq_wait_internal(volatile shm_mq *mq, PGPROC *volatile * ptr,
}
/* Wait to be signalled. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WE_MQ_INTERNAL);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 33e7023..23deeb6 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1212,7 +1212,7 @@ ProcSleep(LOCALLOCK *locallock, LockMethod lockMethodTable)
}
else
{
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WE_PROC_SLEEP);
ResetLatch(MyLatch);
/* check for deadlocks first, as that's probably log-worthy */
if (got_deadlock_timeout)
@@ -1724,7 +1724,7 @@ CheckDeadLockAlert(void)
void
ProcWaitForSignal(void)
{
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WE_PROC_SIGNAL);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
}
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 5e705e9..642f619 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -560,7 +560,8 @@ pg_sleep(PG_FUNCTION_ARGS)
(void) WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT,
- delay_ms);
+ delay_ms,
+ WE_PG_SLEEP);
ResetLatch(MyLatch);
}
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 0c98c59..b3f707e 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -721,8 +721,13 @@ typedef enum WaitClass
WAIT_LWLOCK_NAMED,
WAIT_LWLOCK_TRANCHE,
WAIT_LOCK,
- WAIT_BUFFER_PIN
-} WaitClass;
+ WAIT_BUFFER_PIN,
+ WAIT_ACTIVITY,
+ WAIT_CLIENT,
+ WAIT_EXTENSION,
+ WAIT_IPC,
+ WAIT_TIMEOUT
+} WaitClass;
/* ----------
diff --git a/src/include/storage/latch.h b/src/include/storage/latch.h
index 5179ecc..c4ad1cb 100644
--- a/src/include/storage/latch.h
+++ b/src/include/storage/latch.h
@@ -135,6 +135,75 @@ typedef struct WaitEvent
void *user_data; /* pointer provided in AddWaitEventToSet */
} WaitEvent;
+/*
+ * List of WaitEventSet identifiers used when reporting activity to
+ * statistics collector. Up to 256 different WaitEventIdentifier can be
+ * handled. Those are classified by category first, and then by
+ * alphabetical order. Events are classified into sub-categories following
+ * some basic hierarchy rules:
+ * - "Activity" for main loops of processes waiting for an event.
+ * - "Client" for a socket awaited when a user is connected.
+ * - "IPC", similarly to "Client", for a socket awaited from another
+ * server process.
+ * - "Timeout", for a timeout waiting to expire.
+ * - "Extension", to let extension modules a way to define a custom wait
+ * point.
+ */
+typedef enum WaitEventIdentifier
+{
+ /* Activity */
+ WE_ARCHIVER_MAIN,
+ WE_AUTOVACUUM_MAIN,
+ WE_BGWRITER_HIBERNATE,
+ WE_BGWRITER_MAIN,
+ WE_CHECKPOINTER_MAIN,
+ WE_PGSTAT_MAIN,
+ WE_RECOVERY_WAL_ALL,
+ WE_RECOVERY_WAL_STREAM,
+ WE_SYSLOGGER_MAIN,
+ WE_WAL_RECEIVER_MAIN,
+ WE_WAL_SENDER_MAIN,
+ WE_WAL_WRITER_MAIN,
+ /* Client */
+ WE_SECURE_READ,
+ WE_SECURE_WRITE,
+ WE_SSL_OPEN_SERVER,
+ WE_WAL_RECEIVER_WAIT_START,
+ WE_WAL_SENDER_WAIT_WAL,
+ WE_WAL_SENDER_WRITE_DATA,
+ /* Extension */
+ WE_EXTENSION,
+ /* IPC */
+ WE_BGWORKER_SHUTDOWN,
+ WE_BGWORKER_STARTUP,
+ WE_EXECUTE_GATHER,
+ WE_MQ_INTERNAL,
+ WE_MQ_PUT_MESSAGE,
+ WE_MQ_RECEIVE,
+ WE_MQ_SEND,
+ WE_PARALLEL_FINISH,
+ WE_PROC_SIGNAL,
+ WE_PROC_SLEEP,
+ WE_SYNC_REP,
+ /* Timeout */
+ WE_BASE_BACKUP_THROTTLE,
+ WE_PG_SLEEP,
+ WE_RECOVERY_APPLY_DELAY
+} WaitEventIdentifier;
+
+#define WE_LAST_TYPE WE_RECOVERY_APPLY_DELAY
+
+/*
+ * The information details about each WaitEventIdentifier listed above
+ * are specified by an array of name-pair values.
+ */
+struct wait_event_entry
+{
+ uint8 classId;
+ const char *name;
+};
+extern const struct wait_event_entry WaitEventEntries[];
+
/* forward declaration to avoid exposing latch.c implementation details */
typedef struct WaitEventSet WaitEventSet;
@@ -155,10 +224,15 @@ extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd,
Latch *latch, void *user_data);
extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch);
-extern int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents);
-extern int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout);
+extern int WaitEventSetWait(WaitEventSet *set, long timeout,
+ WaitEvent *occurred_events, int nevents,
+ uint16 eventId);
+extern int WaitLatch(volatile Latch *latch, int wakeEvents, long timeout,
+ uint16 eventId);
extern int WaitLatchOrSocket(volatile Latch *latch, int wakeEvents,
- pgsocket sock, long timeout);
+ pgsocket sock, long timeout, uint16 eventId);
+extern uint8 GetWaitEventClass(uint16 eventId);
+extern const char *GetWaitEventIdentifier(uint16 eventId);
/*
* Unix implementation uses SIGUSR1 for inter-process signaling.
diff --git a/src/test/modules/test_shm_mq/setup.c b/src/test/modules/test_shm_mq/setup.c
index 143df4e..adebfc8 100644
--- a/src/test/modules/test_shm_mq/setup.c
+++ b/src/test/modules/test_shm_mq/setup.c
@@ -279,7 +279,7 @@ wait_for_workers_to_become_ready(worker_state *wstate,
}
/* Wait to be signalled. */
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WE_EXTENSION);
/* Reset the latch so we don't spin. */
ResetLatch(MyLatch);
diff --git a/src/test/modules/test_shm_mq/test.c b/src/test/modules/test_shm_mq/test.c
index dd34bc7..22145db 100644
--- a/src/test/modules/test_shm_mq/test.c
+++ b/src/test/modules/test_shm_mq/test.c
@@ -230,7 +230,7 @@ test_shm_mq_pipelined(PG_FUNCTION_ARGS)
* have read or written data and therefore there may now be work
* for us to do.
*/
- WaitLatch(MyLatch, WL_LATCH_SET, 0);
+ WaitLatch(MyLatch, WL_LATCH_SET, 0, WE_EXTENSION);
ResetLatch(MyLatch);
CHECK_FOR_INTERRUPTS();
}
diff --git a/src/test/modules/worker_spi/worker_spi.c b/src/test/modules/worker_spi/worker_spi.c
index 7c9a3eb..9673b20 100644
--- a/src/test/modules/worker_spi/worker_spi.c
+++ b/src/test/modules/worker_spi/worker_spi.c
@@ -227,7 +227,8 @@ worker_spi_main(Datum main_arg)
*/
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- worker_spi_naptime * 1000L);
+ worker_spi_naptime * 1000L,
+ WE_EXTENSION);
ResetLatch(MyLatch);
/* emergency bailout if postmaster has died */
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers