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

Commit54b6cd5

Browse files
committed
Speedup pgstat_report_activity by moving mb-aware truncation to read side.
Previously multi-byte aware truncation was done on everypgstat_report_activity() call - proving to be a bottleneck forworkloads with long query strings that execute quickly.Instead move the truncation to the read side, which commonly isexecuted far less frequently. That's possible because all serverencodings allow to determine the length of a multi-byte string fromthe first byte.Rename PgBackendStatus.st_activity to st_activity_raw so existingextension users of the field break - their code has to be adjusted touse pgstat_clip_activity().Author: Andres FreundTested-By: Khuntal GhoshReviewed-By: Robert Haas, Tom LaneDiscussion:https://postgr.es/m/20170912071948.pa7igbpkkkviecpz@alap3.anarazel.de
1 parentd1687c6 commit54b6cd5

File tree

3 files changed

+72
-20
lines changed

3 files changed

+72
-20
lines changed

‎src/backend/postmaster/pgstat.c

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2701,7 +2701,7 @@ CreateSharedBackendStatus(void)
27012701
buffer=BackendActivityBuffer;
27022702
for (i=0;i<NumBackendStatSlots;i++)
27032703
{
2704-
BackendStatusArray[i].st_activity=buffer;
2704+
BackendStatusArray[i].st_activity_raw=buffer;
27052705
buffer+=pgstat_track_activity_query_size;
27062706
}
27072707
}
@@ -2922,11 +2922,11 @@ pgstat_bestart(void)
29222922
#endif
29232923
beentry->st_state=STATE_UNDEFINED;
29242924
beentry->st_appname[0]='\0';
2925-
beentry->st_activity[0]='\0';
2925+
beentry->st_activity_raw[0]='\0';
29262926
/* Also make sure the last byte in each string area is always 0 */
29272927
beentry->st_clienthostname[NAMEDATALEN-1]='\0';
29282928
beentry->st_appname[NAMEDATALEN-1]='\0';
2929-
beentry->st_activity[pgstat_track_activity_query_size-1]='\0';
2929+
beentry->st_activity_raw[pgstat_track_activity_query_size-1]='\0';
29302930
beentry->st_progress_command=PROGRESS_COMMAND_INVALID;
29312931
beentry->st_progress_command_target=InvalidOid;
29322932

@@ -3017,7 +3017,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
30173017
pgstat_increment_changecount_before(beentry);
30183018
beentry->st_state=STATE_DISABLED;
30193019
beentry->st_state_start_timestamp=0;
3020-
beentry->st_activity[0]='\0';
3020+
beentry->st_activity_raw[0]='\0';
30213021
beentry->st_activity_start_timestamp=0;
30223022
/* st_xact_start_timestamp and wait_event_info are also disabled */
30233023
beentry->st_xact_start_timestamp=0;
@@ -3034,8 +3034,12 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
30343034
start_timestamp=GetCurrentStatementStartTimestamp();
30353035
if (cmd_str!=NULL)
30363036
{
3037-
len=pg_mbcliplen(cmd_str,strlen(cmd_str),
3038-
pgstat_track_activity_query_size-1);
3037+
/*
3038+
* Compute length of to-be-stored string unaware of multi-byte
3039+
* characters. For speed reasons that'll get corrected on read, rather
3040+
* than computed every write.
3041+
*/
3042+
len=Min(strlen(cmd_str),pgstat_track_activity_query_size-1);
30393043
}
30403044
current_timestamp=GetCurrentTimestamp();
30413045

@@ -3049,8 +3053,8 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
30493053

30503054
if (cmd_str!=NULL)
30513055
{
3052-
memcpy((char*)beentry->st_activity,cmd_str,len);
3053-
beentry->st_activity[len]='\0';
3056+
memcpy((char*)beentry->st_activity_raw,cmd_str,len);
3057+
beentry->st_activity_raw[len]='\0';
30543058
beentry->st_activity_start_timestamp=start_timestamp;
30553059
}
30563060

@@ -3278,8 +3282,8 @@ pgstat_read_current_status(void)
32783282
*/
32793283
strcpy(localappname, (char*)beentry->st_appname);
32803284
localentry->backendStatus.st_appname=localappname;
3281-
strcpy(localactivity, (char*)beentry->st_activity);
3282-
localentry->backendStatus.st_activity=localactivity;
3285+
strcpy(localactivity, (char*)beentry->st_activity_raw);
3286+
localentry->backendStatus.st_activity_raw=localactivity;
32833287
localentry->backendStatus.st_ssl=beentry->st_ssl;
32843288
#ifdefUSE_SSL
32853289
if (beentry->st_ssl)
@@ -3945,10 +3949,13 @@ pgstat_get_backend_current_activity(int pid, bool checkUser)
39453949
/* Now it is safe to use the non-volatile pointer */
39463950
if (checkUser&& !superuser()&&beentry->st_userid!=GetUserId())
39473951
return"<insufficient privilege>";
3948-
elseif (*(beentry->st_activity)=='\0')
3952+
elseif (*(beentry->st_activity_raw)=='\0')
39493953
return"<command string not enabled>";
39503954
else
3951-
returnbeentry->st_activity;
3955+
{
3956+
/* this'll leak a bit of memory, but that seems acceptable */
3957+
returnpgstat_clip_activity(beentry->st_activity_raw);
3958+
}
39523959
}
39533960

39543961
beentry++;
@@ -3994,7 +4001,7 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
39944001
if (beentry->st_procpid==pid)
39954002
{
39964003
/* Read pointer just once, so it can't change after validation */
3997-
constchar*activity=beentry->st_activity;
4004+
constchar*activity=beentry->st_activity_raw;
39984005
constchar*activity_last;
39994006

40004007
/*
@@ -4017,7 +4024,8 @@ pgstat_get_crashed_backend_activity(int pid, char *buffer, int buflen)
40174024
/*
40184025
* Copy only ASCII-safe characters so we don't run into encoding
40194026
* problems when reporting the message; and be sure not to run off
4020-
* the end of memory.
4027+
* the end of memory. As only ASCII characters are reported, it
4028+
* doesn't seem necessary to perform multibyte aware clipping.
40214029
*/
40224030
ascii_safe_strlcpy(buffer,activity,
40234031
Min(buflen,pgstat_track_activity_query_size));
@@ -6270,3 +6278,30 @@ pgstat_db_requested(Oid databaseid)
62706278

62716279
return false;
62726280
}
6281+
6282+
/*
6283+
* Convert a potentially unsafely truncated activity string (see
6284+
* PgBackendStatus.st_activity_raw's documentation) into a correctly truncated
6285+
* one.
6286+
*
6287+
* The returned string is allocated in the caller's memory context and may be
6288+
* freed.
6289+
*/
6290+
char*
6291+
pgstat_clip_activity(constchar*activity)
6292+
{
6293+
intrawlen=strnlen(activity,pgstat_track_activity_query_size-1);
6294+
intcliplen;
6295+
6296+
/*
6297+
* All supported server-encodings make it possible to determine the length
6298+
* of a multi-byte character from its first byte (this is not the case for
6299+
* client encodings, see GB18030). As st_activity is always stored using
6300+
* server encoding, this allows us to perform multi-byte aware truncation,
6301+
* even if the string earlier was truncated in the middle of a multi-byte
6302+
* character.
6303+
*/
6304+
cliplen=pg_mbcliplen(activity,rawlen,
6305+
pgstat_track_activity_query_size-1);
6306+
returnpnstrdup(activity,cliplen);
6307+
}

‎src/backend/utils/adt/pgstatfuncs.c

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
664664
is_member_of_role(GetUserId(),DEFAULT_ROLE_READ_ALL_STATS))
665665
{
666666
SockAddrzero_clientaddr;
667+
char*clipped_activity;
667668

668669
switch (beentry->st_state)
669670
{
@@ -690,7 +691,9 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
690691
break;
691692
}
692693

693-
values[5]=CStringGetTextDatum(beentry->st_activity);
694+
clipped_activity=pgstat_clip_activity(beentry->st_activity_raw);
695+
values[5]=CStringGetTextDatum(clipped_activity);
696+
pfree(clipped_activity);
694697

695698
proc=BackendPidGetProc(beentry->st_procpid);
696699
if (proc!=NULL)
@@ -906,17 +909,23 @@ pg_stat_get_backend_activity(PG_FUNCTION_ARGS)
906909
int32beid=PG_GETARG_INT32(0);
907910
PgBackendStatus*beentry;
908911
constchar*activity;
912+
char*clipped_activity;
913+
text*ret;
909914

910915
if ((beentry=pgstat_fetch_stat_beentry(beid))==NULL)
911916
activity="<backend information not available>";
912917
elseif (!has_privs_of_role(GetUserId(),beentry->st_userid))
913918
activity="<insufficient privilege>";
914-
elseif (*(beentry->st_activity)=='\0')
919+
elseif (*(beentry->st_activity_raw)=='\0')
915920
activity="<command string not enabled>";
916921
else
917-
activity=beentry->st_activity;
922+
activity=beentry->st_activity_raw;
918923

919-
PG_RETURN_TEXT_P(cstring_to_text(activity));
924+
clipped_activity=pgstat_clip_activity(activity);
925+
ret=cstring_to_text(activity);
926+
pfree(clipped_activity);
927+
928+
PG_RETURN_TEXT_P(ret);
920929
}
921930

922931
Datum

‎src/include/pgstat.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,8 +1003,14 @@ typedef struct PgBackendStatus
10031003
/* application name; MUST be null-terminated */
10041004
char*st_appname;
10051005

1006-
/* current command string; MUST be null-terminated */
1007-
char*st_activity;
1006+
/*
1007+
* Current command string; MUST be null-terminated. Note that this string
1008+
* possibly is truncated in the middle of a multi-byte character. As
1009+
* activity strings are stored more frequently than read, that allows to
1010+
* move the cost of correct truncation to the display side. Use
1011+
* pgstat_clip_activity() to truncate correctly.
1012+
*/
1013+
char*st_activity_raw;
10081014

10091015
/*
10101016
* Command progress reporting. Any command which wishes can advertise
@@ -1193,6 +1199,8 @@ extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
11931199

11941200
externvoidpgstat_initstats(Relationrel);
11951201

1202+
externchar*pgstat_clip_activity(constchar*activity);
1203+
11961204
/* ----------
11971205
* pgstat_report_wait_start() -
11981206
*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp