/ Check-in [4144dffb]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Refactor the sqlite3_randomness() implementation for improved performance.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4144dffb57b5ed791d7a6d2f26fab5e7dc77fbd1
User & Date: drh 2013-08-21 22:09:25
Context
2013-08-21
22:54
Minor performance tweaks to the pager. check-in: 9ae1f9ce user: drh tags: trunk
22:09
Refactor the sqlite3_randomness() implementation for improved performance. check-in: 4144dffb user: drh tags: trunk
21:12
Simplification to the StrAccum object and the sqlite3StrAccumAppend() method that also results in slightly better performance. check-in: 700dbbea user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/random.c.

    24     24   static SQLITE_WSD struct sqlite3PrngType {
    25     25     unsigned char isInit;          /* True if initialized */
    26     26     unsigned char i, j;            /* State variables */
    27     27     unsigned char s[256];          /* State variables */
    28     28   } sqlite3Prng;
    29     29   
    30     30   /*
    31         -** Get a single 8-bit random value from the RC4 PRNG.  The Mutex
    32         -** must be held while executing this routine.
    33         -**
    34         -** Why not just use a library random generator like lrand48() for this?
    35         -** Because the OP_NewRowid opcode in the VDBE depends on having a very
    36         -** good source of random numbers.  The lrand48() library function may
    37         -** well be good enough.  But maybe not.  Or maybe lrand48() has some
    38         -** subtle problems on some systems that could cause problems.  It is hard
    39         -** to know.  To minimize the risk of problems due to bad lrand48()
    40         -** implementations, SQLite uses this random number generator based
    41         -** on RC4, which we know works very well.
    42         -**
    43         -** (Later):  Actually, OP_NewRowid does not depend on a good source of
    44         -** randomness any more.  But we will leave this code in all the same.
           31  +** Return N random bytes.
    45     32   */
    46         -static u8 randomByte(void){
           33  +void sqlite3_randomness(int N, void *pBuf){
    47     34     unsigned char t;
    48         -
           35  +  unsigned char *zBuf = pBuf;
    49     36   
    50     37     /* The "wsdPrng" macro will resolve to the pseudo-random number generator
    51     38     ** state vector.  If writable static data is unsupported on the target,
    52     39     ** we have to locate the state vector at run-time.  In the more common
    53     40     ** case where writable static data is supported, wsdPrng can refer directly
    54     41     ** to the "sqlite3Prng" state vector declared above.
    55     42     */
................................................................................
    56     43   #ifdef SQLITE_OMIT_WSD
    57     44     struct sqlite3PrngType *p = &GLOBAL(struct sqlite3PrngType, sqlite3Prng);
    58     45   # define wsdPrng p[0]
    59     46   #else
    60     47   # define wsdPrng sqlite3Prng
    61     48   #endif
    62     49   
           50  +#if SQLITE_THREADSAFE
           51  +  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
           52  +  sqlite3_mutex_enter(mutex);
           53  +#endif
    63     54   
    64     55     /* Initialize the state of the random number generator once,
    65     56     ** the first time this routine is called.  The seed value does
    66     57     ** not need to contain a lot of randomness since we are not
    67     58     ** trying to do secure encryption or anything like that...
    68     59     **
    69     60     ** Nothing in this file or anywhere else in SQLite does any kind of
................................................................................
    84     75         t = wsdPrng.s[wsdPrng.j];
    85     76         wsdPrng.s[wsdPrng.j] = wsdPrng.s[i];
    86     77         wsdPrng.s[i] = t;
    87     78       }
    88     79       wsdPrng.isInit = 1;
    89     80     }
    90     81   
    91         -  /* Generate and return single random byte
    92         -  */
    93         -  wsdPrng.i++;
    94         -  t = wsdPrng.s[wsdPrng.i];
    95         -  wsdPrng.j += t;
    96         -  wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
    97         -  wsdPrng.s[wsdPrng.j] = t;
    98         -  t += wsdPrng.s[wsdPrng.i];
    99         -  return wsdPrng.s[t];
   100         -}
   101         -
   102         -/*
   103         -** Return N random bytes.
   104         -*/
   105         -void sqlite3_randomness(int N, void *pBuf){
   106         -  unsigned char *zBuf = pBuf;
   107         -#if SQLITE_THREADSAFE
   108         -  sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_PRNG);
   109         -#endif
   110         -  sqlite3_mutex_enter(mutex);
   111     82     while( N-- ){
   112         -    *(zBuf++) = randomByte();
           83  +    wsdPrng.i++;
           84  +    t = wsdPrng.s[wsdPrng.i];
           85  +    wsdPrng.j += t;
           86  +    wsdPrng.s[wsdPrng.i] = wsdPrng.s[wsdPrng.j];
           87  +    wsdPrng.s[wsdPrng.j] = t;
           88  +    t += wsdPrng.s[wsdPrng.i];
           89  +    *(zBuf++) = wsdPrng.s[t];
   113     90     }
   114     91     sqlite3_mutex_leave(mutex);
   115     92   }
   116     93   
   117     94   #ifndef SQLITE_OMIT_BUILTIN_TEST
   118     95   /*
   119     96   ** For testing purposes, we sometimes want to preserve the state of