Avoid unnecessary work when stats collection is disabled. Tighten
authorTom Lane
Tue, 12 Aug 2003 16:21:18 +0000 (16:21 +0000)
committerTom Lane
Tue, 12 Aug 2003 16:21:18 +0000 (16:21 +0000)
search loop in pgstat_initstats.  Per report from Gavin Sherry.

src/backend/postmaster/pgstat.c

index 5e603a00b14f28fa577896ef3f31bd1903dd8ac4..aef71fd49676502bcaa92dc926bc62adc86fa796 100644 (file)
@@ -13,7 +13,7 @@
  *
  * 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"
@@ -156,7 +156,8 @@ pgstat_init(void)
    /*
     * 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_startcollector = true;
 
@@ -536,15 +537,16 @@ void
 pgstat_report_tabstat(void)
 {
    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;
+   }
 
    /*
     * For each message buffer used during the last query set the header
@@ -552,18 +554,21 @@ pgstat_report_tabstat(void)
     */
    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]) +
            n * sizeof(PgStat_TableEntry);
 
-       pgStatTabstatMessages[i]->m_xact_commit = pgStatXactCommit;
-       pgStatTabstatMessages[i]->m_xact_rollback = pgStatXactRollback;
+       tsmsg->m_xact_commit = pgStatXactCommit;
+       tsmsg->m_xact_rollback = pgStatXactRollback;
        pgStatXactCommit = 0;
        pgStatXactRollback = 0;
 
-       pgstat_setheader(&pgStatTabstatMessages[i]->m_hdr,
-                        PGSTAT_MTYPE_TABSTAT);
-       pgstat_send(pgStatTabstatMessages[i], len);
+       pgstat_setheader(&tsmsg->m_hdr, PGSTAT_MTYPE_TABSTAT);
+       pgstat_send(tsmsg, len);
    }
 
    pgStatTabstatUsed = 0;
@@ -802,6 +807,53 @@ pgstat_ping(void)
    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() -
@@ -815,8 +867,9 @@ pgstat_ping(void)
 void
 pgstat_initstats(PgStat_Info *stats, Relation rel)
 {
-   PgStat_TableEntry *useent;
    Oid         rel_id = rel->rd_id;
+   PgStat_TableEntry *useent;
+   PgStat_MsgTabstat *tsmsg;
    int         mb;
    int         i;
 
@@ -828,69 +881,39 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
    stats->heap_scan_counted = FALSE;
    stats->index_scan_counted = FALSE;
 
-   if (pgStatSock < 0)
+   if (pgStatSock < 0 ||
+       !(pgstat_collect_tuplelevel ||
+         pgstat_collect_blocklevel))
    {
        stats->no_stats = TRUE;
        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.
     */
    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;
            }
        }
 
-       if (pgStatTabstatMessages[mb]->m_nentries >= PGSTAT_NUM_TABENTRIES)
+       if (tsmsg->m_nentries >= PGSTAT_NUM_TABENTRIES)
            continue;
 
        /*
         * Not found, but found a message buffer with an empty slot
         * instead. Fine, let's use this one.
         */
-       i = pgStatTabstatMessages[mb]->m_nentries++;
-       useent = &pgStatTabstatMessages[mb]->m_entry[i];
+       i = tsmsg->m_nentries++;
+       useent = &tsmsg->m_entry[i];
        MemSet(useent, 0, sizeof(PgStat_TableEntry));
        useent->t_id = rel_id;
        stats->tabentry = (void *) useent;
@@ -902,43 +925,21 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
     */
    if (pgStatTabstatUsed >= pgStatTabstatAlloc)
    {
-       int         newAlloc = pgStatTabstatAlloc + TABSTAT_QUANTUM;
-       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 **)
-           realloc(pgStatTabstatMessages,
-                   sizeof(PgStat_MsgTabstat *) * newAlloc);
-       if (msgArray == NULL)
+       if (!more_tabstat_space())
        {
-           free(newMessages);
-           ereport(LOG,
-                   (errcode(ERRCODE_OUT_OF_MEMORY),
-                    errmsg("out of memory")));
+           stats->no_stats = TRUE;
            return;
        }
-       MemSet(newMessages, 0, sizeof(PgStat_MsgTabstat) * TABSTAT_QUANTUM);
-       for (i = 0; i < TABSTAT_QUANTUM; i++)
-           msgArray[pgStatTabstatAlloc + i] = newMessages++;
-       pgStatTabstatMessages = msgArray;
-       pgStatTabstatAlloc = newAlloc;
+       Assert(pgStatTabstatUsed < pgStatTabstatAlloc);
    }
 
    /*
     * Use the first entry of the next message buffer.
     */
    mb = pgStatTabstatUsed++;
-   pgStatTabstatMessages[mb]->m_nentries = 1;
-   useent = &pgStatTabstatMessages[mb]->m_entry[0];
+   tsmsg = pgStatTabstatMessages[mb];
+   tsmsg->m_nentries = 1;
+   useent = &tsmsg->m_entry[0];
    MemSet(useent, 0, sizeof(PgStat_TableEntry));
    useent->t_id = rel_id;
    stats->tabentry = (void *) useent;
@@ -954,8 +955,9 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
 void
 pgstat_count_xact_commit(void)
 {
-   if (!pgstat_collect_querystring && !pgstat_collect_tuplelevel &&
-       !pgstat_collect_blocklevel)
+   if (!(pgstat_collect_querystring ||
+         pgstat_collect_tuplelevel ||
+         pgstat_collect_blocklevel))
        return;
 
    pgStatXactCommit++;
@@ -965,13 +967,15 @@ pgstat_count_xact_commit(void)
     * message buffer used without slots, causing the next report to tell
     * new xact-counters.
     */
-   if (pgStatTabstatAlloc > 0)
+   if (pgStatTabstatAlloc == 0)
    {
-       if (pgStatTabstatUsed == 0)
-       {
-           pgStatTabstatUsed++;
-           pgStatTabstatMessages[0]->m_nentries = 0;
-       }
+       if (!more_tabstat_space())
+           return;
+   }
+   if (pgStatTabstatUsed == 0)
+   {
+       pgStatTabstatUsed++;
+       pgStatTabstatMessages[0]->m_nentries = 0;
    }
 }
 
@@ -985,8 +989,9 @@ pgstat_count_xact_commit(void)
 void
 pgstat_count_xact_rollback(void)
 {
-   if (!pgstat_collect_querystring && !pgstat_collect_tuplelevel &&
-       !pgstat_collect_blocklevel)
+   if (!(pgstat_collect_querystring ||
+         pgstat_collect_tuplelevel ||
+         pgstat_collect_blocklevel))
        return;
 
    pgStatXactRollback++;
@@ -996,13 +1001,15 @@ pgstat_count_xact_rollback(void)
     * message buffer used without slots, causing the next report to tell
     * new xact-counters.
     */
-   if (pgStatTabstatAlloc > 0)
+   if (pgStatTabstatAlloc == 0)
    {
-       if (pgStatTabstatUsed == 0)
-       {
-           pgStatTabstatUsed++;
-           pgStatTabstatMessages[0]->m_nentries = 0;
-       }
+       if (!more_tabstat_space())
+           return;
+   }
+   if (pgStatTabstatUsed == 0)
+   {
+       pgStatTabstatUsed++;
+       pgStatTabstatMessages[0]->m_nentries = 0;
    }
 }