Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit11da4c6

Browse files
committed
Adjust pgstat_initstats() to avoid repeated searches of the TabStat arrays
when a relation is opened multiple times in the same transaction. This isparticularly useful for system catalogs, which we may heap_open or index_openmany times in a transaction, and it doesn't really cost anything extra evenif the rel is touched but once. Motivated by study of an example from GregStark, in which pgstat_initstats() accounted for an unreasonably largefraction of the runtime.
1 parentca3d14f commit11da4c6

File tree

1 file changed

+74
-53
lines changed

1 file changed

+74
-53
lines changed

‎src/backend/postmaster/pgstat.c

Lines changed: 74 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
*
1414
*Copyright (c) 2001-2007, PostgreSQL Global Development Group
1515
*
16-
*$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.152 2007/03/30 18:34:55 mha Exp $
16+
*$PostgreSQL: pgsql/src/backend/postmaster/pgstat.c,v 1.153 2007/04/21 04:10:53 tgl Exp $
1717
* ----------
1818
*/
1919
#include"postgres.h"
@@ -114,6 +114,14 @@ static bool pgStatRunningInCollector = false;
114114
* Place where backends store per-table info to be sent to the collector.
115115
* We store shared relations separately from non-shared ones, to be able to
116116
* send them in separate messages.
117+
*
118+
* NOTE: once allocated, a PgStat_MsgTabstat struct belonging to a
119+
* TabStatArray is never moved or deleted for the life of the backend.
120+
* Also, we zero out the t_id fields of the contained PgStat_TableEntry
121+
* structs whenever they are not actively in use. This allows PgStat_Info
122+
* pointers to be treated as long-lived data, avoiding repeated searches in
123+
* pgstat_initstats() when a relation is repeatedly heap_open'd or
124+
* index_open'd during a transaction.
117125
*/
118126
typedefstructTabStatArray
119127
{
@@ -169,6 +177,7 @@ static void pgstat_write_statsfile(void);
169177
staticHTAB*pgstat_read_statsfile(Oidonlydb);
170178
staticvoidbackend_read_statsfile(void);
171179
staticvoidpgstat_read_current_status(void);
180+
staticvoidpgstat_report_one_tabstat(TabStatArray*tsarr,Oiddbid);
172181
staticHTAB*pgstat_collect_oids(Oidcatalogid);
173182

174183
staticvoidpgstat_setup_memcxt(void);
@@ -606,25 +615,22 @@ void allow_immediate_pgstat_restart(void)
606615
void
607616
pgstat_report_tabstat(void)
608617
{
609-
inti;
610-
611-
if (pgStatSock<0||
612-
(!pgstat_collect_tuplelevel&&
613-
!pgstat_collect_blocklevel))
614-
{
615-
/* Not reporting stats, so just flush whatever we have */
616-
RegularTabStat.tsa_used=0;
617-
SharedTabStat.tsa_used=0;
618-
return;
619-
}
620-
621618
/*
622619
* For each message buffer used during the last query set the header
623-
* fields and send it out.
620+
* fields and send it out; then mark the entries unused.
624621
*/
625-
for (i=0;i<RegularTabStat.tsa_used;i++)
622+
pgstat_report_one_tabstat(&RegularTabStat,MyDatabaseId);
623+
pgstat_report_one_tabstat(&SharedTabStat,InvalidOid);
624+
}
625+
626+
staticvoid
627+
pgstat_report_one_tabstat(TabStatArray*tsarr,Oiddbid)
628+
{
629+
inti;
630+
631+
for (i=0;i<tsarr->tsa_used;i++)
626632
{
627-
PgStat_MsgTabstat*tsmsg=RegularTabStat.tsa_messages[i];
633+
PgStat_MsgTabstat*tsmsg=tsarr->tsa_messages[i];
628634
intn;
629635
intlen;
630636

@@ -637,32 +643,24 @@ pgstat_report_tabstat(void)
637643
pgStatXactCommit=0;
638644
pgStatXactRollback=0;
639645

640-
pgstat_setheader(&tsmsg->m_hdr,PGSTAT_MTYPE_TABSTAT);
641-
tsmsg->m_databaseid=MyDatabaseId;
642-
pgstat_send(tsmsg,len);
643-
}
644-
RegularTabStat.tsa_used=0;
645-
646-
/* Ditto, for shared relations */
647-
for (i=0;i<SharedTabStat.tsa_used;i++)
648-
{
649-
PgStat_MsgTabstat*tsmsg=SharedTabStat.tsa_messages[i];
650-
intn;
651-
intlen;
652-
653-
n=tsmsg->m_nentries;
654-
len= offsetof(PgStat_MsgTabstat,m_entry[0])+
655-
n*sizeof(PgStat_TableEntry);
656-
657-
/* We don't report transaction commit/abort here */
658-
tsmsg->m_xact_commit=0;
659-
tsmsg->m_xact_rollback=0;
646+
/*
647+
* It's unlikely we'd get here with no socket, but maybe not
648+
* impossible
649+
*/
650+
if (pgStatSock >=0)
651+
{
652+
pgstat_setheader(&tsmsg->m_hdr,PGSTAT_MTYPE_TABSTAT);
653+
tsmsg->m_databaseid=dbid;
654+
pgstat_send(tsmsg,len);
655+
}
660656

661-
pgstat_setheader(&tsmsg->m_hdr,PGSTAT_MTYPE_TABSTAT);
662-
tsmsg->m_databaseid=InvalidOid;
663-
pgstat_send(tsmsg,len);
657+
/*
658+
* Zero out the entries, to mark them unused and prepare them
659+
* for next use.
660+
*/
661+
MemSet(tsmsg,0,len);
664662
}
665-
SharedTabStat.tsa_used=0;
663+
tsarr->tsa_used=0;
666664
}
667665

668666

@@ -1013,7 +1011,7 @@ more_tabstat_space(TabStatArray *tsarr)
10131011

10141012
newAlloc=tsarr->tsa_alloc+TABSTAT_QUANTUM;
10151013

1016-
/* Create (another) quantum of message buffers */
1014+
/* Create (another) quantum of message buffers, and zero them */
10171015
newMessages= (PgStat_MsgTabstat*)
10181016
MemoryContextAllocZero(TopMemoryContext,
10191017
sizeof(PgStat_MsgTabstat)*TABSTAT_QUANTUM);
@@ -1043,6 +1041,17 @@ more_tabstat_space(TabStatArray *tsarr)
10431041
*of Relation or Scan structures. The data placed into these
10441042
*structures from here tell where later to count for buffer reads,
10451043
*scans and tuples fetched.
1044+
*
1045+
*NOTE: PgStat_Info pointers in scan structures are really redundant
1046+
*with those in relcache entries. The passed stats pointer might point
1047+
*either to the Relation struct's own pgstat_info field, or to one in
1048+
*a scan structure; we'll set the Relation pg_statinfo and copy it to
1049+
*the scan struct.
1050+
*
1051+
*We assume that a relcache entry's pgstat_info field is zeroed by
1052+
*relcache.c when the relcache entry is made; thereafter it is long-lived
1053+
*data. We can avoid repeated searches of the TabStat arrays when the
1054+
*same relation is touched repeatedly within a transaction.
10461055
* ----------
10471056
*/
10481057
void
@@ -1055,21 +1064,31 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
10551064
intmb;
10561065
inti;
10571066

1058-
/*
1059-
* Initialize data not to count at all.
1060-
*/
1061-
stats->tabentry=NULL;
1062-
10631067
if (pgStatSock<0||
10641068
!(pgstat_collect_tuplelevel||
10651069
pgstat_collect_blocklevel))
1070+
{
1071+
/* We're not counting at all. */
1072+
stats->tabentry=NULL;
10661073
return;
1074+
}
10671075

1068-
tsarr=rel->rd_rel->relisshared ?&SharedTabStat :&RegularTabStat;
1076+
/*
1077+
* If we already set up this relation in the current transaction,
1078+
* just copy the pointer.
1079+
*/
1080+
if (rel->pgstat_info.tabentry!=NULL&&
1081+
((PgStat_TableEntry*)rel->pgstat_info.tabentry)->t_id==rel_id)
1082+
{
1083+
stats->tabentry=rel->pgstat_info.tabentry;
1084+
return;
1085+
}
10691086

10701087
/*
10711088
* Search the already-used message slots for this relation.
10721089
*/
1090+
tsarr=rel->rd_rel->relisshared ?&SharedTabStat :&RegularTabStat;
1091+
10731092
for (mb=0;mb<tsarr->tsa_used;mb++)
10741093
{
10751094
tsmsg=tsarr->tsa_messages[mb];
@@ -1078,7 +1097,8 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
10781097
{
10791098
if (tsmsg->m_entry[i].t_id==rel_id)
10801099
{
1081-
stats->tabentry= (void*)&(tsmsg->m_entry[i]);
1100+
rel->pgstat_info.tabentry= (void*)&(tsmsg->m_entry[i]);
1101+
stats->tabentry=rel->pgstat_info.tabentry;
10821102
return;
10831103
}
10841104
}
@@ -1088,13 +1108,14 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
10881108

10891109
/*
10901110
* Not found, but found a message buffer with an empty slot instead.
1091-
* Fine, let's use this one.
1111+
* Fine, let's use this one. We assume the entry was already zeroed,
1112+
* either at creation or after last use.
10921113
*/
10931114
i=tsmsg->m_nentries++;
10941115
useent=&tsmsg->m_entry[i];
1095-
MemSet(useent,0,sizeof(PgStat_TableEntry));
10961116
useent->t_id=rel_id;
1097-
stats->tabentry= (void*)useent;
1117+
rel->pgstat_info.tabentry= (void*)useent;
1118+
stats->tabentry=rel->pgstat_info.tabentry;
10981119
return;
10991120
}
11001121

@@ -1111,9 +1132,9 @@ pgstat_initstats(PgStat_Info *stats, Relation rel)
11111132
tsmsg=tsarr->tsa_messages[mb];
11121133
tsmsg->m_nentries=1;
11131134
useent=&tsmsg->m_entry[0];
1114-
MemSet(useent,0,sizeof(PgStat_TableEntry));
11151135
useent->t_id=rel_id;
1116-
stats->tabentry= (void*)useent;
1136+
rel->pgstat_info.tabentry= (void*)useent;
1137+
stats->tabentry=rel->pgstat_info.tabentry;
11171138
}
11181139

11191140

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp