akopytov / sysbench

Scriptable database and system performance benchmark
GNU General Public License v2.0
6.05k stars 1.08k forks source link

`--rand-seed` is non-deterministic #524

Open inikep opened 7 months ago

inikep commented 7 months ago

I created 16 tables with 1024 rows each.
I added print(string.format("tid=%d tnum=%d id=%d", sysbench.tid, tnum, id)) in oltp_delete.lua to check how random numbers are generated. Then I run sysbench oltp_delete.lua --events=8 --thread=1 --rand-seed=1111 --report-interval=10. The runs usually return:

tid=0 tnum=5 id=559
tid=0 tnum=11 id=422
tid=0 tnum=3 id=945
tid=0 tnum=7 id=825
tid=0 tnum=7 id=262
tid=0 tnum=16 id=670
tid=0 tnum=8 id=538
tid=0 tnum=5 id=414

But sometimes it returns:

tid=0 tnum=7 id=917
tid=0 tnum=12 id=49
tid=0 tnum=15 id=432
tid=0 tnum=6 id=248
tid=0 tnum=9 id=122
tid=0 tnum=16 id=678
tid=0 tnum=14 id=845
tid=0 tnum=7 id=603

The issue comes from the fact that sysbench uses random():

void sb_rand_thread_init(void)
{
  /* We use libc PRNG to seed xoroshiro128+ */
  sb_rng_state[0] = (((uint64_t) random()) << 32) |
    (((uint64_t) random()) & UINT32_MAX);
  sb_rng_state[1] = (((uint64_t) random()) << 32) |
    (((uint64_t) random()) & UINT32_MAX);
}

Even with a single client thread there is an additional report thread which also calls random(). But random is not multithreaded safe:

       The random() function should not be used in multithreaded
       programs where reproducible behavior is required.  Use
       random_r(3) for that purpose.