mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
Make pgbench use erand48() rather than random().
glibc renders random() thread-safe by wrapping a futex lock around it; testing reveals that this limits the performance of pgbench on machines with many CPU cores. Rather than switching to random_r(), which is only available on GNU systems and crashes unless you use undocumented alchemy to initialize the random state properly, switch to our built-in implementation of erand48(), which is both thread-safe and concurrent. Since the list of reasons not to use the operating system's erand48() is getting rather long, rename ours to pg_erand48() (and similarly for our implementations of lrand48() and srand48()) and just always use those. We were already doing this on Cygwin anyway, and the glibc implementation is not quite thread-safe, so pgbench wouldn't be able to use that either. Per discussion with Tom Lane.
This commit is contained in:
@ -36,5 +36,5 @@ geqo_rand(PlannerInfo *root)
|
||||
{
|
||||
GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private;
|
||||
|
||||
return erand48(private->random_state);
|
||||
return pg_erand48(private->random_state);
|
||||
}
|
||||
|
@ -64,9 +64,9 @@ geqo_selection(PlannerInfo *root, Chromosome *momma, Chromosome *daddy,
|
||||
* Ensure we have selected different genes, except if pool size is only
|
||||
* one, when we can't.
|
||||
*
|
||||
* This code has been observed to hang up in an infinite loop when the
|
||||
* platform's implementation of erand48() is broken. We consider that a
|
||||
* feature: it lets you know you'd better fix the random-number generator.
|
||||
* This code was observed to hang up in an infinite loop when the
|
||||
* platform's implementation of erand48() was broken. We now always
|
||||
* use our own version.
|
||||
*/
|
||||
if (pool->size > 1)
|
||||
{
|
||||
|
@ -73,7 +73,7 @@ extern double Geqo_seed; /* 0 .. 1 */
|
||||
typedef struct
|
||||
{
|
||||
List *initial_rels; /* the base relations we are joining */
|
||||
unsigned short random_state[3]; /* state for erand48() */
|
||||
unsigned short random_state[3]; /* state for pg_erand48() */
|
||||
} GeqoPrivateData;
|
||||
|
||||
|
||||
|
@ -149,9 +149,6 @@
|
||||
/* Define to 1 if you have the <editline/readline.h> header file. */
|
||||
#undef HAVE_EDITLINE_READLINE_H
|
||||
|
||||
/* Define to 1 if you have the `erand48' function. */
|
||||
#undef HAVE_ERAND48
|
||||
|
||||
/* Define to 1 if you have the `ERR_set_mark' function. */
|
||||
#undef HAVE_ERR_SET_MARK
|
||||
|
||||
|
@ -380,12 +380,9 @@ extern off_t ftello(FILE *stream);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ERAND48
|
||||
/* we assume all of these are present or missing together */
|
||||
extern double erand48(unsigned short xseed[3]);
|
||||
extern long lrand48(void);
|
||||
extern void srand48(long seed);
|
||||
#endif
|
||||
extern double pg_erand48(unsigned short xseed[3]);
|
||||
extern long pg_lrand48(void);
|
||||
extern void pg_srand48(long seed);
|
||||
|
||||
#ifndef HAVE_FSEEKO
|
||||
#define fseeko(a, b, c) fseek(a, b, c)
|
||||
|
@ -30,8 +30,8 @@ include $(top_builddir)/src/Makefile.global
|
||||
override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
|
||||
LIBS += $(PTHREAD_LIBS)
|
||||
|
||||
OBJS = $(LIBOBJS) chklocale.o dirmod.o exec.o inet_net_ntop.o noblock.o \
|
||||
path.o pgcheckdir.o pgmkdirp.o pgsleep.o pgstrcasecmp.o \
|
||||
OBJS = $(LIBOBJS) chklocale.o dirmod.o erand48.o exec.o inet_net_ntop.o \
|
||||
noblock.o path.o pgcheckdir.o pgmkdirp.o pgsleep.o pgstrcasecmp.o \
|
||||
qsort.o qsort_arg.o sprompt.o thread.o
|
||||
|
||||
# foo_srv.o and foo.o are both built from foo.c, but only foo.o has -DFRONTEND
|
||||
|
@ -2,10 +2,14 @@
|
||||
*
|
||||
* erand48.c
|
||||
*
|
||||
* This file supplies versions of erand48(), lrand48(), and srand48()
|
||||
* for machines that lack them. (These are all the members of the drand48
|
||||
* family that Postgres currently requires. We name the file after erand48
|
||||
* because that is the one that configure tests for.)
|
||||
* This file supplies pg_erand48(), pg_lrand48(), and pg_srand48(), which
|
||||
* are just like erand48(), lrand48(), and srand48() except that we use
|
||||
* our own implementation rather than the one provided by the operating
|
||||
* system. We used to test for an operating system version rather than
|
||||
* unconditionally using our own, but (1) some versions of Cygwin have a
|
||||
* buggy erand48() that always returns zero and (2) as of 2011, glibc's
|
||||
* erand48() is strangely coded to be almost-but-not-quite thread-safe,
|
||||
* which doesn't matter for the backend but is important for pgbench.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 1993 Martin Birgmeier
|
||||
@ -72,7 +76,7 @@ _dorand48(unsigned short xseed[3])
|
||||
|
||||
|
||||
double
|
||||
erand48(unsigned short xseed[3])
|
||||
pg_erand48(unsigned short xseed[3])
|
||||
{
|
||||
_dorand48(xseed);
|
||||
return ldexp((double) xseed[0], -48) +
|
||||
@ -81,14 +85,14 @@ erand48(unsigned short xseed[3])
|
||||
}
|
||||
|
||||
long
|
||||
lrand48(void)
|
||||
pg_lrand48(void)
|
||||
{
|
||||
_dorand48(_rand48_seed);
|
||||
return ((long) _rand48_seed[2] << 15) + ((long) _rand48_seed[1] >> 1);
|
||||
}
|
||||
|
||||
void
|
||||
srand48(long seed)
|
||||
pg_srand48(long seed)
|
||||
{
|
||||
_rand48_seed[0] = RAND48_SEED_0;
|
||||
_rand48_seed[1] = (unsigned short) seed;
|
||||
|
@ -21,5 +21,5 @@
|
||||
long
|
||||
random()
|
||||
{
|
||||
return lrand48();
|
||||
return pg_lrand48();
|
||||
}
|
||||
|
@ -21,5 +21,5 @@
|
||||
void
|
||||
srandom(unsigned int seed)
|
||||
{
|
||||
srand48((long int) seed);
|
||||
pg_srand48((long int) seed);
|
||||
}
|
||||
|
Reference in New Issue
Block a user