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

Commit64f8589

Browse files
committed
Set random seed for pgbench.
Setting random could increase reproducibility of test in some cases. Patchsuggests three providers for seed: time (default), strong randomgenerator (if available) and unsigned constant. Seed could be set fromcommand line or enviroment variable.Author: Fabien CoelhoReviewed by: Chapman FlackDiscussion:https://www.postgresql.org/message-id/flat/20160407082711.q7iq3ykffqxcszkv@alap3.anarazel.de
1 parent530bcf7 commit64f8589

File tree

4 files changed

+170
-12
lines changed

4 files changed

+170
-12
lines changed

‎doc/src/sgml/ref/pgbench.sgml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,43 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
679679
</listitem>
680680
</varlistentry>
681681

682+
<varlistentry>
683+
<term><option>--random-seed=</option><replaceable>SEED</replaceable></term>
684+
<listitem>
685+
<para>
686+
Set random generator seed. Seeds the system random number generator,
687+
which then produces a sequence of initial generator states, one for
688+
each thread.
689+
Values for <replaceable>SEED</replaceable> may be:
690+
<literal>time</literal> (the default, the seed is based on the current time),
691+
<literal>rand</literal> (use a strong random source, failing if none
692+
is available), or an unsigned decimal integer value.
693+
The random generator is invoked explicitly from a pgbench script
694+
(<literal>random...</literal> functions) or implicitly (for instance option
695+
<option>--rate</option> uses it to schedule transactions).
696+
When explicitly set, the value used for seeding is shown on the terminal.
697+
Any value allowed for <replaceable>SEED</replaceable> may also be
698+
provided through the environment variable
699+
<literal>PGBENCH_RANDOM_SEED</literal>.
700+
To ensure that the provided seed impacts all possible uses, put this option
701+
first or use the environment variable.
702+
</para>
703+
<para>
704+
Setting the seed explicitly allows to reproduce a <command>pgbench</command>
705+
run exactly, as far as random numbers are concerned.
706+
As the random state is managed per thread, this means the exact same
707+
<command>pgbench</command> run for an identical invocation if there is one
708+
client per thread and there are no external or data dependencies.
709+
From a statistical viewpoint reproducing runs exactly is a bad idea because
710+
it can hide the performance variability or improve performance unduly,
711+
e.g. by hitting the same pages as a previous run.
712+
However, it may also be of great help for debugging, for instance
713+
re-running a tricky case which leads to an error.
714+
Use wisely.
715+
</para>
716+
</listitem>
717+
</varlistentry>
718+
682719
<varlistentry>
683720
<term><option>--sampling-rate=<replaceable>rate</replaceable></option></term>
684721
<listitem>
@@ -883,6 +920,11 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
883920
<entry>seed used in hash functions by default</entry>
884921
</row>
885922

923+
<row>
924+
<entry> <literal>random_seed</literal> </entry>
925+
<entry>random generator seed (unless overwritten with <option>-D</option>)</entry>
926+
</row>
927+
886928
<row>
887929
<entry> <literal>scale</literal> </entry>
888930
<entry>current scale factor</entry>

‎src/bin/pgbench/pgbench.c

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ int64latency_limit = 0;
155155
char*tablespace=NULL;
156156
char*index_tablespace=NULL;
157157

158+
/* random seed used when calling srandom() */
159+
int64random_seed=-1;
160+
158161
/*
159162
* end of configurable parameters
160163
*********************************************************************/
@@ -579,6 +582,7 @@ usage(void)
579582
" --log-prefix=PREFIX prefix for transaction time log file\n"
580583
" (default: \"pgbench_log\")\n"
581584
" --progress-timestamp use Unix epoch timestamps for progress\n"
585+
" --random-seed=SEED set random seed (\"time\", \"rand\", integer)\n"
582586
" --sampling-rate=NUM fraction of transactions to log (e.g., 0.01 for 1%%)\n"
583587
"\nCommon options:\n"
584588
" -d, --debug print debugging output\n"
@@ -4664,6 +4668,49 @@ printResults(TState *threads, StatsData *total, instr_time total_time,
46644668
}
46654669
}
46664670

4671+
/* call srandom based on some seed. NULL triggers the default behavior. */
4672+
staticvoid
4673+
set_random_seed(constchar*seed,constchar*origin)
4674+
{
4675+
/* srandom expects an unsigned int */
4676+
unsignedintiseed;
4677+
4678+
if (seed==NULL||strcmp(seed,"time")==0)
4679+
{
4680+
/* rely on current time */
4681+
instr_timenow;
4682+
INSTR_TIME_SET_CURRENT(now);
4683+
iseed= (unsignedint)INSTR_TIME_GET_MICROSEC(now);
4684+
}
4685+
elseif (strcmp(seed,"rand")==0)
4686+
{
4687+
/* use some "strong" random source */
4688+
if (!pg_strong_random(&iseed,sizeof(iseed)))
4689+
{
4690+
fprintf(stderr,"cannot seed random from a strong source\n");
4691+
exit(1);
4692+
}
4693+
}
4694+
else
4695+
{
4696+
/* parse seed unsigned int value */
4697+
chargarbage;
4698+
if (sscanf(seed,"%u%c",&iseed,&garbage)!=1)
4699+
{
4700+
fprintf(stderr,
4701+
"error while scanning '%s' from %s, expecting an unsigned integer, 'time' or 'rand'\n",
4702+
seed,origin);
4703+
exit(1);
4704+
}
4705+
}
4706+
4707+
if (seed!=NULL)
4708+
fprintf(stderr,"setting random seed to %u\n",iseed);
4709+
srandom(iseed);
4710+
/* no precision loss: 32 bit unsigned int cast to 64 bit int */
4711+
random_seed=iseed;
4712+
}
4713+
46674714

46684715
int
46694716
main(intargc,char**argv)
@@ -4706,6 +4753,7 @@ main(int argc, char **argv)
47064753
{"progress-timestamp",no_argument,NULL,6},
47074754
{"log-prefix",required_argument,NULL,7},
47084755
{"foreign-keys",no_argument,NULL,8},
4756+
{"random-seed",required_argument,NULL,9},
47094757
{NULL,0,NULL,0}
47104758
};
47114759

@@ -4774,6 +4822,9 @@ main(int argc, char **argv)
47744822
state= (CState*)pg_malloc(sizeof(CState));
47754823
memset(state,0,sizeof(CState));
47764824

4825+
/* set random seed early, because it may be used while parsing scripts. */
4826+
set_random_seed(getenv("PGBENCH_RANDOM_SEED"),"PGBENCH_RANDOM_SEED environment variable");
4827+
47774828
while ((c=getopt_long(argc,argv,"iI:h:nvp:dqb:SNc:j:Crs:t:T:U:lf:D:F:M:P:R:L:",long_options,&optindex))!=-1)
47784829
{
47794830
char*script;
@@ -5046,6 +5097,10 @@ main(int argc, char **argv)
50465097
initialization_option_set= true;
50475098
foreign_keys= true;
50485099
break;
5100+
case9:/* random-seed */
5101+
benchmarking_option_set= true;
5102+
set_random_seed(optarg,"--random-seed option");
5103+
break;
50495104
default:
50505105
fprintf(stderr,_("Try \"%s --help\" for more information.\n"),progname);
50515106
exit(1);
@@ -5280,10 +5335,6 @@ main(int argc, char **argv)
52805335
exit(1);
52815336
}
52825337

5283-
/* set random seed */
5284-
INSTR_TIME_SET_CURRENT(start_time);
5285-
srandom((unsignedint)INSTR_TIME_GET_MICROSEC(start_time));
5286-
52875338
if (internal_script_used)
52885339
{
52895340
/*
@@ -5339,10 +5390,8 @@ main(int argc, char **argv)
53395390
if (lookupVariable(&state[0],"client_id")==NULL)
53405391
{
53415392
for (i=0;i<nclients;i++)
5342-
{
53435393
if (!putVariableInt(&state[i],"startup","client_id",i))
53445394
exit(1);
5345-
}
53465395
}
53475396

53485397
/* set default seed for hash functions */
@@ -5358,6 +5407,14 @@ main(int argc, char **argv)
53585407
exit(1);
53595408
}
53605409

5410+
/* set random seed unless overwritten */
5411+
if (lookupVariable(&state[0],"random_seed")==NULL)
5412+
{
5413+
for (i=0;i<nclients;i++)
5414+
if (!putVariableInt(&state[i],"startup","random_seed",random_seed))
5415+
exit(1);
5416+
}
5417+
53615418
if (!is_no_vacuum)
53625419
{
53635420
fprintf(stderr,"starting vacuum...");

‎src/bin/pgbench/t/001_pgbench_with_server.pl

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ sub pgbench
2929
$filename =~s/\@\d+$//;
3030

3131
#push @filenames, $filename;
32+
# filenames are expected to be unique on a test
33+
if (-e$filename)
34+
{
35+
ok(0,"$filename must not already exists");
36+
unlink$filenameordie"cannot unlink$filename:$!";
37+
}
3238
append_to_file($filename,$$files{$fn});
3339
}
3440
}
@@ -210,14 +216,18 @@ sub pgbench
210216
} });
211217

212218
# test expressions
219+
# command 1..3 and 23 depend on random seed which is used to call srandom.
213220
pgbench(
214-
'-t 1 -Dfoo=-10.1 -Dbla=false -Di=+3 -Dminint=-9223372036854775808 -Dn=null -Dt=t -Df=of -Dd=1.0',
221+
'--random-seed=5432 -t 1 -Dfoo=-10.1 -Dbla=false -Di=+3 -Dminint=-9223372036854775808 -Dn=null -Dt=t -Df=of -Dd=1.0',
215222
0,
216223
[qr{type: .*/001_pgbench_expressions},qr{processed: 1/1} ],
217-
[qr{command=1.: int 1\d\b},
218-
qr{command=2.: int 1\d\d\b},
219-
qr{command=3.: int 1\d\d\d\b},
220-
qr{command=4.: int 4\b},
224+
[qr{setting random seed to 5432\b},
225+
# After explicit seeding, the four * random checks (1-3,20) should be
226+
# deterministic, but not necessarily portable.
227+
qr{command=1.: int 1\d\b},# uniform random: 12 on linux
228+
qr{command=2.: int 1\d\d\b},# exponential random: 106 on linux
229+
qr{command=3.: int 1\d\d\d\b},# gaussian random: 1462 on linux
230+
qr{command=4.: int 4\b},
221231
qr{command=5.: int 5\b},
222232
qr{command=6.: int 6\b},
223233
qr{command=7.: int 7\b},
@@ -230,7 +240,7 @@ sub pgbench
230240
qr{command=16.: double 16\b},
231241
qr{command=17.: double 17\b},
232242
qr{command=18.: int 9223372036854775807\b},
233-
qr{command=20.: int[1-9]\b},
243+
qr{command=20.: int\d\b},# zipfian random: 1 on linux
234244
qr{command=21.: double -27\b},
235245
qr{command=22.: double 1024\b},
236246
qr{command=23.: double 1\b},
@@ -270,6 +280,9 @@ sub pgbench
270280
qr{command=86.: int 86\b},
271281
qr{command=93.: int 93\b},
272282
qr{command=95.: int 0\b},
283+
qr{command=96.: int 1\b},# :scale
284+
qr{command=97.: int 0\b},# :client_id
285+
qr{command=98.: int 5432\b},# :random_seed
273286
],
274287
'pgbench expressions',
275288
{'001_pgbench_expressions'=>q{-- integer functions
@@ -390,8 +403,52 @@ sub pgbench
390403
\endif
391404
-- must be zero if false branches where skipped
392405
\set nope debug(:nope)
406+
-- check automatic variables
407+
\set sc debug(:scale)
408+
\set ci debug(:client_id)
409+
\set rs debug(:random_seed)
393410
} });
394411

412+
# random determinism when seeded
413+
$node->safe_psql('postgres',
414+
'CREATE UNLOGGED TABLE seeded_random(seed INT8 NOT NULL, rand TEXT NOT NULL, val INTEGER NOT NULL);');
415+
416+
# same value to check for determinism
417+
my$seed =int(rand(1000000000));
418+
formy$i (1, 2)
419+
{
420+
pgbench("--random-seed=$seed -t 1",
421+
0,
422+
[qr{processed: 1/1}],
423+
[qr{setting random seed to$seed\b}],
424+
"random seeded with$seed",
425+
{"001_pgbench_random_seed_$i"=>q{-- test random functions
426+
\set ur random(1000, 1999)
427+
\set er random_exponential(2000, 2999, 2.0)
428+
\set gr random_gaussian(3000, 3999, 3.0)
429+
\set zr random_zipfian(4000, 4999, 2.5)
430+
INSERT INTO seeded_random(seed, rand, val) VALUES
431+
(:random_seed, 'uniform', :ur),
432+
(:random_seed, 'exponential', :er),
433+
(:random_seed, 'gaussian', :gr),
434+
(:random_seed, 'zipfian', :zr);
435+
} });
436+
}
437+
438+
# check that all runs generated the same 4 values
439+
my ($ret,$out,$err) =
440+
$node->psql('postgres',
441+
'SELECT seed, rand, val, COUNT(*) FROM seeded_random GROUP BY seed, rand, val');
442+
443+
ok($ret == 0,"psql seeded_random count ok");
444+
ok($erreq'',"psql seeded_random count stderr is empty");
445+
ok($out =~/\b$seed\|uniform\|1\d\d\d\|2/,"psql seeded_random count uniform");
446+
ok($out =~/\b$seed\|exponential\|2\d\d\d\|2/,"psql seeded_random count exponential");
447+
ok($out =~/\b$seed\|gaussian\|3\d\d\d\|2/,"psql seeded_random count gaussian");
448+
ok($out =~/\b$seed\|zipfian\|4\d\d\d\|2/,"psql seeded_random count zipfian");
449+
450+
$node->safe_psql('postgres','DROP TABLE seeded_random;');
451+
395452
# backslash commands
396453
pgbench(
397454
'-t 1', 0,

‎src/bin/pgbench/t/002_pgbench_no_server.pl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ sub pgbench_scripts
110110
['invalid init step','-i -I dta',
111111
[qr{unrecognized initialization step},
112112
qr{allowed steps are} ] ],
113+
['bad random seed','--random-seed=one',
114+
[qr{error while scanning 'one' from --random-seed option, expecting an unsigned integer} ] ],
113115

114116
# loging sub-options
115117
['sampling => log','--sampling-rate=0.01',

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp