Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
5a4e19ab
Commit
5a4e19ab
authored
Aug 12, 2010
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add the ability to compute per-statement latencies (ie, average execution
times) to pgbench. Florian Pflug, reviewed by Greg Smith
parent
47eeb5e6
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
254 additions
and
64 deletions
+254
-64
contrib/pgbench/pgbench.c
contrib/pgbench/pgbench.c
+174
-53
doc/src/sgml/pgbench.sgml
doc/src/sgml/pgbench.sgml
+80
-11
No files found.
contrib/pgbench/pgbench.c
View file @
5a4e19ab
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
* A simple benchmark program for PostgreSQL
* A simple benchmark program for PostgreSQL
* Originally written by Tatsuo Ishii and enhanced by many contributors.
* Originally written by Tatsuo Ishii and enhanced by many contributors.
*
*
* $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.
99 2010/07/06 19:18:55 momjian
Exp $
* $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.
100 2010/08/12 20:39:39 tgl
Exp $
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
* ALL RIGHTS RESERVED;
*
*
...
@@ -133,6 +133,7 @@ int fillfactor = 100;
...
@@ -133,6 +133,7 @@ int fillfactor = 100;
bool
use_log
;
/* log transaction latencies to a file */
bool
use_log
;
/* log transaction latencies to a file */
bool
is_connect
;
/* establish connection for each transaction */
bool
is_connect
;
/* establish connection for each transaction */
bool
is_latencies
;
/* report per-command latencies */
int
main_pid
;
/* main process id used in log filename */
int
main_pid
;
/* main process id used in log filename */
char
*
pghost
=
""
;
char
*
pghost
=
""
;
...
@@ -171,7 +172,8 @@ typedef struct
...
@@ -171,7 +172,8 @@ typedef struct
int64
until
;
/* napping until (usec) */
int64
until
;
/* napping until (usec) */
Variable
*
variables
;
/* array of variable definitions */
Variable
*
variables
;
/* array of variable definitions */
int
nvariables
;
int
nvariables
;
instr_time
txn_begin
;
/* used for measuring latencies */
instr_time
txn_begin
;
/* used for measuring transaction latencies */
instr_time
stmt_begin
;
/* used for measuring statement latencies */
int
use_file
;
/* index in sql_files for this client */
int
use_file
;
/* index in sql_files for this client */
bool
prepared
[
MAX_FILES
];
bool
prepared
[
MAX_FILES
];
}
CState
;
}
CState
;
...
@@ -186,6 +188,8 @@ typedef struct
...
@@ -186,6 +188,8 @@ typedef struct
CState
*
state
;
/* array of CState */
CState
*
state
;
/* array of CState */
int
nstate
;
/* length of state[] */
int
nstate
;
/* length of state[] */
instr_time
start_time
;
/* thread start time */
instr_time
start_time
;
/* thread start time */
instr_time
*
exec_elapsed
;
/* time spent executing cmds (per Command) */
int
*
exec_count
;
/* number of cmd executions (per Command) */
}
TState
;
}
TState
;
#define INVALID_THREAD ((pthread_t) 0)
#define INVALID_THREAD ((pthread_t) 0)
...
@@ -216,13 +220,16 @@ static const char *QUERYMODE[] = {"simple", "extended", "prepared"};
...
@@ -216,13 +220,16 @@ static const char *QUERYMODE[] = {"simple", "extended", "prepared"};
typedef
struct
typedef
struct
{
{
char
*
line
;
/* full text of command line */
int
command_num
;
/* unique index of this Command struct */
int
type
;
/* command type (SQL_COMMAND or META_COMMAND) */
int
type
;
/* command type (SQL_COMMAND or META_COMMAND) */
int
argc
;
/* number of commands */
int
argc
;
/* number of command
word
s */
char
*
argv
[
MAX_ARGS
];
/* command list */
char
*
argv
[
MAX_ARGS
];
/* command
word
list */
}
Command
;
}
Command
;
static
Command
**
sql_files
[
MAX_FILES
];
/* SQL script files */
static
Command
**
sql_files
[
MAX_FILES
];
/* SQL script files */
static
int
num_files
;
/* number of script files */
static
int
num_files
;
/* number of script files */
static
int
num_commands
=
0
;
/* total number of Command structs */
static
int
debug
=
0
;
/* debug flag */
static
int
debug
=
0
;
/* debug flag */
/* default scenario */
/* default scenario */
...
@@ -287,6 +294,7 @@ usage(const char *progname)
...
@@ -287,6 +294,7 @@ usage(const char *progname)
" define variable for use by custom script
\n
"
" define variable for use by custom script
\n
"
" -f FILENAME read transaction script from FILENAME
\n
"
" -f FILENAME read transaction script from FILENAME
\n
"
" -j NUM number of threads (default: 1)
\n
"
" -j NUM number of threads (default: 1)
\n
"
" -r report average latency per command
\n
"
" -l write transaction times to log file
\n
"
" -l write transaction times to log file
\n
"
" -M {simple|extended|prepared}
\n
"
" -M {simple|extended|prepared}
\n
"
" protocol for submitting queries to server (default: simple)
\n
"
" protocol for submitting queries to server (default: simple)
\n
"
...
@@ -629,11 +637,13 @@ runShellCommand(CState *st, char *variable, char **argv, int argc)
...
@@ -629,11 +637,13 @@ runShellCommand(CState *st, char *variable, char **argv, int argc)
char
*
endptr
;
char
*
endptr
;
int
retval
;
int
retval
;
/*
/*----------
* Join arguments with whilespace separaters. Arguments starting with
* Join arguments with whitespace separators. Arguments starting with
* exactly one colon are treated as variables: name - append a string
* exactly one colon are treated as variables:
* "name" :var - append a variable named 'var'. ::name - append a string
* name - append a string "name"
* ":name"
* :var - append a variable named 'var'
* ::name - append a string ":name"
*----------
*/
*/
for
(
i
=
0
;
i
<
argc
;
i
++
)
for
(
i
=
0
;
i
<
argc
;
i
++
)
{
{
...
@@ -740,7 +750,7 @@ clientDone(CState *st, bool ok)
...
@@ -740,7 +750,7 @@ clientDone(CState *st, bool ok)
/* return false iff client should be disconnected */
/* return false iff client should be disconnected */
static
bool
static
bool
doCustom
(
CState
*
st
,
instr_time
*
conn_time
,
FILE
*
logfile
)
doCustom
(
TState
*
thread
,
CState
*
st
,
instr_time
*
conn_time
,
FILE
*
logfile
)
{
{
PGresult
*
res
;
PGresult
*
res
;
Command
**
commands
;
Command
**
commands
;
...
@@ -775,7 +785,22 @@ top:
...
@@ -775,7 +785,22 @@ top:
}
}
/*
/*
* transaction finished: record the time it took in the log
* command finished: accumulate per-command execution times in
* thread-local data structure, if per-command latencies are requested
*/
if
(
is_latencies
)
{
instr_time
now
;
int
cnum
=
commands
[
st
->
state
]
->
command_num
;
INSTR_TIME_SET_CURRENT
(
now
);
INSTR_TIME_ACCUM_DIFF
(
thread
->
exec_elapsed
[
cnum
],
now
,
st
->
stmt_begin
);
thread
->
exec_count
[
cnum
]
++
;
}
/*
* if transaction finished, record the time it took in the log
*/
*/
if
(
logfile
&&
commands
[
st
->
state
+
1
]
==
NULL
)
if
(
logfile
&&
commands
[
st
->
state
+
1
]
==
NULL
)
{
{
...
@@ -802,6 +827,10 @@ top:
...
@@ -802,6 +827,10 @@ top:
if
(
commands
[
st
->
state
]
->
type
==
SQL_COMMAND
)
if
(
commands
[
st
->
state
]
->
type
==
SQL_COMMAND
)
{
{
/*
* Read and discard the query result; note this is not included
* in the statement latency numbers.
*/
res
=
PQgetResult
(
st
->
con
);
res
=
PQgetResult
(
st
->
con
);
switch
(
PQresultStatus
(
res
))
switch
(
PQresultStatus
(
res
))
{
{
...
@@ -856,9 +885,14 @@ top:
...
@@ -856,9 +885,14 @@ top:
INSTR_TIME_ACCUM_DIFF
(
*
conn_time
,
end
,
start
);
INSTR_TIME_ACCUM_DIFF
(
*
conn_time
,
end
,
start
);
}
}
/* Record transaction start time if logging is enabled */
if
(
logfile
&&
st
->
state
==
0
)
if
(
logfile
&&
st
->
state
==
0
)
INSTR_TIME_SET_CURRENT
(
st
->
txn_begin
);
INSTR_TIME_SET_CURRENT
(
st
->
txn_begin
);
/* Record statement start time if per-command latencies are requested */
if
(
is_latencies
)
INSTR_TIME_SET_CURRENT
(
st
->
stmt_begin
);
if
(
commands
[
st
->
state
]
->
type
==
SQL_COMMAND
)
if
(
commands
[
st
->
state
]
->
type
==
SQL_COMMAND
)
{
{
const
Command
*
command
=
commands
[
st
->
state
];
const
Command
*
command
=
commands
[
st
->
state
];
...
@@ -1351,6 +1385,7 @@ parseQuery(Command *cmd, const char *raw_sql)
...
@@ -1351,6 +1385,7 @@ parseQuery(Command *cmd, const char *raw_sql)
return
true
;
return
true
;
}
}
/* Parse a command; return a Command struct, or NULL if it's a comment */
static
Command
*
static
Command
*
process_commands
(
char
*
buf
)
process_commands
(
char
*
buf
)
{
{
...
@@ -1361,24 +1396,28 @@ process_commands(char *buf)
...
@@ -1361,24 +1396,28 @@ process_commands(char *buf)
char
*
p
,
char
*
p
,
*
tok
;
*
tok
;
/* Make the string buf end at the next newline */
if
((
p
=
strchr
(
buf
,
'\n'
))
!=
NULL
)
if
((
p
=
strchr
(
buf
,
'\n'
))
!=
NULL
)
*
p
=
'\0'
;
*
p
=
'\0'
;
/* Skip leading whitespace */
p
=
buf
;
p
=
buf
;
while
(
isspace
((
unsigned
char
)
*
p
))
while
(
isspace
((
unsigned
char
)
*
p
))
p
++
;
p
++
;
/* If the line is empty or actually a comment, we're done */
if
(
*
p
==
'\0'
||
strncmp
(
p
,
"--"
,
2
)
==
0
)
if
(
*
p
==
'\0'
||
strncmp
(
p
,
"--"
,
2
)
==
0
)
{
return
NULL
;
return
NULL
;
}
/* Allocate and initialize Command structure */
my_commands
=
(
Command
*
)
malloc
(
sizeof
(
Command
));
my_commands
=
(
Command
*
)
malloc
(
sizeof
(
Command
));
if
(
my_commands
==
NULL
)
if
(
my_commands
==
NULL
)
{
return
NULL
;
return
NULL
;
}
my_commands
->
line
=
strdup
(
buf
);
if
(
my_commands
->
line
==
NULL
)
return
NULL
;
my_commands
->
command_num
=
num_commands
++
;
my_commands
->
type
=
0
;
/* until set */
my_commands
->
argc
=
0
;
my_commands
->
argc
=
0
;
if
(
*
p
==
'\\'
)
if
(
*
p
==
'\\'
)
...
@@ -1547,26 +1586,13 @@ process_file(char *filename)
...
@@ -1547,26 +1586,13 @@ process_file(char *filename)
while
(
fgets
(
buf
,
sizeof
(
buf
),
fd
)
!=
NULL
)
while
(
fgets
(
buf
,
sizeof
(
buf
),
fd
)
!=
NULL
)
{
{
Command
*
commands
;
Command
*
command
;
int
i
;
i
=
0
;
command
=
process_commands
(
buf
);
while
(
isspace
((
unsigned
char
)
buf
[
i
]))
if
(
command
==
NULL
)
i
++
;
if
(
buf
[
i
]
!=
'\0'
&&
strncmp
(
&
buf
[
i
],
"--"
,
2
)
!=
0
)
{
commands
=
process_commands
(
&
buf
[
i
]);
if
(
commands
==
NULL
)
{
fclose
(
fd
);
return
false
;
}
}
else
continue
;
continue
;
my_commands
[
lineno
]
=
command
s
;
my_commands
[
lineno
]
=
command
;
lineno
++
;
lineno
++
;
if
(
lineno
>=
alloc_num
)
if
(
lineno
>=
alloc_num
)
...
@@ -1612,7 +1638,7 @@ process_builtin(char *tb)
...
@@ -1612,7 +1638,7 @@ process_builtin(char *tb)
for
(;;)
for
(;;)
{
{
char
*
p
;
char
*
p
;
Command
*
command
s
;
Command
*
command
;
p
=
buf
;
p
=
buf
;
while
(
*
tb
&&
*
tb
!=
'\n'
)
while
(
*
tb
&&
*
tb
!=
'\n'
)
...
@@ -1626,13 +1652,11 @@ process_builtin(char *tb)
...
@@ -1626,13 +1652,11 @@ process_builtin(char *tb)
*
p
=
'\0'
;
*
p
=
'\0'
;
commands
=
process_commands
(
buf
);
command
=
process_commands
(
buf
);
if
(
commands
==
NULL
)
if
(
command
==
NULL
)
{
continue
;
return
NULL
;
}
my_commands
[
lineno
]
=
command
s
;
my_commands
[
lineno
]
=
command
;
lineno
++
;
lineno
++
;
if
(
lineno
>=
alloc_num
)
if
(
lineno
>=
alloc_num
)
...
@@ -1653,7 +1677,8 @@ process_builtin(char *tb)
...
@@ -1653,7 +1677,8 @@ process_builtin(char *tb)
/* print out results */
/* print out results */
static
void
static
void
printResults
(
int
ttype
,
int
normal_xacts
,
int
nclients
,
int
nthreads
,
printResults
(
int
ttype
,
int
normal_xacts
,
int
nclients
,
TState
*
threads
,
int
nthreads
,
instr_time
total_time
,
instr_time
conn_total_time
)
instr_time
total_time
,
instr_time
conn_total_time
)
{
{
double
time_include
,
double
time_include
,
...
@@ -1694,6 +1719,51 @@ printResults(int ttype, int normal_xacts, int nclients, int nthreads,
...
@@ -1694,6 +1719,51 @@ printResults(int ttype, int normal_xacts, int nclients, int nthreads,
}
}
printf
(
"tps = %f (including connections establishing)
\n
"
,
tps_include
);
printf
(
"tps = %f (including connections establishing)
\n
"
,
tps_include
);
printf
(
"tps = %f (excluding connections establishing)
\n
"
,
tps_exclude
);
printf
(
"tps = %f (excluding connections establishing)
\n
"
,
tps_exclude
);
/* Report per-command latencies */
if
(
is_latencies
)
{
int
i
;
for
(
i
=
0
;
i
<
num_files
;
i
++
)
{
Command
**
commands
;
if
(
num_files
>
1
)
printf
(
"statement latencies in milliseconds, file %d:
\n
"
,
i
+
1
);
else
printf
(
"statement latencies in milliseconds:
\n
"
);
for
(
commands
=
sql_files
[
i
];
*
commands
!=
NULL
;
commands
++
)
{
Command
*
command
=
*
commands
;
int
cnum
=
command
->
command_num
;
double
total_time
;
instr_time
total_exec_elapsed
;
int
total_exec_count
;
int
t
;
/* Accumulate per-thread data for command */
INSTR_TIME_SET_ZERO
(
total_exec_elapsed
);
total_exec_count
=
0
;
for
(
t
=
0
;
t
<
nthreads
;
t
++
)
{
TState
*
thread
=
&
threads
[
t
];
INSTR_TIME_ADD
(
total_exec_elapsed
,
thread
->
exec_elapsed
[
cnum
]);
total_exec_count
+=
thread
->
exec_count
[
cnum
];
}
if
(
total_exec_count
>
0
)
total_time
=
INSTR_TIME_GET_MILLISEC
(
total_exec_elapsed
)
/
(
double
)
total_exec_count
;
else
total_time
=
0
.
0
;
printf
(
"
\t
%f
\t
%s
\n
"
,
total_time
,
command
->
line
);
}
}
}
}
}
...
@@ -1770,7 +1840,7 @@ main(int argc, char **argv)
...
@@ -1770,7 +1840,7 @@ main(int argc, char **argv)
memset
(
state
,
0
,
sizeof
(
*
state
));
memset
(
state
,
0
,
sizeof
(
*
state
));
while
((
c
=
getopt
(
argc
,
argv
,
"ih:nvp:dSNc:
Cs:t:T:U:lf:D:F:M:j
:"
))
!=
-
1
)
while
((
c
=
getopt
(
argc
,
argv
,
"ih:nvp:dSNc:
j:Crs:t:T:U:lf:D:F:M
:"
))
!=
-
1
)
{
{
switch
(
c
)
switch
(
c
)
{
{
...
@@ -1834,6 +1904,9 @@ main(int argc, char **argv)
...
@@ -1834,6 +1904,9 @@ main(int argc, char **argv)
case
'C'
:
case
'C'
:
is_connect
=
true
;
is_connect
=
true
;
break
;
break
;
case
'r'
:
is_latencies
=
true
;
break
;
case
's'
:
case
's'
:
scale_given
=
true
;
scale_given
=
true
;
scale
=
atoi
(
optarg
);
scale
=
atoi
(
optarg
);
...
@@ -1954,6 +2027,22 @@ main(int argc, char **argv)
...
@@ -1954,6 +2027,22 @@ main(int argc, char **argv)
exit
(
1
);
exit
(
1
);
}
}
/*
* is_latencies only works with multiple threads in thread-based
* implementations, not fork-based ones, because it supposes that the
* parent can see changes made to the per-thread execution stats by child
* threads. It seems useful enough to accept despite this limitation,
* but perhaps we should FIXME someday (by passing the stats data back
* up through the parent-to-child pipes).
*/
#ifndef ENABLE_THREAD_SAFETY
if
(
is_latencies
&&
nthreads
>
1
)
{
fprintf
(
stderr
,
"-r does not work with -j larger than 1 on this platform.
\n
"
);
exit
(
1
);
}
#endif
/*
/*
* save main process id in the global variable because process id will be
* save main process id in the global variable because process id will be
* changed after fork.
* changed after fork.
...
@@ -2091,6 +2180,39 @@ main(int argc, char **argv)
...
@@ -2091,6 +2180,39 @@ main(int argc, char **argv)
break
;
break
;
}
}
/* set up thread data structures */
threads
=
(
TState
*
)
malloc
(
sizeof
(
TState
)
*
nthreads
);
for
(
i
=
0
;
i
<
nthreads
;
i
++
)
{
TState
*
thread
=
&
threads
[
i
];
thread
->
tid
=
i
;
thread
->
state
=
&
state
[
nclients
/
nthreads
*
i
];
thread
->
nstate
=
nclients
/
nthreads
;
if
(
is_latencies
)
{
/* Reserve memory for the thread to store per-command latencies */
int
t
;
thread
->
exec_elapsed
=
(
instr_time
*
)
malloc
(
sizeof
(
instr_time
)
*
num_commands
);
thread
->
exec_count
=
(
int
*
)
malloc
(
sizeof
(
int
)
*
num_commands
);
for
(
t
=
0
;
t
<
num_commands
;
t
++
)
{
INSTR_TIME_SET_ZERO
(
thread
->
exec_elapsed
[
t
]);
thread
->
exec_count
[
t
]
=
0
;
}
}
else
{
thread
->
exec_elapsed
=
NULL
;
thread
->
exec_count
=
NULL
;
}
}
/* get start up time */
/* get start up time */
INSTR_TIME_SET_CURRENT
(
start_time
);
INSTR_TIME_SET_CURRENT
(
start_time
);
...
@@ -2099,20 +2221,18 @@ main(int argc, char **argv)
...
@@ -2099,20 +2221,18 @@ main(int argc, char **argv)
setalarm
(
duration
);
setalarm
(
duration
);
/* start threads */
/* start threads */
threads
=
(
TState
*
)
malloc
(
sizeof
(
TState
)
*
nthreads
);
for
(
i
=
0
;
i
<
nthreads
;
i
++
)
for
(
i
=
0
;
i
<
nthreads
;
i
++
)
{
{
threads
[
i
].
tid
=
i
;
TState
*
thread
=
&
threads
[
i
];
threads
[
i
].
state
=
&
state
[
nclients
/
nthreads
*
i
];
threads
[
i
].
nstate
=
nclients
/
nthreads
;
INSTR_TIME_SET_CURRENT
(
thread
->
start_time
);
INSTR_TIME_SET_CURRENT
(
threads
[
i
].
start_time
);
/* the first thread (i = 0) is executed by main thread */
/* the first thread (i = 0) is executed by main thread */
if
(
i
>
0
)
if
(
i
>
0
)
{
{
int
err
=
pthread_create
(
&
thread
s
[
i
].
thread
,
NULL
,
threadRun
,
&
threads
[
i
]
);
int
err
=
pthread_create
(
&
thread
->
thread
,
NULL
,
threadRun
,
thread
);
if
(
err
!=
0
||
thread
s
[
i
].
thread
==
INVALID_THREAD
)
if
(
err
!=
0
||
thread
->
thread
==
INVALID_THREAD
)
{
{
fprintf
(
stderr
,
"cannot create thread: %s
\n
"
,
strerror
(
err
));
fprintf
(
stderr
,
"cannot create thread: %s
\n
"
,
strerror
(
err
));
exit
(
1
);
exit
(
1
);
...
@@ -2120,7 +2240,7 @@ main(int argc, char **argv)
...
@@ -2120,7 +2240,7 @@ main(int argc, char **argv)
}
}
else
else
{
{
thread
s
[
i
].
thread
=
INVALID_THREAD
;
thread
->
thread
=
INVALID_THREAD
;
}
}
}
}
...
@@ -2150,7 +2270,8 @@ main(int argc, char **argv)
...
@@ -2150,7 +2270,8 @@ main(int argc, char **argv)
/* get end time */
/* get end time */
INSTR_TIME_SET_CURRENT
(
total_time
);
INSTR_TIME_SET_CURRENT
(
total_time
);
INSTR_TIME_SUBTRACT
(
total_time
,
start_time
);
INSTR_TIME_SUBTRACT
(
total_time
,
start_time
);
printResults
(
ttype
,
total_xacts
,
nclients
,
nthreads
,
total_time
,
conn_total_time
);
printResults
(
ttype
,
total_xacts
,
nclients
,
threads
,
nthreads
,
total_time
,
conn_total_time
);
return
0
;
return
0
;
}
}
...
@@ -2211,7 +2332,7 @@ threadRun(void *arg)
...
@@ -2211,7 +2332,7 @@ threadRun(void *arg)
int
prev_ecnt
=
st
->
ecnt
;
int
prev_ecnt
=
st
->
ecnt
;
st
->
use_file
=
getrand
(
0
,
num_files
-
1
);
st
->
use_file
=
getrand
(
0
,
num_files
-
1
);
if
(
!
doCustom
(
st
,
&
result
->
conn_time
,
logfile
))
if
(
!
doCustom
(
thread
,
st
,
&
result
->
conn_time
,
logfile
))
remains
--
;
/* I've aborted */
remains
--
;
/* I've aborted */
if
(
st
->
ecnt
>
prev_ecnt
&&
commands
[
st
->
state
]
->
type
==
META_COMMAND
)
if
(
st
->
ecnt
>
prev_ecnt
&&
commands
[
st
->
state
]
->
type
==
META_COMMAND
)
...
@@ -2313,7 +2434,7 @@ threadRun(void *arg)
...
@@ -2313,7 +2434,7 @@ threadRun(void *arg)
if
(
st
->
con
&&
(
FD_ISSET
(
PQsocket
(
st
->
con
),
&
input_mask
)
if
(
st
->
con
&&
(
FD_ISSET
(
PQsocket
(
st
->
con
),
&
input_mask
)
||
commands
[
st
->
state
]
->
type
==
META_COMMAND
))
||
commands
[
st
->
state
]
->
type
==
META_COMMAND
))
{
{
if
(
!
doCustom
(
st
,
&
result
->
conn_time
,
logfile
))
if
(
!
doCustom
(
thread
,
st
,
&
result
->
conn_time
,
logfile
))
remains
--
;
/* I've aborted */
remains
--
;
/* I've aborted */
}
}
...
...
doc/src/sgml/pgbench.sgml
View file @
5a4e19ab
<!-- $PostgreSQL: pgsql/doc/src/sgml/pgbench.sgml,v 1.1
7 2010/07/29 19:34:40 petere
Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/pgbench.sgml,v 1.1
8 2010/08/12 20:39:39 tgl
Exp $ -->
<sect1 id="pgbench">
<sect1 id="pgbench">
<title>pgbench</title>
<title>pgbench</title>
...
@@ -38,7 +38,9 @@ tps = 85.296346 (excluding connections establishing)
...
@@ -38,7 +38,9 @@ tps = 85.296346 (excluding connections establishing)
settings. The next line reports the number of transactions completed
settings. The next line reports the number of transactions completed
and intended (the latter being just the product of number of clients
and intended (the latter being just the product of number of clients
and number of transactions per client); these will be equal unless the run
and number of transactions per client); these will be equal unless the run
failed before completion. The last two lines report the TPS rate,
failed before completion. (In <literal>-T</> mode, only the actual
number of transactions is printed.)
The last two lines report the TPS rate,
figured with and without counting the time to start database sessions.
figured with and without counting the time to start database sessions.
</para>
</para>
...
@@ -126,22 +128,22 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
...
@@ -126,22 +128,22 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
<variablelist>
<variablelist>
<varlistentry>
<varlistentry>
<term><option>-
F</option> <replaceable>fillfactor</
></term>
<term><option>-
i</option
></term>
<listitem>
<listitem>
<para>
<para>
Create the <structname>pgbench_accounts</>,
Required to invoke initialization mode.
<structname>pgbench_tellers</> and
<structname>pgbench_branches</> tables with the given fillfactor.
Default is 100.
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
<varlistentry>
<term><option>-
i</option
></term>
<term><option>-
F</option> <replaceable>fillfactor</
></term>
<listitem>
<listitem>
<para>
<para>
Required to invoke initialization mode.
Create the <structname>pgbench_accounts</>,
<structname>pgbench_tellers</> and
<structname>pgbench_branches</> tables with the given fillfactor.
Default is 100.
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
@@ -294,6 +296,17 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
...
@@ -294,6 +296,17 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
<term><option>-r</option></term>
<listitem>
<para>
Report the average per-statement latency (execution time from the
perspective of the client) of each command after the benchmark
finishes. See below for details.
</para>
</listitem>
</varlistentry>
<varlistentry>
<varlistentry>
<term><option>-s</option> <replaceable>scale_factor</></term>
<term><option>-s</option> <replaceable>scale_factor</></term>
<listitem>
<listitem>
...
@@ -618,7 +631,7 @@ END;
...
@@ -618,7 +631,7 @@ END;
<replaceable>nnn</> is the PID of the pgbench process.
<replaceable>nnn</> is the PID of the pgbench process.
If the <literal>-j</> option is 2 or higher, creating multiple worker
If the <literal>-j</> option is 2 or higher, creating multiple worker
threads, each will have its own log file. The first worker will use the
threads, each will have its own log file. The first worker will use the
same name for its log file as in the standard single worker case.
same name for its log file as in the standard single worker case.
The additional log files for the other workers will be named
The additional log files for the other workers will be named
<filename>pgbench_log.<replaceable>nnn</>.<replaceable>mmm</></filename>,
<filename>pgbench_log.<replaceable>nnn</>.<replaceable>mmm</></filename>,
where <replaceable>mmm</> is a sequential number for each worker starting
where <replaceable>mmm</> is a sequential number for each worker starting
...
@@ -632,7 +645,7 @@ END;
...
@@ -632,7 +645,7 @@ END;
<replaceable>client_id</> <replaceable>transaction_no</> <replaceable>time</> <replaceable>file_no</> <replaceable>time_epoch</> <replaceable>time_us</>
<replaceable>client_id</> <replaceable>transaction_no</> <replaceable>time</> <replaceable>file_no</> <replaceable>time_epoch</> <replaceable>time_us</>
</synopsis>
</synopsis>
where <replaceable>time</> is the elapsed transaction time in microseconds,
where <replaceable>time</> is the
total
elapsed transaction time in microseconds,
<replaceable>file_no</> identifies which script file was used
<replaceable>file_no</> identifies which script file was used
(useful when multiple scripts were specified with <literal>-f</>),
(useful when multiple scripts were specified with <literal>-f</>),
and <replaceable>time_epoch</>/<replaceable>time_us</> are a
and <replaceable>time_epoch</>/<replaceable>time_us</> are a
...
@@ -653,6 +666,62 @@ END;
...
@@ -653,6 +666,62 @@ END;
</para>
</para>
</sect2>
</sect2>
<sect2>
<title>Per-statement latencies</title>
<para>
With the <literal>-r</> option, <application>pgbench</> collects
the elapsed transaction time of each statement executed by every
client. It then reports an average of those values, referred to
as the latency for each statement, after the benchmark has finished.
</para>
<para>
For the default script, the output will look similar to this:
<screen>
starting vacuum...end.
transaction type: TPC-B (sort of)
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
tps = 618.764555 (including connections establishing)
tps = 622.977698 (excluding connections establishing)
statement latencies in milliseconds:
0.004386 \set nbranches 1 * :scale
0.001343 \set ntellers 10 * :scale
0.001212 \set naccounts 100000 * :scale
0.001310 \setrandom aid 1 :naccounts
0.001073 \setrandom bid 1 :nbranches
0.001005 \setrandom tid 1 :ntellers
0.001078 \setrandom delta -5000 5000
0.326152 BEGIN;
0.603376 UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
0.454643 SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
5.528491 UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
7.335435 UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
0.371851 INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
1.212976 END;
</screen>
</para>
<para>
If multiple script files are specified, the averages are reported
separately for each script file.
</para>
<para>
Note that collecting the additional timing information needed for
per-statement latency computation adds some overhead. This will slow
average execution speed and lower the computed TPS. The amount
of slowdown varies significantly depending on platform and hardware.
Comparing average TPS values with and without latency reporting enabled
is a good way to measure if the timing overhead is significant.
</para>
</sect2>
<sect2>
<sect2>
<title>Good Practices</title>
<title>Good Practices</title>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment