8000 Replace random(), pg_erand48(), etc with a better PRNG API and algori… · postgrespro/postgres@3804539 · GitHub
[go: up one dir, main page]

Skip to content

Commit 3804539

Browse files
committed
Replace random(), pg_erand48(), etc with a better PRNG API and algorithm.
Standardize on xoroshiro128** as our basic PRNG algorithm, eliminating a bunch of platform dependencies as well as fundamentally-obsolete PRNG code. In addition, this API replacement will ease replacing the algorithm again in future, should that become necessary. xoroshiro128** is a few percent slower than the drand48 family, but it can produce full-width 64-bit random values not only 48-bit, and it should be much more trustworthy. It's likely to be noticeably faster than the platform's random(), depending on which platform you are thinking about; and we can have non-global state vectors easily, unlike with random(). It is not cryptographically strong, but neither are the functions it replaces. Fabien Coelho, reviewed by Dean Rasheed, Aleksander Alekseev, and myself Discussion: https://postgr.es/m/alpine.DEB.2.22.394.2105241211230.165418@pseudo
1 parent f44ceb4 commit 3804539

File tree

50 files changed

+544
-481
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+544
-481
lines changed

configure

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16463,32 +16463,6 @@ esac
1646316463

1646416464
fi
1646516465

16466-
ac_fn_c_check_func "$LINENO" "random" "ac_cv_func_random"
16467-
if test "x$ac_cv_func_random" = xyes; then :
16468-
$as_echo "#define HAVE_RANDOM 1" >>confdefs.h
16469-
16470-
else
16471-
case " $LIBOBJS " in
16472-
*" random.$ac_objext "* ) ;;
16473-
*) LIBOBJS="$LIBOBJS random.$ac_objext"
16474-
;;
16475-
esac
16476-
16477-
fi
16478-
16479-
ac_fn_c_check_func "$LINENO" "srandom" "ac_cv_func_srandom"
16480-
if test "x$ac_cv_func_srandom" = xyes; then :
16481-
$as_echo "#define HAVE_SRANDOM 1" >>confdefs.h
16482-
16483-
else
16484-
case " $LIBOBJS " in
16485-
*" srandom.$ac_objext "* ) ;;
16486-
*) LIBOBJS="$LIBOBJS srandom.$ac_objext"
16487-
;;
16488-
esac
16489-
16490-
fi
16491-
1649216466
ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
1649316467
if test "x$ac_cv_func_strlcat" = xyes; then :
1649416468
$as_echo "#define HAVE_STRLCAT 1" >>confdefs.h

configure.ac

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,8 +1858,6 @@ AC_REPLACE_FUNCS(m4_normalize([
18581858
mkdtemp
18591859
pread
18601860
pwrite
1861-
random
1862-
srandom
18631861
strlcat
18641862
strlcpy
18651863
strnlen

contrib/amcheck/verify_nbtree.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "catalog/index.h"
3333
#include "catalog/pg_am.h"
3434
#include "commands/tablecmds.h"
35+
#include "common/pg_prng.h"
3536
#include "lib/bloomfilter.h"
3637
#include "miscadmin.h"
3738
#include "storage/lmgr.h"
@@ -466,8 +467,8 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace,
466467
total_pages = RelationGetNumberOfBlocks(rel);
467468
total_elems = Max(total_pages * (MaxTIDsPerBTreePage / 3),
468469
(int64) state->rel->rd_rel->reltuples);
469-
/* Random seed relies on backend srandom() call to avoid repetition */
470-
seed = random();
470+
/* Generate a random seed to avoid repetition */
471+
seed = pg_prng_uint64(&pg_global_prng_state);
471472
/* Create Bloom filter to fingerprint index */
472473
state->filter = bloom_create(total_elems, maintenance_work_mem, seed);
473474
state->heaptuplespresent = 0;

contrib/auto_explain/auto_explain.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "access/parallel.h"
1818
#include "commands/explain.h"
19+
#include "common/pg_prng.h"
1920
#include "executor/instrument.h"
2021
#include "jit/jit.h"
2122
#include "utils/guc.h"
@@ -275,8 +276,7 @@ explain_ExecutorStart(QueryDesc *queryDesc, int eflags)
275276
if (nesting_level == 0)
276277
{
277278
if (auto_explain_log_min_duration >= 0 && !IsParallelWorker())
278-
current_query_sampled = (random() < auto_explain_sample_rate *
279-
((double) MAX_RANDOM_VALUE + 1));
279+
current_query_sampled = (pg_prng_double(&pg_global_prng_state) < auto_explain_sample_rate);
280280
else
281281
current_query_sampled = false;
282282
}

contrib/file_fdw/file_fdw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ file_acquire_sample_rows(Relation onerel, int elevel,
11881188
* Found a suitable tuple, so save it, replacing one old tuple
11891189
* at random
11901190
*/
1191-
int k = (int) (targrows * sampler_random_fract(rstate.randstate));
1191+
int k = (int) (targrows * sampler_random_fract(&rstate.randstate));
11921192

11931193
Assert(k >= 0 && k < targrows);
11941194
heap_freetuple(rows[k]);

contrib/postgres_fdw/postgres_fdw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5158,7 +5158,7 @@ analyze_row_processor(PGresult *res, int row, PgFdwAnalyzeState *astate)
51585158
if (astate->rowstoskip <= 0)
51595159
{
51605160
/* Choose a random reservoir element to replace. */
5161-
pos = (int) (targrows * sampler_random_fract(astate->rstate.randstate));
5161+
pos = (int) (targrows * sampler_random_fract(&astate->rstate.randstate));
51625162
Assert(pos >= 0 && pos < targrows);
51635163
heap_freetuple(astate->rows[pos]);
51645164
}

contrib/tablefunc/tablefunc.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
#include "access/htup_details.h"
3838
#include "catalog/pg_type.h"
39+
#include "common/pg_prng.h"
3940
#include "executor/spi.h"
4041
#include "funcapi.h"
4142
#include "lib/stringinfo.h"
@@ -290,8 +291,8 @@ get_normal_pair(float8 *x1, float8 *x2)
290291

291292
do
292293
{
293-
u1 = (float8) random() / (float8) MAX_RANDOM_VALUE;
294-
u2 = (float8) random() / (float8) MAX_RANDOM_VALUE;
294+
u1 = pg_prng_double(&pg_global_prng_state);
295+
u2 = pg_prng_double(&pg_global_prng_state);
295296

296297
v1 = (2.0 * u1) - 1.0;
297298
v2 = (2.0 * u2) - 1.0;

contrib/tsm_system_rows/tsm_system_rows.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static BlockNumber system_rows_nextsampleblock(SampleScanState *node, BlockNumbe
6969
static OffsetNumber system_rows_nextsampletuple(SampleScanState *node,
7070
BlockNumber blockno,
7171
OffsetNumber maxoffset);
72-
static uint32 random_relative_prime(uint32 n, SamplerRandomState randstate);
72+
static uint32 random_relative_prime(uint32 n, pg_prng_state *randstate);
7373

7474

7575
/*
@@ -213,25 +213,25 @@ system_rows_nextsampleblock(SampleScanState *node, BlockNumber nblocks)
213213
if (sampler->step == 0)
214214
{
215215
/* Initialize now that we have scan descriptor */
216-
SamplerRandomState randstate;
216+
pg_prng_state randstate;
217217

218218
/* If relation is empty, there's nothing to scan */
219219
if (nblocks == 0)
220220
return InvalidBlockNumber;
221221

222222
/* We only need an RNG during this setup step */
223-
sampler_random_init_state(sampler->seed, randstate);
223+
sampler_random_init_state(sampler->seed, &randstate);
224224

225225
/* Compute nblocks/firstblock/step only once per query */
226226
sampler->nblocks = nblocks;
227227

228228
/* Choose random starting block within the relation */
229229
/* (Actually this is the predecessor of the first block visited) */
230-
sampler->firstblock = sampler_random_fract(randstate) *
230+
sampler->firstblock = sampler_random_fract(&randstate) *
231231
sampler->nblocks;
232232

233233
/* Find relative prime as step size for linear probing */
234-
sampler->step = random_relative_prime(sampler->nblocks, randstate);
234+
sampler->step = random_relative_prime(sampler->nblocks, &randstate);
235235
}
236236

237237
/* Reinitialize lb */
@@ -317,7 +317,7 @@ gcd(uint32 a, uint32 b)
317317
* (else return 1).
318318
*/
319319
static uint32
320-
random_relative_prime(uint32 n, SamplerRandomState randstate)
320+
random_relative_prime(uint32 n, pg_prng_state *randstate)
321321
{
322322
uint32 r;
323323

contrib/tsm_system_time/tsm_system_time.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static BlockNumber system_time_nextsampleblock(SampleScanState *node, BlockNumbe
6969
static OffsetNumber system_time_nextsampletuple(SampleScanState *node,
7070
BlockNumber blockno,
7171
OffsetNumber maxoffset);
72-
static uint32 random_relative_prime(uint32 n, SamplerRandomState randstate);
72+
static uint32 random_relative_prime(uint32 n, pg_prng_state *randstate);
7373

7474

7575
/*
@@ -224,25 +224,25 @@ system_time_nextsampleblock(SampleScanState *node, BlockNumber nblocks)
224224
if (sampler->step == 0)
225225
{
226226
/* Initialize now that we have scan descriptor */
227-
SamplerRandomState randstate;
227+
pg_prng_state randstate;
228228

229229
/* If relation is empty, there's nothing to scan */
230230
if (nblocks == 0)
231231
return InvalidBlockNumber;
232232

233233
/* We only need an RNG during this setup step */
234-
sampler_random_init_state(sampler->seed, randstate);
234+
sampler_random_init_state(sampler->seed, &randstate);
235235

236236
/* Compute nblocks/firstblock/step only once per query */
237237
sampler->nblocks = nblocks;
238238

239239
/* Choose random starting block within the relation */
240240
/* (Actually this is the predecessor of the first block visited) */
241-
sampler->firstblock = sampler_random_fract(randstate) *
241+
sampler->firstblock = sampler_random_fract(&randstate) *
242242
sampler->nblocks;
243243

244244
/* Find relative prime as step size for linear probing */
245-
sampler->step = random_relative_prime(sampler->nblocks, randstate);
245+
sampler->step = random_relative_prime(sampler->nblocks, &randstate);
246246
}
247247

248248
/* Reinitialize lb and start_time */
@@ -330,7 +330,7 @@ gcd(uint32 a, uint32 b)
330330
* (else return 1).
331331
*/
332332
static uint32
333-
random_relative_prime(uint32 n, SamplerRandomState randstate)
333+
random_relative_prime(uint32 n, pg_prng_state *randstate)
334334
{
335335
uint32 r;
336336

src/backend/access/gin/ginget.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "access/gin_private.h"
1818
#include "access/relscan.h"
19+
#include "common/pg_prng.h"
1920
#include "miscadmin.h"
2021
#include "storage/predicate.h"
2122
#include "utils/datum.h"
@@ -787,7 +788,7 @@ entryLoadMoreItems(GinState *ginstate, GinScanEntry entry,
787788
}
788789
}
789790

790-
#define gin_rand() (((double) random()) / ((double) MAX_RANDOM_VALUE))
791+
#define gin_rand() pg_prng_double(&pg_global_prng_state)
791792
#define dropItem(e) ( gin_rand() > ((double)GinFuzzySearchLimit)/((double)((e)->predictNumberResult)) )
792793

793794
/*

0 commit comments

Comments
 (0)
0