Commit 1c6702f6 authored by Tom Lane's avatar Tom Lane

Avoid unnecessary work when stats collection is disabled. Tighten

search loop in pgstat_initstats.  Per report from Gavin Sherry.
parent e3d97d7d
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
* *
* Copyright (c) 2001-2003, PostgreSQL Global Development Group * Copyright (c) 2001-2003, PostgreSQL Global Development Group
* *
* $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.42 2003/08/04 00:43:21 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/postmaster/pgstat.c,v 1.43 2003/08/12 16:21:18 tgl Exp $
* ---------- * ----------
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -156,7 +156,8 @@ pgstat_init(void) ...@@ -156,7 +156,8 @@ pgstat_init(void)
/* /*
* Force start of collector daemon if something to collect * Force start of collector daemon if something to collect
*/ */
if (pgstat_collect_querystring || pgstat_collect_tuplelevel || if (pgstat_collect_querystring ||
pgstat_collect_tuplelevel ||
pgstat_collect_blocklevel) pgstat_collect_blocklevel)
pgstat_collect_startcollector = true; pgstat_collect_startcollector = true;
...@@ -536,15 +537,16 @@ void ...@@ -536,15 +537,16 @@ void
pgstat_report_tabstat(void) pgstat_report_tabstat(void)
{ {
int i; int i;
int n;
int len;
if (!pgstat_collect_querystring && !pgstat_collect_tuplelevel &&
!pgstat_collect_blocklevel)
return;
if (pgStatSock < 0) if (pgStatSock < 0 ||
!(pgstat_collect_querystring ||
pgstat_collect_tuplelevel ||
pgstat_collect_blocklevel))
{
/* Not reporting stats, so just flush whatever we have */
pgStatTabstatUsed = 0;
return; return;
}
/* /*
* For each message buffer used during the last query set the header * For each message buffer used during the last query set the header
...@@ -552,18 +554,21 @@ pgstat_report_tabstat(void) ...@@ -552,18 +554,21 @@ pgstat_report_tabstat(void)
*/ */
for (i = 0; i < pgStatTabstatUsed; i++) for (i = 0; i < pgStatTabstatUsed; i++)
{ {
n = pgStatTabstatMessages[i]->m_nentries; PgStat_MsgTabstat *tsmsg = pgStatTabstatMessages[i];
int n;
int len;
n = tsmsg->m_nentries;
len = offsetof(PgStat_MsgTabstat, m_entry[0]) + len = offsetof(PgStat_MsgTabstat, m_entry[0]) +
n * sizeof(PgStat_TableEntry); n * sizeof(PgStat_TableEntry);
pgStatTabstatMessages[i]->m_xact_commit = pgStatXactCommit; tsmsg->m_xact_commit = pgStatXactCommit;
pgStatTabstatMessages[i]->m_xact_rollback = pgStatXactRollback; tsmsg->m_xact_rollback = pgStatXactRollback;
pgStatXactCommit = 0; pgStatXactCommit = 0;
pgStatXactRollback = 0; pgStatXactRollback = 0;
pgstat_setheader(&pgStatTabstatMessages[i]->m_hdr, pgstat_setheader(&tsmsg->m_hdr, PGSTAT_MTYPE_TABSTAT);
PGSTAT_MTYPE_TABSTAT); pgstat_send(tsmsg, len);
pgstat_send(pgStatTabstatMessages[i], len);
} }
pgStatTabstatUsed = 0; pgStatTabstatUsed = 0;
...@@ -802,6 +807,53 @@ pgstat_ping(void) ...@@ -802,6 +807,53 @@ pgstat_ping(void)
pgstat_send(&msg, sizeof(msg)); pgstat_send(&msg, sizeof(msg));
} }
/*
* Create or enlarge the pgStatTabstatMessages array
*/
static bool
more_tabstat_space(void)
{
PgStat_MsgTabstat *newMessages;
PgStat_MsgTabstat **msgArray;
int newAlloc = pgStatTabstatAlloc + TABSTAT_QUANTUM;
int i;
/* Create (another) quantum of message buffers */
newMessages = (PgStat_MsgTabstat *)
malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);
if (newMessages == NULL)
{
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
return false;
}
/* Create or enlarge the pointer array */
if (pgStatTabstatMessages == NULL)
msgArray = (PgStat_MsgTabstat **)
malloc(sizeof(PgStat_MsgTabstat *) * newAlloc);
else
msgArray = (PgStat_MsgTabstat **)
realloc(pgStatTabstatMessages,
sizeof(PgStat_MsgTabstat *) * newAlloc);
if (msgArray == NULL)
{
free(newMessages);
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
return false;
}
MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);
for (i = 0; i < TABSTAT_QUANTUM; i++)
msgArray[pgStatTabstatAlloc + i] = newMessages++;
pgStatTabstatMessages = msgArray;
pgStatTabstatAlloc = newAlloc;
return true;
}
/* ---------- /* ----------
* pgstat_initstats() - * pgstat_initstats() -
...@@ -815,8 +867,9 @@ pgstat_ping(void) ...@@ -815,8 +867,9 @@ pgstat_ping(void)
void void
pgstat_initstats(PgStat_Info *stats, Relation rel) pgstat_initstats(PgStat_Info *stats, Relation rel)
{ {
PgStat_TableEntry *useent;
Oid rel_id = rel->rd_id; Oid rel_id = rel->rd_id;
PgStat_TableEntry *useent;
PgStat_MsgTabstat *tsmsg;
int mb; int mb;
int i; int i;
...@@ -828,69 +881,39 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) ...@@ -828,69 +881,39 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
stats->heap_scan_counted = FALSE; stats->heap_scan_counted = FALSE;
stats->index_scan_counted = FALSE; stats->index_scan_counted = FALSE;
if (pgStatSock < 0) if (pgStatSock < 0 ||
!(pgstat_collect_tuplelevel ||
pgstat_collect_blocklevel))
{ {
stats->no_stats = TRUE; stats->no_stats = TRUE;
return; return;
} }
/*
* On the first of all calls create some message buffers.
*/
if (pgStatTabstatMessages == NULL)
{
PgStat_MsgTabstat *newMessages;
PgStat_MsgTabstat **msgArray;
newMessages = (PgStat_MsgTabstat *)
malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);
if (newMessages == NULL)
{
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
return;
}
msgArray = (PgStat_MsgTabstat **)
malloc(sizeof(PgStat_MsgTabstat *) * TABSTAT_QUANTUM);
if (msgArray == NULL)
{
free(newMessages);
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
return;
}
MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);
for (i = 0; i < TABSTAT_QUANTUM; i++)
msgArray[i] = newMessages++;
pgStatTabstatMessages = msgArray;
pgStatTabstatAlloc = TABSTAT_QUANTUM;
}
/* /*
* Search the already-used message slots for this relation. * Search the already-used message slots for this relation.
*/ */
for (mb = 0; mb < pgStatTabstatUsed; mb++) for (mb = 0; mb < pgStatTabstatUsed; mb++)
{ {
for (i = 0; i < pgStatTabstatMessages[mb]->m_nentries; i++) tsmsg = pgStatTabstatMessages[mb];
for (i = tsmsg->m_nentries; --i >= 0; )
{ {
if (pgStatTabstatMessages[mb]->m_entry[i].t_id == rel_id) if (tsmsg->m_entry[i].t_id == rel_id)
{ {
stats->tabentry = (void *) &(pgStatTabstatMessages[mb]->m_entry[i]); stats->tabentry = (void *) &(tsmsg->m_entry[i]);
return; return;
} }
} }
if (pgStatTabstatMessages[mb]->m_nentries >= PGSTAT_NUM_TABENTRIES) if (tsmsg->m_nentries >= PGSTAT_NUM_TABENTRIES)
continue; continue;
/* /*
* Not found, but found a message buffer with an empty slot * Not found, but found a message buffer with an empty slot
* instead. Fine, let's use this one. * instead. Fine, let's use this one.
*/ */
i = pgStatTabstatMessages[mb]->m_nentries++; i = tsmsg->m_nentries++;
useent = &pgStatTabstatMessages[mb]->m_entry[i]; useent = &tsmsg->m_entry[i];
MemSet(useent, 0, sizeof(PgStat_TableEntry)); MemSet(useent, 0, sizeof(PgStat_TableEntry));
useent->t_id = rel_id; useent->t_id = rel_id;
stats->tabentry = (void *) useent; stats->tabentry = (void *) useent;
...@@ -902,43 +925,21 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) ...@@ -902,43 +925,21 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
*/ */
if (pgStatTabstatUsed >= pgStatTabstatAlloc) if (pgStatTabstatUsed >= pgStatTabstatAlloc)
{ {
int newAlloc = pgStatTabstatAlloc + TABSTAT_QUANTUM; if (!more_tabstat_space())
PgStat_MsgTabstat *newMessages;
PgStat_MsgTabstat **msgArray;
newMessages = (PgStat_MsgTabstat *)
malloc(sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);
if (newMessages == NULL)
{ {
ereport(LOG, stats->no_stats = TRUE;
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
return;
}
msgArray = (PgStat_MsgTabstat **)
realloc(pgStatTabstatMessages,
sizeof(PgStat_MsgTabstat *) * newAlloc);
if (msgArray == NULL)
{
free(newMessages);
ereport(LOG,
(errcode(ERRCODE_OUT_OF_MEMORY),
errmsg("out of memory")));
return; return;
} }
MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM); Assert(pgStatTabstatUsed < pgStatTabstatAlloc);
for (i = 0; i < TABSTAT_QUANTUM; i++)
msgArray[pgStatTabstatAlloc + i] = newMessages++;
pgStatTabstatMessages = msgArray;
pgStatTabstatAlloc = newAlloc;
} }
/* /*
* Use the first entry of the next message buffer. * Use the first entry of the next message buffer.
*/ */
mb = pgStatTabstatUsed++; mb = pgStatTabstatUsed++;
pgStatTabstatMessages[mb]->m_nentries = 1; tsmsg = pgStatTabstatMessages[mb];
useent = &pgStatTabstatMessages[mb]->m_entry[0]; tsmsg->m_nentries = 1;
useent = &tsmsg->m_entry[0];
MemSet(useent, 0, sizeof(PgStat_TableEntry)); MemSet(useent, 0, sizeof(PgStat_TableEntry));
useent->t_id = rel_id; useent->t_id = rel_id;
stats->tabentry = (void *) useent; stats->tabentry = (void *) useent;
...@@ -954,8 +955,9 @@ pgstat_initstats(PgStat_Info *stats, Relation rel) ...@@ -954,8 +955,9 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
void void
pgstat_count_xact_commit(void) pgstat_count_xact_commit(void)
{ {
if (!pgstat_collect_querystring && !pgstat_collect_tuplelevel && if (!(pgstat_collect_querystring ||
!pgstat_collect_blocklevel) pgstat_collect_tuplelevel ||
pgstat_collect_blocklevel))
return; return;
pgStatXactCommit++; pgStatXactCommit++;
...@@ -965,14 +967,16 @@ pgstat_count_xact_commit(void) ...@@ -965,14 +967,16 @@ pgstat_count_xact_commit(void)
* message buffer used without slots, causing the next report to tell * message buffer used without slots, causing the next report to tell
* new xact-counters. * new xact-counters.
*/ */
if (pgStatTabstatAlloc > 0) if (pgStatTabstatAlloc == 0)
{ {
if (!more_tabstat_space())
return;
}
if (pgStatTabstatUsed == 0) if (pgStatTabstatUsed == 0)
{ {
pgStatTabstatUsed++; pgStatTabstatUsed++;
pgStatTabstatMessages[0]->m_nentries = 0; pgStatTabstatMessages[0]->m_nentries = 0;
} }
}
} }
...@@ -985,8 +989,9 @@ pgstat_count_xact_commit(void) ...@@ -985,8 +989,9 @@ pgstat_count_xact_commit(void)
void void
pgstat_count_xact_rollback(void) pgstat_count_xact_rollback(void)
{ {
if (!pgstat_collect_querystring && !pgstat_collect_tuplelevel && if (!(pgstat_collect_querystring ||
!pgstat_collect_blocklevel) pgstat_collect_tuplelevel ||
pgstat_collect_blocklevel))
return; return;
pgStatXactRollback++; pgStatXactRollback++;
...@@ -996,14 +1001,16 @@ pgstat_count_xact_rollback(void) ...@@ -996,14 +1001,16 @@ pgstat_count_xact_rollback(void)
* message buffer used without slots, causing the next report to tell * message buffer used without slots, causing the next report to tell
* new xact-counters. * new xact-counters.
*/ */
if (pgStatTabstatAlloc > 0) if (pgStatTabstatAlloc == 0)
{ {
if (!more_tabstat_space())
return;
}
if (pgStatTabstatUsed == 0) if (pgStatTabstatUsed == 0)
{ {
pgStatTabstatUsed++; pgStatTabstatUsed++;
pgStatTabstatMessages[0]->m_nentries = 0; pgStatTabstatMessages[0]->m_nentries = 0;
} }
}
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment