summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas2008-06-30 10:58:47 +0000
committerHeikki Linnakangas2008-06-30 10:58:47 +0000
commit13928f0e4ccea0d3a5e6aafa2a7f3e4e2142df9b (patch)
tree94709233295e1b8a18f99a19459156cea9c3ae03
parentc82d141c6f1101719945e96206e0b5a65649202a (diff)
Turn PGBE_ACTIVITY_SIZE into a GUC variable, track_activity_query_size.
As the buffer could now be a lot larger than before, and copying it could thus be a lot more expensive than before, use strcpy instead of memcpy to copy the query string, as was already suggested in comments. Also, only copy the PgBackendStatus struct and string if the slot is in use. Patch by Thomas Lee, with some changes by me.
-rw-r--r--doc/src/sgml/config.sgml16
-rw-r--r--src/backend/postmaster/pgstat.c55
-rw-r--r--src/backend/utils/misc/guc.c9
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample1
-rw-r--r--src/include/pgstat.h6
5 files changed, 73 insertions, 14 deletions
diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 1fcbb54d13..a54c413823 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -3331,6 +3331,22 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
</listitem>
</varlistentry>
+ <varlistentry id="guc-track-activity-query-size" xreflabel="track_activity_query_size">
+ <term><varname>track_activity_query_size</varname> (<type>integer</type>)</term>
+ <indexterm>
+ <primary><varname>track_activity_query_size</> configuration parameter</primary>
+ </indexterm>
+ <listitem>
+ <para>
+ Specifies the number of bytes reserved to track the currently
+ executing command for each active session, for the
+ <structname>pg_stat_activity</>.<structfield>current_query</> field.
+ The default value is 1024. This parameter can only be set at server
+ start.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="guc-track-counts" xreflabel="track_counts">
<term><varname>track_counts</varname> (<type>boolean</type>)</term>
<indexterm>
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index f178fe31d3..34a2406a9a 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -101,6 +101,7 @@
bool pgstat_track_activities = false;
bool pgstat_track_counts = false;
int pgstat_track_functions = TRACK_FUNC_OFF;
+int pgstat_track_activity_query_size = 1024;
/*
* BgWriter global statistics counters (unused in other processes).
@@ -2010,6 +2011,7 @@ pgstat_fetch_global(void)
static PgBackendStatus *BackendStatusArray = NULL;
static PgBackendStatus *MyBEEntry = NULL;
+static char *BackendActivityBuffer = NULL;
/*
@@ -2020,20 +2022,25 @@ BackendStatusShmemSize(void)
{
Size size;
- size = mul_size(sizeof(PgBackendStatus), MaxBackends);
+ size = add_size(mul_size(sizeof(PgBackendStatus), MaxBackends),
+ mul_size(pgstat_track_activity_query_size, MaxBackends));
return size;
}
/*
- * Initialize the shared status array during postmaster startup.
+ * Initialize the shared status array and activity string buffer during
+ * postmaster startup.
*/
void
CreateSharedBackendStatus(void)
{
- Size size = BackendStatusShmemSize();
+ Size size;
bool found;
+ int i;
+ char *buffer;
/* Create or attach to the shared array */
+ size = mul_size(sizeof(PgBackendStatus), MaxBackends);
BackendStatusArray = (PgBackendStatus *)
ShmemInitStruct("Backend Status Array", size, &found);
@@ -2044,6 +2051,23 @@ CreateSharedBackendStatus(void)
*/
MemSet(BackendStatusArray, 0, size);
}
+
+ /* Create or attach to the shared activity buffer */
+ size = mul_size(pgstat_track_activity_query_size, MaxBackends);
+ BackendActivityBuffer = (char*)
+ ShmemInitStruct("Backend Activity Buffer", size, &found);
+
+ if (!found)
+ {
+ MemSet(BackendActivityBuffer, 0, size);
+
+ /* Initialize st_activity pointers. */
+ buffer = BackendActivityBuffer;
+ for (i = 0; i < MaxBackends; i++) {
+ BackendStatusArray[i].st_activity = buffer;
+ buffer += pgstat_track_activity_query_size;
+ }
+ }
}
@@ -2128,7 +2152,7 @@ pgstat_bestart(void)
beentry->st_waiting = false;
beentry->st_activity[0] = '\0';
/* Also make sure the last byte in the string area is always 0 */
- beentry->st_activity[PGBE_ACTIVITY_SIZE - 1] = '\0';
+ beentry->st_activity[pgstat_track_activity_query_size - 1] = '\0';
beentry->st_changecount++;
Assert((beentry->st_changecount & 1) == 0);
@@ -2188,7 +2212,7 @@ pgstat_report_activity(const char *cmd_str)
start_timestamp = GetCurrentStatementStartTimestamp();
len = strlen(cmd_str);
- len = pg_mbcliplen(cmd_str, len, PGBE_ACTIVITY_SIZE - 1);
+ len = pg_mbcliplen(cmd_str, len, pgstat_track_activity_query_size - 1);
/*
* Update my status entry, following the protocol of bumping
@@ -2267,6 +2291,7 @@ pgstat_read_current_status(void)
volatile PgBackendStatus *beentry;
PgBackendStatus *localtable;
PgBackendStatus *localentry;
+ char *localactivity;
int i;
Assert(!pgStatRunningInCollector);
@@ -2278,6 +2303,9 @@ pgstat_read_current_status(void)
localtable = (PgBackendStatus *)
MemoryContextAlloc(pgStatLocalContext,
sizeof(PgBackendStatus) * MaxBackends);
+ localactivity = (char *)
+ MemoryContextAlloc(pgStatLocalContext,
+ pgstat_track_activity_query_size * MaxBackends);
localNumBackends = 0;
beentry = BackendStatusArray;
@@ -2295,11 +2323,17 @@ pgstat_read_current_status(void)
{
int save_changecount = beentry->st_changecount;
- /*
- * XXX if PGBE_ACTIVITY_SIZE is really large, it might be best to
- * use strcpy not memcpy for copying the activity string?
- */
- memcpy(localentry, (char *) beentry, sizeof(PgBackendStatus));
+ localentry->st_procpid = beentry->st_procpid;
+ if (localentry->st_procpid > 0)
+ {
+ memcpy(localentry, (char *) beentry, sizeof(PgBackendStatus));
+ /*
+ * strcpy is safe even if the string is modified concurrently,
+ * because there's always a \0 at the end of the buffer.
+ */
+ strcpy(localactivity, (char *) beentry->st_activity);
+ localentry->st_activity = localactivity;
+ }
if (save_changecount == beentry->st_changecount &&
(save_changecount & 1) == 0)
@@ -2314,6 +2348,7 @@ pgstat_read_current_status(void)
if (localentry->st_procpid > 0)
{
localentry++;
+ localactivity += pgstat_track_activity_query_size;
localNumBackends++;
}
}
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index fa964370a9..456560ba3b 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1848,6 +1848,15 @@ static struct config_int ConfigureNamesInt[] =
-1, -1, INT_MAX, NULL, NULL
},
+ {
+ {"track_activity_query_size", PGC_POSTMASTER, RESOURCES_MEM,
+ gettext_noop("Sets the size reserved for pg_stat_activity.current_query, in bytes."),
+ NULL,
+ },
+ &pgstat_track_activity_query_size,
+ 1024, 100, 102400, NULL, NULL
+ },
+
/* End-of-list marker */
{
{NULL, 0, 0, NULL, NULL}, NULL, 0, 0, 0, NULL, NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index 033a74b2d4..552d856ae2 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -364,6 +364,7 @@
#track_activities = on
#track_counts = on
#track_functions = none # none, pl, all
+#track_activity_query_size = 1024
#update_process_title = on
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index a9f5501143..8abcc2f264 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -509,9 +509,6 @@ typedef struct PgStat_GlobalStats
* ----------
*/
-/* Max length of st_activity string ... perhaps replace with a GUC var? */
-#define PGBE_ACTIVITY_SIZE 1024
-
/* ----------
* PgBackendStatus
*
@@ -551,7 +548,7 @@ typedef struct PgBackendStatus
bool st_waiting;
/* current command string; MUST be null-terminated */
- char st_activity[PGBE_ACTIVITY_SIZE];
+ char *st_activity;
} PgBackendStatus;
/*
@@ -578,6 +575,7 @@ typedef struct PgStat_FunctionCallUsage
extern bool pgstat_track_activities;
extern bool pgstat_track_counts;
extern int pgstat_track_functions;
+extern int pgstat_track_activity_query_size;
/*
* BgWriter statistics counters are updated directly by bgwriter and bufmgr