Commit 6b45e3b7 authored by Tom Lane's avatar Tom Lane

Arrange to generate different random sequences in the different child

processes of a pgbench run, when we are using -j > 1 and are emulating
threads via fork().  Otherwise the children all inherit the same random
sequence state and produce the same random-number sequence.

In the threaded case the different threads will share one RNG state, so
they will produce different subsets of one sequence, which is maybe more
correlated than a purist would like but will not be "the same".  So we
leave that case alone.

First noticed by Takahiro Itagaki, and is also part of the explanation
for the pgbench misbehavior recently reported by Jaime Casanova.
parent d8e511fa
...@@ -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.91 2009/09/10 13:59:57 ishii Exp $ * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.92 2009/12/11 21:50:06 tgl Exp $
* Copyright (c) 2000-2009, PostgreSQL Global Development Group * Copyright (c) 2000-2009, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED; * ALL RIGHTS RESERVED;
* *
...@@ -1916,7 +1916,7 @@ main(int argc, char **argv) ...@@ -1916,7 +1916,7 @@ main(int argc, char **argv)
INSTR_TIME_SET_CURRENT(start_time); INSTR_TIME_SET_CURRENT(start_time);
srandom((unsigned int) INSTR_TIME_GET_MICROSEC(start_time)); srandom((unsigned int) INSTR_TIME_GET_MICROSEC(start_time));
/* process bultin SQL scripts */ /* process builtin SQL scripts */
switch (ttype) switch (ttype)
{ {
case 0: case 0:
...@@ -2201,6 +2201,7 @@ pthread_create(pthread_t *thread, ...@@ -2201,6 +2201,7 @@ pthread_create(pthread_t *thread,
{ {
fork_pthread *th; fork_pthread *th;
void *ret; void *ret;
instr_time start_time;
th = (fork_pthread *) malloc(sizeof(fork_pthread)); th = (fork_pthread *) malloc(sizeof(fork_pthread));
pipe(th->pipes); pipe(th->pipes);
...@@ -2211,20 +2212,31 @@ pthread_create(pthread_t *thread, ...@@ -2211,20 +2212,31 @@ pthread_create(pthread_t *thread,
free(th); free(th);
return errno; return errno;
} }
if (th->pid != 0) /* parent process */ if (th->pid != 0) /* in parent process */
{ {
close(th->pipes[1]); close(th->pipes[1]);
*thread = th; *thread = th;
return 0; return 0;
} }
/* child process */ /* in child process */
close(th->pipes[0]); close(th->pipes[0]);
/* set alarm again because the child does not inherit timers */ /* set alarm again because the child does not inherit timers */
if (duration > 0) if (duration > 0)
setalarm(duration); setalarm(duration);
/*
* Set a different random seed in each child process. Otherwise they
* all inherit the parent's state and generate the same "random"
* sequence. (In the threaded case, the different threads will obtain
* subsets of the output of a single random() sequence, which should be
* okay for our purposes.)
*/
INSTR_TIME_SET_CURRENT(start_time);
srandom(((unsigned int) INSTR_TIME_GET_MICROSEC(start_time)) +
((unsigned int) getpid()));
ret = start_routine(arg); ret = start_routine(arg);
write(th->pipes[1], ret, sizeof(TResult)); write(th->pipes[1], ret, sizeof(TResult));
close(th->pipes[1]); close(th->pipes[1]);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment