Repository: petermattis/pebble
Pull request #93 (2019-04-27 17:32:44)

Use golang.org/x/exp/rand instead of math/rand
* Remove the one usage of pkg/errors

petermattis: 

<!-- Reviewable:start -->
This change is [<img src="https://reviewable.io/review_button.png" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/petermattis/pebble/93)
<!-- Reviewable:end -->

petermattis: Note that most of the uses of `math/rand` were find. I just changed them all for consistency. The two places the change is significant is in `internal/arenaskl` and `internal/batchskl` which generate a random number in order to generate a random height during insertions.

Patch:
diff --git a/cmd/pebble/scan.go b/cmd/pebble/scan.go
index 665d8a1..7d80675 100644
--- a/cmd/pebble/scan.go
+++ b/cmd/pebble/scan.go
@@ -8,7 +8,6 @@ import (
 	"fmt"
 	"log"
 	"math"
-	"math/rand"
 	"sync"
 	"sync/atomic"
 	"time"
@@ -16,6 +15,7 @@ import (
 	"github.com/petermattis/pebble"
 	"github.com/petermattis/pebble/db"
 	"github.com/spf13/cobra"
+	"golang.org/x/exp/rand"
 )
 
 var (
@@ -77,7 +77,7 @@ func runScan(cmd *cobra.Command, args []string) {
 				go func(i int) {
 					defer wg.Done()
 
-					rng := rand.New(rand.NewSource(int64(i)))
+					rng := rand.New(rand.NewSource(uint64(i)))
 					startKeyBuf := append(make([]byte, 0, 64), []byte("key-")...)
 					endKeyBuf := append(make([]byte, 0, 64), []byte("key-")...)
 					minTS := encodeUint64Ascending(nil, math.MaxUint64)
diff --git a/cmd/pebble/sync.go b/cmd/pebble/sync.go
index be6e992..593ff85 100644
--- a/cmd/pebble/sync.go
+++ b/cmd/pebble/sync.go
@@ -5,15 +5,16 @@
 package main
 
 import (
+	"encoding/binary"
 	"fmt"
 	"log"
-	"math/rand"
 	"sync"
 	"time"
 
 	"github.com/petermattis/pebble"
 	"github.com/petermattis/pebble/db"
 	"github.com/spf13/cobra"
+	"golang.org/x/exp/rand"
 )
 
 var syncCmd = &cobra.Command{
@@ -35,14 +36,21 @@ func runSync(cmd *cobra.Command, args []string) {
 				go func() {
 					defer wg.Done()
 
-					rand := rand.New(rand.NewSource(time.Now().UnixNano()))
+					rand := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 					var raw []byte
 					var buf []byte
 
 					randBlock := func(min, max int) []byte {
 						data := make([]byte, rand.Intn(max-min)+min)
-						for i := range data {
-							data[i] = byte(rand.Int() & 0xff)
+						tmp := data
+						for len(tmp) >= 8 {
+							binary.LittleEndian.PutUint64(tmp, rand.Uint64())
+							tmp = tmp[8:]
+						}
+						r := rand.Uint64()
+						for i := 0; i < len(tmp); i++ {
+							tmp[i] = byte(r)
+							r >>= 8
 						}
 						return data
 					}
diff --git a/go.mod b/go.mod
index 451c6c4..0e59345 100644
--- a/go.mod
+++ b/go.mod
@@ -6,9 +6,9 @@ require (
 	github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db
 	github.com/inconshreveable/mousetrap v1.0.0 // indirect
 	github.com/kr/pretty v0.1.0
-	github.com/pkg/errors v0.8.1
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/spf13/cobra v0.0.3
 	github.com/spf13/pflag v1.0.3 // indirect
 	github.com/stretchr/testify v1.2.2
+	golang.org/x/exp v0.0.0-20190426190305-956cc1757749
 )
diff --git a/go.sum b/go.sum
index aed8564..f91daa2 100644
--- a/go.sum
+++ b/go.sum
@@ -1,3 +1,4 @@
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
 github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -11,8 +12,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
@@ -21,3 +20,13 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/exp v0.0.0-20190426190305-956cc1757749 h1:Bduxdpx1O6126WsH6F6NwKywZ/FPncphlTduoPxFG78=
+golang.org/x/exp v0.0.0-20190426190305-956cc1757749/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
diff --git a/internal/arenaskl/skl.go b/internal/arenaskl/skl.go
index 81aa775..c783548 100644
--- a/internal/arenaskl/skl.go
+++ b/internal/arenaskl/skl.go
@@ -47,7 +47,6 @@ import (
 	"encoding/binary"
 	"errors"
 	"math"
-	"math/rand"
 	"runtime"
 	"sync"
 	"sync/atomic"
@@ -55,6 +54,7 @@ import (
 	"unsafe"
 
 	"github.com/petermattis/pebble/db"
+	"golang.org/x/exp/rand"
 )
 
 const (
@@ -86,7 +86,7 @@ type Skiplist struct {
 
 	rand struct {
 		sync.Mutex
-		src rand.Source64
+		src rand.PCGSource
 	}
 
 	// If set to true by tests, then extra delays are added to make it easier to
@@ -158,7 +158,7 @@ func (s *Skiplist) Reset(arena *Arena, cmp db.Compare) {
 		tail:   tail,
 		height: 1,
 	}
-	s.rand.src = rand.NewSource(time.Now().UnixNano()).(rand.Source64)
+	s.rand.src.Seed(uint64(time.Now().UnixNano()))
 }
 
 // Height returns the height of the highest tower within any of the nodes that
diff --git a/internal/batchskl/skl.go b/internal/batchskl/skl.go
index 6b66dfc..5c6e6cf 100644
--- a/internal/batchskl/skl.go
+++ b/internal/batchskl/skl.go
@@ -58,10 +58,11 @@ import (
 	"errors"
 	"fmt"
 	"math"
-	"math/rand"
+	"time"
 	"unsafe"
 
 	"github.com/petermattis/pebble/db"
+	"golang.org/x/exp/rand"
 )
 
 const (
@@ -123,6 +124,7 @@ type Skiplist struct {
 	head    uint32
 	tail    uint32
 	height  uint32 // Current height: 1 <= height <= maxHeight
+	rand    rand.PCGSource
 }
 
 var (
@@ -152,6 +154,7 @@ func NewSkiplist(storage Storage, initBufSize int) *Skiplist {
 		nodes:   make([]byte, 0, initBufSize),
 		height:  1,
 	}
+	s.rand.Seed(uint64(time.Now().UnixNano()))
 
 	// Allocate head and tail nodes.
 	s.head = s.newNode(maxHeight, 0, 0)
@@ -268,7 +271,7 @@ func (s *Skiplist) node(offset uint32) *node {
 }
 
 func (s *Skiplist) randomHeight() uint32 {
-	rnd := rand.Uint32()
+	rnd := uint32(s.rand.Uint64())
 	h := uint32(1)
 	for h < maxHeight && rnd <= probabilities[h] {
 		h++
diff --git a/vendor/golang.org/x/exp/AUTHORS b/vendor/golang.org/x/exp/AUTHORS
new file mode 100644
index 0000000..15167cd
--- /dev/null
+++ b/vendor/golang.org/x/exp/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/exp/CONTRIBUTORS b/vendor/golang.org/x/exp/CONTRIBUTORS
new file mode 100644
index 0000000..1c4577e
--- /dev/null
+++ b/vendor/golang.org/x/exp/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/exp/LICENSE b/vendor/golang.org/x/exp/LICENSE
new file mode 100644
index 0000000..6a66aea
--- /dev/null
+++ b/vendor/golang.org/x/exp/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+   * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+   * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+   * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/exp/PATENTS b/vendor/golang.org/x/exp/PATENTS
new file mode 100644
index 0000000..7330990
--- /dev/null
+++ b/vendor/golang.org/x/exp/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go.  This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation.  If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/exp/rand/exp.go b/vendor/golang.org/x/exp/rand/exp.go
new file mode 100644
index 0000000..4bc110f
--- /dev/null
+++ b/vendor/golang.org/x/exp/rand/exp.go
@@ -0,0 +1,222 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+import (
+	"math"
+)
+
+/*
+ * Exponential distribution
+ *
+ * See "The Ziggurat Method for Generating Random Variables"
+ * (Marsaglia & Tsang, 2000)
+ * http://www.jstatsoft.org/v05/i08/paper [pdf]
+ */
+
+const (
+	re = 7.69711747013104972
+)
+
+// ExpFloat64 returns an exponentially distributed float64 in the range
+// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
+// (lambda) is 1 and whose mean is 1/lambda (1).
+// To produce a distribution with a different rate parameter,
+// callers can adjust the output using:
+//
+//  sample = ExpFloat64() / desiredRateParameter
+//
+func (r *Rand) ExpFloat64() float64 {
+	for {
+		j := r.Uint32()
+		i := j & 0xFF
+		x := float64(j) * float64(we[i])
+		if j < ke[i] {
+			return x
+		}
+		if i == 0 {
+			return re - math.Log(r.Float64())
+		}
+		if fe[i]+float32(r.Float64())*(fe[i-1]-fe[i]) < float32(math.Exp(-x)) {
+			return x
+		}
+	}
+}
+
+var ke = [256]uint32{
+	0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990,
+	0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8,
+	0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78,
+	0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651,
+	0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca,
+	0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8,
+	0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea,
+	0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba,
+	0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed,
+	0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662,
+	0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3,
+	0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace,
+	0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6,
+	0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7,
+	0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415,
+	0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4,
+	0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36,
+	0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46,
+	0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac,
+	0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245,
+	0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52,
+	0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06,
+	0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0,
+	0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9,
+	0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76,
+	0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516,
+	0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289,
+	0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed,
+	0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb,
+	0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e,
+	0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a,
+	0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1,
+	0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b,
+	0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621,
+	0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d,
+	0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3,
+	0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73,
+	0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88,
+	0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a,
+	0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb,
+	0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176,
+	0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be,
+	0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192,
+	0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed,
+	0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936,
+	0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b,
+	0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4,
+	0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1,
+	0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482,
+	0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023,
+	0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d,
+	0xe6da6ecf,
+}
+var we = [256]float32{
+	2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11,
+	3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11,
+	5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11,
+	7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11,
+	9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10,
+	1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10,
+	1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10,
+	1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10,
+	1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10,
+	1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10,
+	1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10,
+	1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10,
+	1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10,
+	1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10,
+	2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10,
+	2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10,
+	2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10,
+	2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10,
+	2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10,
+	2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10,
+	2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10,
+	2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10,
+	2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10,
+	2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10,
+	3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10,
+	3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10,
+	3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10,
+	3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10,
+	3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10,
+	3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10,
+	3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10,
+	3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10,
+	3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10,
+	4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10,
+	4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10,
+	4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10,
+	4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10,
+	4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10,
+	4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10,
+	4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10,
+	4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10,
+	5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10,
+	5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10,
+	5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10,
+	5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10,
+	5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10,
+	5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10,
+	6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10,
+	6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10,
+	6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10,
+	6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10,
+	6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10,
+	7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10,
+	7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10,
+	7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10,
+	8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10,
+	8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10,
+	8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10,
+	9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10,
+	9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09,
+	1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09,
+	1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09,
+	1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09,
+	1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09,
+}
+var fe = [256]float32{
+	1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933,
+	0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686,
+	0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665,
+	0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967,
+	0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896,
+	0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092,
+	0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386,
+	0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495,
+	0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752,
+	0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325,
+	0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955,
+	0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694,
+	0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218,
+	0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763,
+	0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044,
+	0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796,
+	0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408,
+	0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928,
+	0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393,
+	0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625,
+	0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107,
+	0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878,
+	0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438,
+	0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682,
+	0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852,
+	0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479,
+	0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354,
+	0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494,
+	0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119,
+	0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624,
+	0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574,
+	0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672,
+	0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763,
+	0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816,
+	0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919,
+	0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274,
+	0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195,
+	0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106,
+	0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434,
+	0.062193416, 0.060783047, 0.059384305, 0.057997175,
+	0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236,
+	0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623,
+	0.043502413, 0.042254124, 0.041017443, 0.039792392,
+	0.038578995, 0.037377283, 0.036187284, 0.035009038,
+	0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566,
+	0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421,
+	0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867,
+	0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392,
+	0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414,
+	0.008780315, 0.007963077, 0.0071633533, 0.006381906,
+	0.0056196423, 0.0048776558, 0.004157295, 0.0034602648,
+	0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693,
+	0.00045413437,
+}
diff --git a/vendor/golang.org/x/exp/rand/normal.go b/vendor/golang.org/x/exp/rand/normal.go
new file mode 100644
index 0000000..ba4ea54
--- /dev/null
+++ b/vendor/golang.org/x/exp/rand/normal.go
@@ -0,0 +1,157 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+import (
+	"math"
+)
+
+/*
+ * Normal distribution
+ *
+ * See "The Ziggurat Method for Generating Random Variables"
+ * (Marsaglia & Tsang, 2000)
+ * http://www.jstatsoft.org/v05/i08/paper [pdf]
+ */
+
+const (
+	rn = 3.442619855899
+)
+
+func absInt32(i int32) uint32 {
+	if i < 0 {
+		return uint32(-i)
+	}
+	return uint32(i)
+}
+
+// NormFloat64 returns a normally distributed float64 in the range
+// [-math.MaxFloat64, +math.MaxFloat64] with
+// standard normal distribution (mean = 0, stddev = 1).
+// To produce a different normal distribution, callers can
+// adjust the output using:
+//
+//  sample = NormFloat64() * desiredStdDev + desiredMean
+//
+func (r *Rand) NormFloat64() float64 {
+	for {
+		j := int32(r.Uint32()) // Possibly negative
+		i := j & 0x7F
+		x := float64(j) * float64(wn[i])
+		if absInt32(j) < kn[i] {
+			// This case should be hit better than 99% of the time.
+			return x
+		}
+
+		if i == 0 {
+			// This extra work is only required for the base strip.
+			for {
+				x = -math.Log(r.Float64()) * (1.0 / rn)
+				y := -math.Log(r.Float64())
+				if y+y >= x*x {
+					break
+				}
+			}
+			if j > 0 {
+				return rn + x
+			}
+			return -rn - x
+		}
+		if fn[i]+float32(r.Float64())*(fn[i-1]-fn[i]) < float32(math.Exp(-.5*x*x)) {
+			return x
+		}
+	}
+}
+
+var kn = [128]uint32{
+	0x76ad2212, 0x0, 0x600f1b53, 0x6ce447a6, 0x725b46a2,
+	0x7560051d, 0x774921eb, 0x789a25bd, 0x799045c3, 0x7a4bce5d,
+	0x7adf629f, 0x7b5682a6, 0x7bb8a8c6, 0x7c0ae722, 0x7c50cce7,
+	0x7c8cec5b, 0x7cc12cd6, 0x7ceefed2, 0x7d177e0b, 0x7d3b8883,
+	0x7d5bce6c, 0x7d78dd64, 0x7d932886, 0x7dab0e57, 0x7dc0dd30,
+	0x7dd4d688, 0x7de73185, 0x7df81cea, 0x7e07c0a3, 0x7e163efa,
+	0x7e23b587, 0x7e303dfd, 0x7e3beec2, 0x7e46db77, 0x7e51155d,
+	0x7e5aabb3, 0x7e63abf7, 0x7e6c222c, 0x7e741906, 0x7e7b9a18,
+	0x7e82adfa, 0x7e895c63, 0x7e8fac4b, 0x7e95a3fb, 0x7e9b4924,
+	0x7ea0a0ef, 0x7ea5b00d, 0x7eaa7ac3, 0x7eaf04f3, 0x7eb3522a,
+	0x7eb765a5, 0x7ebb4259, 0x7ebeeafd, 0x7ec2620a, 0x7ec5a9c4,
+	0x7ec8c441, 0x7ecbb365, 0x7ece78ed, 0x7ed11671, 0x7ed38d62,
+	0x7ed5df12, 0x7ed80cb4, 0x7eda175c, 0x7edc0005, 0x7eddc78e,
+	0x7edf6ebf, 0x7ee0f647, 0x7ee25ebe, 0x7ee3a8a9, 0x7ee4d473,
+	0x7ee5e276, 0x7ee6d2f5, 0x7ee7a620, 0x7ee85c10, 0x7ee8f4cd,
+	0x7ee97047, 0x7ee9ce59, 0x7eea0eca, 0x7eea3147, 0x7eea3568,
+	0x7eea1aab, 0x7ee9e071, 0x7ee98602, 0x7ee90a88, 0x7ee86d08,
+	0x7ee7ac6a, 0x7ee6c769, 0x7ee5bc9c, 0x7ee48a67, 0x7ee32efc,
+	0x7ee1a857, 0x7edff42f, 0x7ede0ffa, 0x7edbf8d9, 0x7ed9ab94,
+	0x7ed7248d, 0x7ed45fae, 0x7ed1585c, 0x7ece095f, 0x7eca6ccb,
+	0x7ec67be2, 0x7ec22eee, 0x7ebd7d1a, 0x7eb85c35, 0x7eb2c075,
+	0x7eac9c20, 0x7ea5df27, 0x7e9e769f, 0x7e964c16, 0x7e8d44ba,
+	0x7e834033, 0x7e781728, 0x7e6b9933, 0x7e5d8a1a, 0x7e4d9ded,
+	0x7e3b737a, 0x7e268c2f, 0x7e0e3ff5, 0x7df1aa5d, 0x7dcf8c72,
+	0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
+	0x7ba90bdc, 0x7a722176, 0x77d664e5,
+}
+var wn = [128]float32{
+	1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
+	2.2232431e-10, 2.4244937e-10, 2.601613e-10, 2.7611988e-10,
+	2.9073963e-10, 3.042997e-10, 3.1699796e-10, 3.289802e-10,
+	3.4035738e-10, 3.5121603e-10, 3.616251e-10, 3.7164058e-10,
+	3.8130857e-10, 3.9066758e-10, 3.9975012e-10, 4.08584e-10,
+	4.1719309e-10, 4.2559822e-10, 4.338176e-10, 4.418672e-10,
+	4.497613e-10, 4.5751258e-10, 4.651324e-10, 4.7263105e-10,
+	4.8001775e-10, 4.87301e-10, 4.944885e-10, 5.015873e-10,
+	5.0860405e-10, 5.155446e-10, 5.2241467e-10, 5.2921934e-10,
+	5.359635e-10, 5.426517e-10, 5.4928817e-10, 5.5587696e-10,
+	5.624219e-10, 5.6892646e-10, 5.753941e-10, 5.818282e-10,
+	5.882317e-10, 5.946077e-10, 6.00959e-10, 6.072884e-10,
+	6.135985e-10, 6.19892e-10, 6.2617134e-10, 6.3243905e-10,
+	6.386974e-10, 6.449488e-10, 6.511956e-10, 6.5744005e-10,
+	6.6368433e-10, 6.699307e-10, 6.7618144e-10, 6.824387e-10,
+	6.8870465e-10, 6.949815e-10, 7.012715e-10, 7.075768e-10,
+	7.1389966e-10, 7.202424e-10, 7.266073e-10, 7.329966e-10,
+	7.394128e-10, 7.4585826e-10, 7.5233547e-10, 7.58847e-10,
+	7.653954e-10, 7.719835e-10, 7.7861395e-10, 7.852897e-10,
+	7.920138e-10, 7.987892e-10, 8.0561924e-10, 8.125073e-10,
+	8.194569e-10, 8.2647167e-10, 8.3355556e-10, 8.407127e-10,
+	8.479473e-10, 8.55264e-10, 8.6266755e-10, 8.7016316e-10,
+	8.777562e-10, 8.8545243e-10, 8.932582e-10, 9.0117996e-10,
+	9.09225e-10, 9.174008e-10, 9.2571584e-10, 9.341788e-10,
+	9.427997e-10, 9.515889e-10, 9.605579e-10, 9.697193e-10,
+	9.790869e-10, 9.88676e-10, 9.985036e-10, 1.0085882e-09,
+	1.0189509e-09, 1.0296151e-09, 1.0406069e-09, 1.0519566e-09,
+	1.063698e-09, 1.0758702e-09, 1.0885183e-09, 1.1016947e-09,
+	1.1154611e-09, 1.1298902e-09, 1.1450696e-09, 1.1611052e-09,
+	1.1781276e-09, 1.1962995e-09, 1.2158287e-09, 1.2369856e-09,
+	1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09,
+	1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09,
+}
+var fn = [128]float32{
+	1, 0.9635997, 0.9362827, 0.9130436, 0.89228165, 0.87324303,
+	0.8555006, 0.8387836, 0.8229072, 0.8077383, 0.793177,
+	0.7791461, 0.7655842, 0.7524416, 0.73967725, 0.7272569,
+	0.7151515, 0.7033361, 0.69178915, 0.68049186, 0.6694277,
+	0.658582, 0.6479418, 0.63749546, 0.6272325, 0.6171434,
+	0.6072195, 0.5974532, 0.58783704, 0.5783647, 0.56903,
+	0.5598274, 0.5507518, 0.54179835, 0.5329627, 0.52424055,
+	0.5156282, 0.50712204, 0.49871865, 0.49041483, 0.48220766,
+	0.4740943, 0.46607214, 0.4581387, 0.45029163, 0.44252872,
+	0.43484783, 0.427247, 0.41972435, 0.41227803, 0.40490642,
+	0.39760786, 0.3903808, 0.3832238, 0.37613547, 0.36911446,
+	0.3621595, 0.35526937, 0.34844297, 0.34167916, 0.33497685,
+	0.3283351, 0.3217529, 0.3152294, 0.30876362, 0.30235484,
+	0.29600215, 0.28970486, 0.2834622, 0.2772735, 0.27113807,
+	0.2650553, 0.25902456, 0.2530453, 0.24711695, 0.241239,
+	0.23541094, 0.22963232, 0.2239027, 0.21822165, 0.21258877,
+	0.20700371, 0.20146611, 0.19597565, 0.19053204, 0.18513499,
+	0.17978427, 0.17447963, 0.1692209, 0.16400786, 0.15884037,
+	0.15371831, 0.14864157, 0.14361008, 0.13862377, 0.13368265,
+	0.12878671, 0.12393598, 0.119130544, 0.11437051, 0.10965602,
+	0.104987256, 0.10036444, 0.095787846, 0.0912578, 0.08677467,
+	0.0823389, 0.077950984, 0.073611505, 0.06932112, 0.06508058,
+	0.06089077, 0.056752663, 0.0526674, 0.048636295, 0.044660863,
+	0.040742867, 0.03688439, 0.033087887, 0.029356318,
+	0.025693292, 0.022103304, 0.018592102, 0.015167298,
+	0.011839478, 0.008624485, 0.005548995, 0.0026696292,
+}
diff --git a/vendor/golang.org/x/exp/rand/rand.go b/vendor/golang.org/x/exp/rand/rand.go
new file mode 100644
index 0000000..884e3e4
--- /dev/null
+++ b/vendor/golang.org/x/exp/rand/rand.go
@@ -0,0 +1,363 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package rand implements pseudo-random number generators.
+//
+// Random numbers are generated by a Source. Top-level functions, such as
+// Float64 and Int, use a default shared Source that produces a deterministic
+// sequence of values each time a program is run. Use the Seed function to
+// initialize the default Source if different behavior is required for each run.
+// The default Source, a LockedSource, is safe for concurrent use by multiple
+// goroutines, but Sources created by NewSource are not. However, Sources are small
+// and it is reasonable to have a separate Source for each goroutine, seeded
+// differently, to avoid locking.
+//
+// For random numbers suitable for security-sensitive work, see the crypto/rand
+// package.
+package rand
+
+import "sync"
+
+// A Source represents a source of uniformly-distributed
+// pseudo-random int64 values in the range [0, 1<<64).
+type Source interface {
+	Uint64() uint64
+	Seed(seed uint64)
+}
+
+// NewSource returns a new pseudo-random Source seeded with the given value.
+func NewSource(seed uint64) Source {
+	var rng PCGSource
+	rng.Seed(seed)
+	return &rng
+}
+
+// A Rand is a source of random numbers.
+type Rand struct {
+	src Source
+
+	// readVal contains remainder of 64-bit integer used for bytes
+	// generation during most recent Read call.
+	// It is saved so next Read call can start where the previous
+	// one finished.
+	readVal uint64
+	// readPos indicates the number of low-order bytes of readVal
+	// that are still valid.
+	readPos int8
+}
+
+// New returns a new Rand that uses random values from src
+// to generate other random values.
+func New(src Source) *Rand {
+	return &Rand{src: src}
+}
+
+// Seed uses the provided seed value to initialize the generator to a deterministic state.
+// Seed should not be called concurrently with any other Rand method.
+func (r *Rand) Seed(seed uint64) {
+	if lk, ok := r.src.(*LockedSource); ok {
+		lk.seedPos(seed, &r.readPos)
+		return
+	}
+
+	r.src.Seed(seed)
+	r.readPos = 0
+}
+
+// Uint64 returns a pseudo-random 64-bit integer as a uint64.
+func (r *Rand) Uint64() uint64 { return r.src.Uint64() }
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
+func (r *Rand) Int63() int64 { return int64(r.src.Uint64() &^ (1 << 63)) }
+
+// Uint32 returns a pseudo-random 32-bit value as a uint32.
+func (r *Rand) Uint32() uint32 { return uint32(r.Uint64() >> 32) }
+
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
+func (r *Rand) Int31() int32 { return int32(r.Uint64() >> 33) }
+
+// Int returns a non-negative pseudo-random int.
+func (r *Rand) Int() int {
+	u := uint(r.Uint64())
+	return int(u << 1 >> 1) // clear sign bit.
+}
+
+const maxUint64 = (1 << 64) - 1
+
+// Uint64n returns, as a uint64, a pseudo-random number in [0,n).
+// It is guaranteed more uniform than taking a Source value mod n
+// for any n that is not a power of 2.
+func (r *Rand) Uint64n(n uint64) uint64 {
+	if n&(n-1) == 0 { // n is power of two, can mask
+		if n == 0 {
+			panic("invalid argument to Uint64n")
+		}
+		return r.Uint64() & (n - 1)
+	}
+	// If n does not divide v, to avoid bias we must not use
+	// a v that is within maxUint64%n of the top of the range.
+	v := r.Uint64()
+	if v > maxUint64-n { // Fast check.
+		ceiling := maxUint64 - maxUint64%n
+		for v >= ceiling {
+			v = r.Uint64()
+		}
+	}
+
+	return v % n
+}
+
+// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
+// It panics if n <= 0.
+func (r *Rand) Int63n(n int64) int64 {
+	if n <= 0 {
+		panic("invalid argument to Int63n")
+	}
+	return int64(r.Uint64n(uint64(n)))
+}
+
+// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
+// It panics if n <= 0.
+func (r *Rand) Int31n(n int32) int32 {
+	if n <= 0 {
+		panic("invalid argument to Int31n")
+	}
+	// TODO: Avoid some 64-bit ops to make it more efficient on 32-bit machines.
+	return int32(r.Uint64n(uint64(n)))
+}
+
+// Intn returns, as an int, a non-negative pseudo-random number in [0,n).
+// It panics if n <= 0.
+func (r *Rand) Intn(n int) int {
+	if n <= 0 {
+		panic("invalid argument to Intn")
+	}
+	// TODO: Avoid some 64-bit ops to make it more efficient on 32-bit machines.
+	return int(r.Uint64n(uint64(n)))
+}
+
+// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
+func (r *Rand) Float64() float64 {
+	// There is one bug in the value stream: r.Int63() may be so close
+	// to 1<<63 that the division rounds up to 1.0, and we've guaranteed
+	// that the result is always less than 1.0.
+	//
+	// We tried to fix this by mapping 1.0 back to 0.0, but since float64
+	// values near 0 are much denser than near 1, mapping 1 to 0 caused
+	// a theoretically significant overshoot in the probability of returning 0.
+	// Instead of that, if we round up to 1, just try again.
+	// Getting 1 only happens 1/2⁵³ of the time, so most clients
+	// will not observe it anyway.
+again:
+	f := float64(r.Uint64n(1<<53)) / (1 << 53)
+	if f == 1.0 {
+		goto again // resample; this branch is taken O(never)
+	}
+	return f
+}
+
+// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
+func (r *Rand) Float32() float32 {
+	// We do not want to return 1.0.
+	// This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Float64).
+again:
+	f := float32(r.Float64())
+	if f == 1 {
+		goto again // resample; this branch is taken O(very rarely)
+	}
+	return f
+}
+
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
+func (r *Rand) Perm(n int) []int {
+	m := make([]int, n)
+	// In the following loop, the iteration when i=0 always swaps m[0] with m[0].
+	// A change to remove this useless iteration is to assign 1 to i in the init
+	// statement. But Perm also effects r. Making this change will affect
+	// the final state of r. So this change can't be made for compatibility
+	// reasons for Go 1.
+	for i := 0; i < n; i++ {
+		j := r.Intn(i + 1)
+		m[i] = m[j]
+		m[j] = i
+	}
+	return m
+}
+
+// Shuffle pseudo-randomizes the order of elements.
+// n is the number of elements. Shuffle panics if n < 0.
+// swap swaps the elements with indexes i and j.
+func (r *Rand) Shuffle(n int, swap func(i, j int)) {
+	if n < 0 {
+		panic("invalid argument to Shuffle")
+	}
+
+	// Fisher-Yates shuffle: https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+	// Shuffle really ought not be called with n that doesn't fit in 32 bits.
+	// Not only will it take a very long time, but with 2³¹! possible permutations,
+	// there's no way that any PRNG can have a big enough internal state to
+	// generate even a minuscule percentage of the possible permutations.
+	// Nevertheless, the right API signature accepts an int n, so handle it as best we can.
+	i := n - 1
+	for ; i > 1<<31-1-1; i-- {
+		j := int(r.Int63n(int64(i + 1)))
+		swap(i, j)
+	}
+	for ; i > 0; i-- {
+		j := int(r.Int31n(int32(i + 1)))
+		swap(i, j)
+	}
+}
+
+// Read generates len(p) random bytes and writes them into p. It
+// always returns len(p) and a nil error.
+// Read should not be called concurrently with any other Rand method.
+func (r *Rand) Read(p []byte) (n int, err error) {
+	if lk, ok := r.src.(*LockedSource); ok {
+		return lk.Read(p, &r.readVal, &r.readPos)
+	}
+	return read(p, r.Uint64, &r.readVal, &r.readPos)
+}
+
+func read(p []byte, uint64 func() uint64, readVal *uint64, readPos *int8) (n int, err error) {
+	pos := *readPos
+	val := *readVal
+	for n = 0; n < len(p); n++ {
+		if pos == 0 {
+			val = uint64()
+			pos = 8
+		}
+		p[n] = byte(val)
+		val >>= 8
+		pos--
+	}
+	*readPos = pos
+	*readVal = val
+	return
+}
+
+/*
+ * Top-level convenience functions
+ */
+
+var globalRand = New(&LockedSource{src: NewSource(1)})
+
+// Seed uses the provided seed value to initialize the default Source to a
+// deterministic state. If Seed is not called, the generator behaves as
+// if seeded by Seed(1).
+// Seed, unlike the Rand.Seed method, is safe for concurrent use.
+func Seed(seed uint64) { globalRand.Seed(seed) }
+
+// Int63 returns a non-negative pseudo-random 63-bit integer as an int64
+// from the default Source.
+func Int63() int64 { return globalRand.Int63() }
+
+// Uint32 returns a pseudo-random 32-bit value as a uint32
+// from the default Source.
+func Uint32() uint32 { return globalRand.Uint32() }
+
+// Uint64 returns a pseudo-random 64-bit value as a uint64
+// from the default Source.
+func Uint64() uint64 { return globalRand.Uint64() }
+
+// Int31 returns a non-negative pseudo-random 31-bit integer as an int32
+// from the default Source.
+func Int31() int32 { return globalRand.Int31() }
+
+// Int returns a non-negative pseudo-random int from the default Source.
+func Int() int { return globalRand.Int() }
+
+// Int63n returns, as an int64, a non-negative pseudo-random number in [0,n)
+// from the default Source.
+// It panics if n <= 0.
+func Int63n(n int64) int64 { return globalRand.Int63n(n) }
+
+// Int31n returns, as an int32, a non-negative pseudo-random number in [0,n)
+// from the default Source.
+// It panics if n <= 0.
+func Int31n(n int32) int32 { return globalRand.Int31n(n) }
+
+// Intn returns, as an int, a non-negative pseudo-random number in [0,n)
+// from the default Source.
+// It panics if n <= 0.
+func Intn(n int) int { return globalRand.Intn(n) }
+
+// Float64 returns, as a float64, a pseudo-random number in [0.0,1.0)
+// from the default Source.
+func Float64() float64 { return globalRand.Float64() }
+
+// Float32 returns, as a float32, a pseudo-random number in [0.0,1.0)
+// from the default Source.
+func Float32() float32 { return globalRand.Float32() }
+
+// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n)
+// from the default Source.
+func Perm(n int) []int { return globalRand.Perm(n) }
+
+// Shuffle pseudo-randomizes the order of elements using the default Source.
+// n is the number of elements. Shuffle panics if n < 0.
+// swap swaps the elements with indexes i and j.
+func Shuffle(n int, swap func(i, j int)) { globalRand.Shuffle(n, swap) }
+
+// Read generates len(p) random bytes from the default Source and
+// writes them into p. It always returns len(p) and a nil error.
+// Read, unlike the Rand.Read method, is safe for concurrent use.
+func Read(p []byte) (n int, err error) { return globalRand.Read(p) }
+
+// NormFloat64 returns a normally distributed float64 in the range
+// [-math.MaxFloat64, +math.MaxFloat64] with
+// standard normal distribution (mean = 0, stddev = 1)
+// from the default Source.
+// To produce a different normal distribution, callers can
+// adjust the output using:
+//
+//  sample = NormFloat64() * desiredStdDev + desiredMean
+//
+func NormFloat64() float64 { return globalRand.NormFloat64() }
+
+// ExpFloat64 returns an exponentially distributed float64 in the range
+// (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
+// (lambda) is 1 and whose mean is 1/lambda (1) from the default Source.
+// To produce a distribution with a different rate parameter,
+// callers can adjust the output using:
+//
+//  sample = ExpFloat64() / desiredRateParameter
+//
+func ExpFloat64() float64 { return globalRand.ExpFloat64() }
+
+// LockedSource is an implementation of Source that is concurrency-safe.
+// It is just a standard Source with its operations protected by a sync.Mutex.
+type LockedSource struct {
+	lk  sync.Mutex
+	src Source
+}
+
+func (s *LockedSource) Uint64() (n uint64) {
+	s.lk.Lock()
+	n = s.src.Uint64()
+	s.lk.Unlock()
+	return
+}
+
+func (s *LockedSource) Seed(seed uint64) {
+	s.lk.Lock()
+	s.src.Seed(seed)
+	s.lk.Unlock()
+}
+
+// seedPos implements Seed for a LockedSource without a race condiiton.
+func (s *LockedSource) seedPos(seed uint64, readPos *int8) {
+	s.lk.Lock()
+	s.src.Seed(seed)
+	*readPos = 0
+	s.lk.Unlock()
+}
+
+// Read implements Read for a LockedSource.
+func (s *LockedSource) Read(p []byte, readVal *uint64, readPos *int8) (n int, err error) {
+	s.lk.Lock()
+	n, err = read(p, s.src.Uint64, readVal, readPos)
+	s.lk.Unlock()
+	return
+}
diff --git a/vendor/golang.org/x/exp/rand/rng.go b/vendor/golang.org/x/exp/rand/rng.go
new file mode 100644
index 0000000..f59fadb
--- /dev/null
+++ b/vendor/golang.org/x/exp/rand/rng.go
@@ -0,0 +1,55 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rand
+
+import "math/bits"
+
+// PCGSource is an implementation of a 64-bit permuted congruential
+// generator as defined in
+//
+// 	PCG: A Family of Simple Fast Space-Efficient Statistically Good
+// 	Algorithms for Random Number Generation
+// 	Melissa E. O’Neill, Harvey Mudd College
+// 	http://www.pcg-random.org/pdf/toms-oneill-pcg-family-v1.02.pdf
+//
+// The generator here is the congruential generator PCG XSL RR 128/64 (LCG)
+// as found in the software available at http://www.pcg-random.org/.
+// It has period 2^128 with 128 bits of state, producing 64-bit values.
+// Is state is represented by two uint64 words.
+type PCGSource struct {
+	low  uint64
+	high uint64
+}
+
+const (
+	maxUint32 = (1 << 32) - 1
+
+	multiplier = 47026247687942121848144207491837523525
+	mulHigh    = multiplier >> 64
+	mulLow     = multiplier & maxUint64
+
+	increment = 117397592171526113268558934119004209487
+	incHigh   = increment >> 64
+	incLow    = increment & maxUint64
+
+	// TODO: Use these?
+	initializer = 245720598905631564143578724636268694099
+	initHigh    = initializer >> 64
+	initLow     = initializer & maxUint64
+)
+
+// Seed uses the provided seed value to initialize the generator to a deterministic state.
+func (pcg *PCGSource) Seed(seed uint64) {
+	pcg.low = seed
+	pcg.high = seed // TODO: What is right?
+}
+
+// Uint64 returns a pseudo-random 64-bit unsigned integer as a uint64.
+func (pcg *PCGSource) Uint64() uint64 {
+	pcg.multiply()
+	pcg.add()
+	// XOR high and low 64 bits together and rotate right by high 6 bits of state.
+	return bits.RotateLeft64(pcg.high^pcg.low, -int(pcg.high>>58))
+}
diff --git a/vendor/golang.org/x/exp/rand/uint64.go b/vendor/golang.org/x/exp/rand/uint64.go
new file mode 100644
index 0000000..cc1fc01
--- /dev/null
+++ b/vendor/golang.org/x/exp/rand/uint64.go
@@ -0,0 +1,23 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.12
+
+package rand
+
+import "math/bits"
+
+func (pcg *PCGSource) add() {
+	var carry uint64
+	pcg.low, carry = bits.Add64(pcg.low, incLow, 0)
+	pcg.high, _ = bits.Add64(pcg.high, incHigh, carry)
+}
+
+func (pcg *PCGSource) multiply() {
+	hi, lo := bits.Mul64(pcg.low, mulLow)
+	hi += pcg.high * mulLow
+	hi += pcg.low * mulHigh
+	pcg.low = lo
+	pcg.high = hi
+}
diff --git a/vendor/golang.org/x/exp/rand/uint64_fallback.go b/vendor/golang.org/x/exp/rand/uint64_fallback.go
new file mode 100644
index 0000000..58f66cf
--- /dev/null
+++ b/vendor/golang.org/x/exp/rand/uint64_fallback.go
@@ -0,0 +1,44 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !go1.12
+
+package rand
+
+func (pcg *PCGSource) add() {
+	old := pcg.low
+	pcg.low += incLow
+	if pcg.low < old {
+		// Carry occurred.
+		pcg.high++
+	}
+	pcg.high += incHigh
+}
+
+func (pcg *PCGSource) multiply() {
+	// Break each lower word into two separate 32-bit 'digits' each stored
+	// in a 64-bit word with 32 high zero bits.  This allows the overflow
+	// into the high word to be computed.
+	s0 := (pcg.low >> 00) & maxUint32
+	s1 := (pcg.low >> 32) & maxUint32
+
+	const (
+		m0    = (multiplier >> 00) & maxUint32
+		m1    = (multiplier >> 32) & maxUint32
+		mLow  = multiplier & (1<<64 - 1)
+		mHigh = multiplier >> 64 & (1<<64 - 1)
+	)
+
+	high := pcg.low*mHigh + pcg.high*mLow
+	s0m0 := s0 * m0
+	s0m1 := s0 * m1
+	s1m0 := s1 * m0
+	s1m1 := s1 * m1
+	high += (s0m1 >> 32) + (s1m0 >> 32)
+	carry := (s0m1 & maxUint32) + (s1m0 & maxUint32) + s0m0>>32
+	high += (carry >> 32)
+
+	pcg.low *= mLow
+	pcg.high = high + s1m1
+}
diff --git a/vendor/golang.org/x/exp/rand/zipf.go b/vendor/golang.org/x/exp/rand/zipf.go
new file mode 100644
index 0000000..f04c814
--- /dev/null
+++ b/vendor/golang.org/x/exp/rand/zipf.go
@@ -0,0 +1,77 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// W.Hormann, G.Derflinger:
+// "Rejection-Inversion to Generate Variates
+// from Monotone Discrete Distributions"
+// http://eeyore.wu-wien.ac.at/papers/96-04-04.wh-der.ps.gz
+
+package rand
+
+import "math"
+
+// A Zipf generates Zipf distributed variates.
+type Zipf struct {
+	r            *Rand
+	imax         float64
+	v            float64
+	q            float64
+	s            float64
+	oneminusQ    float64
+	oneminusQinv float64
+	hxm          float64
+	hx0minusHxm  float64
+}
+
+func (z *Zipf) h(x float64) float64 {
+	return math.Exp(z.oneminusQ*math.Log(z.v+x)) * z.oneminusQinv
+}
+
+func (z *Zipf) hinv(x float64) float64 {
+	return math.Exp(z.oneminusQinv*math.Log(z.oneminusQ*x)) - z.v
+}
+
+// NewZipf returns a Zipf variate generator.
+// The generator generates values k ∈ [0, imax]
+// such that P(k) is proportional to (v + k) ** (-s).
+// Requirements: s > 1 and v >= 1.
+func NewZipf(r *Rand, s float64, v float64, imax uint64) *Zipf {
+	z := new(Zipf)
+	if s <= 1.0 || v < 1 {
+		return nil
+	}
+	z.r = r
+	z.imax = float64(imax)
+	z.v = v
+	z.q = s
+	z.oneminusQ = 1.0 - z.q
+	z.oneminusQinv = 1.0 / z.oneminusQ
+	z.hxm = z.h(z.imax + 0.5)
+	z.hx0minusHxm = z.h(0.5) - math.Exp(math.Log(z.v)*(-z.q)) - z.hxm
+	z.s = 1 - z.hinv(z.h(1.5)-math.Exp(-z.q*math.Log(z.v+1.0)))
+	return z
+}
+
+// Uint64 returns a value drawn from the Zipf distribution described
+// by the Zipf object.
+func (z *Zipf) Uint64() uint64 {
+	if z == nil {
+		panic("rand: nil Zipf")
+	}
+	k := 0.0
+
+	for {
+		r := z.r.Float64() // r on [0,1]
+		ur := z.hxm + r*z.hx0minusHxm
+		x := z.hinv(ur)
+		k = math.Floor(x + 0.5)
+		if k-x <= z.s {
+			break
+		}
+		if ur >= z.h(k+0.5)-math.Exp(-math.Log(k+z.v)*z.q) {
+			break
+		}
+	}
+	return uint64(k)
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 1f4dff8..edfc563 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -19,3 +19,5 @@ github.com/spf13/pflag
 # github.com/stretchr/testify v1.2.2
 github.com/stretchr/testify/require
 github.com/stretchr/testify/assert
+# golang.org/x/exp v0.0.0-20190426190305-956cc1757749
+golang.org/x/exp/rand


Test patch:
diff --git a/commit_test.go b/commit_test.go
index e4cb382..f4c80b4 100644
--- a/commit_test.go
+++ b/commit_test.go
@@ -8,7 +8,6 @@ import (
 	"encoding/binary"
 	"fmt"
 	"io/ioutil"
-	"math/rand"
 	"sync"
 	"sync/atomic"
 	"testing"
@@ -16,6 +15,7 @@ import (
 
 	"github.com/petermattis/pebble/internal/arenaskl"
 	"github.com/petermattis/pebble/internal/record"
+	"golang.org/x/exp/rand"
 )
 
 type testCommitEnv struct {
@@ -171,7 +171,7 @@ func BenchmarkCommitPipeline(b *testing.B) {
 			b.ResetTimer()
 
 			b.RunParallel(func(pb *testing.PB) {
-				rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 				buf := make([]byte, keySize)
 
 				for pb.Next() {
diff --git a/db/comparer_test.go b/db/comparer_test.go
index eb6514f..4a635bf 100644
--- a/db/comparer_test.go
+++ b/db/comparer_test.go
@@ -6,10 +6,11 @@ package db
 
 import (
 	"fmt"
-	"math/rand"
 	"sort"
 	"testing"
 	"time"
+
+	"golang.org/x/exp/rand"
 )
 
 func TestDefAppendSeparator(t *testing.T) {
@@ -55,7 +56,7 @@ func TestDefAppendSeparator(t *testing.T) {
 }
 
 func TestAbbreviatedKey(t *testing.T) {
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	randBytes := func(size int) []byte {
 		data := make([]byte, size)
 		for i := range data {
diff --git a/db_test.go b/db_test.go
index b6da234..b8a5516 100644
--- a/db_test.go
+++ b/db_test.go
@@ -9,7 +9,6 @@ import (
 	"errors"
 	"fmt"
 	"io"
-	"math/rand"
 	"os"
 	"strconv"
 	"strings"
@@ -20,6 +19,7 @@ import (
 	"github.com/petermattis/pebble/cache"
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 // try repeatedly calls f, sleeping between calls with exponential back-off,
diff --git a/ingest_test.go b/ingest_test.go
index 58b59c1..8639e6a 100644
--- a/ingest_test.go
+++ b/ingest_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"fmt"
 	"io/ioutil"
-	"math/rand"
 	"regexp"
 	"sort"
 	"strconv"
@@ -21,6 +20,7 @@ import (
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/sstable"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 func TestIngestLoad(t *testing.T) {
@@ -69,7 +69,7 @@ func TestIngestLoad(t *testing.T) {
 
 func TestIngestLoadRand(t *testing.T) {
 	mem := storage.NewMem()
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	cmp := db.DefaultComparer.Compare
 
 	randBytes := func(size int) []byte {
diff --git a/internal/arenaskl/skl_test.go b/internal/arenaskl/skl_test.go
index 96c177d..6e65b3c 100644
--- a/internal/arenaskl/skl_test.go
+++ b/internal/arenaskl/skl_test.go
@@ -21,7 +21,6 @@ import (
 	"bytes"
 	"encoding/binary"
 	"fmt"
-	"math/rand"
 	"strconv"
 	"sync"
 	"sync/atomic"
@@ -30,6 +29,7 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/stretchr/testify/require"
+	"golang.org/x/exp/rand"
 )
 
 const arenaSize = 1 << 20
@@ -652,7 +652,7 @@ func BenchmarkReadWrite(b *testing.B) {
 			var count int
 			b.RunParallel(func(pb *testing.PB) {
 				it := l.NewIter(nil, nil)
-				rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 				buf := make([]byte, 8)
 
 				for pb.Next() {
@@ -690,7 +690,7 @@ func BenchmarkOrderedWrite(b *testing.B) {
 
 func BenchmarkIterNext(b *testing.B) {
 	l := NewSkiplist(NewArena(64<<10, 0), bytes.Compare)
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	buf := make([]byte, 8)
 	for {
 		if err := l.Add(randomKey(rng, buf), nil); err == ErrArenaFull {
@@ -710,7 +710,7 @@ func BenchmarkIterNext(b *testing.B) {
 
 func BenchmarkIterPrev(b *testing.B) {
 	l := NewSkiplist(NewArena(64<<10, 0), bytes.Compare)
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	buf := make([]byte, 8)
 	for {
 		if err := l.Add(randomKey(rng, buf), nil); err == ErrArenaFull {
diff --git a/internal/batchskl/skl_test.go b/internal/batchskl/skl_test.go
index 24e9103..be69636 100644
--- a/internal/batchskl/skl_test.go
+++ b/internal/batchskl/skl_test.go
@@ -21,12 +21,12 @@ import (
 	"bytes"
 	"encoding/binary"
 	"fmt"
-	"math/rand"
 	"testing"
 	"time"
 
 	"github.com/petermattis/pebble/db"
 	"github.com/stretchr/testify/require"
+	"golang.org/x/exp/rand"
 )
 
 // length iterates over skiplist to give exact size.
@@ -383,7 +383,7 @@ func BenchmarkReadWrite(b *testing.B) {
 			}
 			l := NewSkiplist(d, 0)
 			it := l.NewIter(nil, nil)
-			rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+			rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 			b.ResetTimer()
 			for i := 0; i < b.N; i++ {
@@ -408,7 +408,7 @@ func BenchmarkIterNext(b *testing.B) {
 	}
 	l := NewSkiplist(d, 0)
 
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	for i := 0; i < len(buf); i += 8 {
 		key := randomKey(rng, buf[i:i+8])
 		offset := uint32(len(d.keys))
@@ -433,7 +433,7 @@ func BenchmarkIterPrev(b *testing.B) {
 	}
 	l := NewSkiplist(d, 0)
 
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	for i := 0; i < len(buf); i += 8 {
 		key := randomKey(rng, buf[i:i+8])
 		offset := uint32(len(d.keys))
diff --git a/internal/record/record_test.go b/internal/record/record_test.go
index b41fc28..82741bf 100644
--- a/internal/record/record_test.go
+++ b/internal/record/record_test.go
@@ -10,10 +10,11 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
-	"math/rand"
 	"os"
 	"strings"
 	"testing"
+
+	"golang.org/x/exp/rand"
 )
 
 func short(s string) string {
diff --git a/iterator_test.go b/iterator_test.go
index f2571da..da9a8b2 100644
--- a/iterator_test.go
+++ b/iterator_test.go
@@ -8,7 +8,6 @@ import (
 	"bytes"
 	"errors"
 	"fmt"
-	"math/rand"
 	"strconv"
 	"strings"
 	"testing"
@@ -16,6 +15,7 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
+	"golang.org/x/exp/rand"
 )
 
 var testKeyValuePairs = []string{
@@ -362,7 +362,7 @@ func BenchmarkIteratorSeekGE(b *testing.B) {
 		equal: db.DefaultComparer.Equal,
 		iter:  m.newIter(nil),
 	}
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
diff --git a/level_iter_test.go b/level_iter_test.go
index 0b1c3c5..9eb1619 100644
--- a/level_iter_test.go
+++ b/level_iter_test.go
@@ -7,7 +7,6 @@ package pebble
 import (
 	"bytes"
 	"fmt"
-	"math/rand"
 	"strings"
 	"testing"
 	"time"
@@ -18,6 +17,7 @@ import (
 	"github.com/petermattis/pebble/internal/rangedel"
 	"github.com/petermattis/pebble/sstable"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 func TestLevelIter(t *testing.T) {
@@ -291,7 +291,7 @@ func BenchmarkLevelIterSeekGE(b *testing.B) {
 								return readers[meta.fileNum].NewIter(nil /* lower */, nil /* upper */), nil, nil
 							}
 							l := newLevelIter(nil, db.DefaultComparer.Compare, newIters, files)
-							rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+							rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 							b.ResetTimer()
 							for i := 0; i < b.N; i++ {
diff --git a/mem_table_test.go b/mem_table_test.go
index 6cf31c4..0fbbbd1 100644
--- a/mem_table_test.go
+++ b/mem_table_test.go
@@ -7,7 +7,6 @@ package pebble
 import (
 	"bytes"
 	"fmt"
-	"math/rand"
 	"strconv"
 	"strings"
 	"sync"
@@ -18,6 +17,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/arenaskl"
 	"github.com/petermattis/pebble/internal/datadriven"
+	"golang.org/x/exp/rand"
 )
 
 // Set sets the value for the given key. It overwrites any previous value for
@@ -341,7 +341,7 @@ func buildMemTable(b *testing.B) (*memTable, [][]byte) {
 func BenchmarkMemTableIterSeekGE(b *testing.B) {
 	m, keys := buildMemTable(b)
 	iter := m.newIter(nil)
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
diff --git a/merging_iter_test.go b/merging_iter_test.go
index 268b048..08e285b 100644
--- a/merging_iter_test.go
+++ b/merging_iter_test.go
@@ -6,7 +6,6 @@ package pebble
 
 import (
 	"fmt"
-	"math/rand"
 	"strings"
 	"testing"
 	"time"
@@ -16,6 +15,7 @@ import (
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/sstable"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 func TestMergingIter(t *testing.T) {
@@ -202,7 +202,7 @@ func BenchmarkMergingIterSeekGE(b *testing.B) {
 								iters[i] = readers[i].NewIter(nil /* lower */, nil /* upper */)
 							}
 							m := newMergingIter(db.DefaultComparer.Compare, iters...)
-							rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+							rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 							b.ResetTimer()
 							for i := 0; i < b.N; i++ {
diff --git a/ptable/block_test.go b/ptable/block_test.go
index 9d6a158..2825386 100644
--- a/ptable/block_test.go
+++ b/ptable/block_test.go
@@ -6,11 +6,12 @@ package ptable
 
 import (
 	"fmt"
-	"math/rand"
 	"reflect"
 	"testing"
 	"time"
 	"unsafe"
+
+	"golang.org/x/exp/rand"
 )
 
 func randBlock(rng *rand.Rand, rows int, schema []ColumnType) ([]byte, []interface{}) {
@@ -171,7 +172,7 @@ func testSchema(t *testing.T, rng *rand.Rand, rows int, schema []ColumnType) {
 }
 
 func TestBlockWriter(t *testing.T) {
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	randInt := func(lo, hi int) int {
 		return lo + rng.Intn(hi-lo)
 	}
@@ -217,7 +218,7 @@ func TestBlockWriterNullValues(t *testing.T) {
 }
 
 func BenchmarkBlock(b *testing.B) {
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	blocks := make([][]byte, 128)
 	for i := range blocks {
 		blocks[i], _ = randBlock(rng, 4096, []ColumnType{ColumnTypeInt64})
diff --git a/ptable/column_test.go b/ptable/column_test.go
index 794e9e8..6ae2681 100644
--- a/ptable/column_test.go
+++ b/ptable/column_test.go
@@ -6,9 +6,10 @@ package ptable
 
 import (
 	"fmt"
-	"math/rand"
 	"testing"
 	"time"
+
+	"golang.org/x/exp/rand"
 )
 
 func randNullBitmap(rng *rand.Rand, size int) NullBitmap {
@@ -21,7 +22,7 @@ func randNullBitmap(rng *rand.Rand, size int) NullBitmap {
 
 func BenchmarkNullBitmapGet(b *testing.B) {
 	const size = 4096
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	bmap := randNullBitmap(rng, size)
 	b.ResetTimer()
 
@@ -44,7 +45,7 @@ func BenchmarkNullBitmapGet(b *testing.B) {
 
 func BenchmarkNullBitmapRank(b *testing.B) {
 	const size = 4096
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	bmap := randNullBitmap(rng, size)
 	b.ResetTimer()
 
diff --git a/ptable/table_test.go b/ptable/table_test.go
index 7e8b17f..71e4c3b 100644
--- a/ptable/table_test.go
+++ b/ptable/table_test.go
@@ -6,7 +6,6 @@ package ptable
 
 import (
 	"fmt"
-	"math/rand"
 	"sort"
 	"testing"
 	"time"
@@ -14,6 +13,7 @@ import (
 	"github.com/petermattis/pebble/cache"
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 type testEnv []ColumnDef
@@ -202,7 +202,7 @@ func BenchmarkTableIterSeekGE(b *testing.B) {
 
 	r, keys := buildBenchmarkTable(b, blockSize, false /* NULL values */)
 	it := r.NewIter()
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 	b.ResetTimer()
 	for i := 0; i < b.N; i++ {
diff --git a/read_state_test.go b/read_state_test.go
index d694093..d3409fb 100644
--- a/read_state_test.go
+++ b/read_state_test.go
@@ -6,12 +6,12 @@ package pebble
 
 import (
 	"fmt"
-	"math/rand"
 	"testing"
 	"time"
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 func BenchmarkReadState(b *testing.B) {
@@ -25,7 +25,7 @@ func BenchmarkReadState(b *testing.B) {
 	for _, updateFrac := range []float32{0, 0.1, 0.5} {
 		b.Run(fmt.Sprintf("updates=%.0f", updateFrac*100), func(b *testing.B) {
 			b.RunParallel(func(pb *testing.PB) {
-				rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 				for pb.Next() {
 					if rng.Float32() < updateFrac {
diff --git a/sstable/block_test.go b/sstable/block_test.go
index b4e4a6a..58bf71e 100644
--- a/sstable/block_test.go
+++ b/sstable/block_test.go
@@ -7,7 +7,6 @@ package sstable
 import (
 	"bytes"
 	"fmt"
-	"math/rand"
 	"strconv"
 	"strings"
 	"testing"
@@ -15,6 +14,7 @@ import (
 
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
+	"golang.org/x/exp/rand"
 )
 
 func TestBlockWriter(t *testing.T) {
@@ -227,7 +227,7 @@ func BenchmarkBlockIterSeekGE(b *testing.B) {
 				if err != nil {
 					b.Fatal(err)
 				}
-				rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 				b.ResetTimer()
 				for i := 0; i < b.N; i++ {
@@ -269,7 +269,7 @@ func BenchmarkBlockIterSeekLT(b *testing.B) {
 				if err != nil {
 					b.Fatal(err)
 				}
-				rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 				b.ResetTimer()
 				for i := 0; i < b.N; i++ {
diff --git a/sstable/reader_test.go b/sstable/reader_test.go
index 08a986a..577267e 100644
--- a/sstable/reader_test.go
+++ b/sstable/reader_test.go
@@ -9,7 +9,6 @@ import (
 	"encoding/binary"
 	"fmt"
 	"io/ioutil"
-	"math/rand"
 	"strconv"
 	"strings"
 	"testing"
@@ -20,6 +19,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/internal/datadriven"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 func TestReader(t *testing.T) {
@@ -228,7 +228,7 @@ func BenchmarkTableIterSeekGE(b *testing.B) {
 			func(b *testing.B) {
 				r, keys := buildBenchmarkTable(b, blockSize, restartInterval)
 				it := r.NewIter(nil /* lower */, nil /* upper */)
-				rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 				b.ResetTimer()
 				for i := 0; i < b.N; i++ {
@@ -246,7 +246,7 @@ func BenchmarkTableIterSeekLT(b *testing.B) {
 			func(b *testing.B) {
 				r, keys := buildBenchmarkTable(b, blockSize, restartInterval)
 				it := r.NewIter(nil /* lower */, nil /* upper */)
-				rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+				rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 
 				b.ResetTimer()
 				for i := 0; i < b.N; i++ {
diff --git a/sstable/table_test.go b/sstable/table_test.go
index 19467ac..1b6c47e 100644
--- a/sstable/table_test.go
+++ b/sstable/table_test.go
@@ -10,7 +10,6 @@ import (
 	"encoding/binary"
 	"fmt"
 	"io"
-	"math/rand"
 	"os"
 	"path/filepath"
 	"sort"
@@ -22,6 +21,7 @@ import (
 	"github.com/petermattis/pebble/bloom"
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 // nonsenseWords are words that aren't in testdata/h.txt.
@@ -228,7 +228,7 @@ func check(f storage.File, comparer *db.Comparer, fp db.FilterPolicy) error {
 
 	// Check lower/upper bounds behavior. Randomly choose a lower and upper bound
 	// and then guarantee that iteration finds the expected number if entries.
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	sort.Strings(words)
 	for i := 0; i < 10; i++ {
 		lowerIdx := -1
diff --git a/sstable/unsafe_test.go b/sstable/unsafe_test.go
index ac6be6e..b1aa91d 100644
--- a/sstable/unsafe_test.go
+++ b/sstable/unsafe_test.go
@@ -8,10 +8,11 @@ import (
 	"encoding/binary"
 	"fmt"
 	"io/ioutil"
-	"math/rand"
 	"testing"
 	"time"
 	"unsafe"
+
+	"golang.org/x/exp/rand"
 )
 
 func TestDecodeVarint(t *testing.T) {
@@ -39,7 +40,7 @@ func TestDecodeVarint(t *testing.T) {
 }
 
 func BenchmarkDecodeVarint(b *testing.B) {
-	rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+	rng := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
 	vals := make([]unsafe.Pointer, 10000)
 	for i := range vals {
 		buf := make([]byte, 5)
diff --git a/sstable/writer_fixture_test.go b/sstable/writer_fixture_test.go
index 0b51542..e329545 100644
--- a/sstable/writer_fixture_test.go
+++ b/sstable/writer_fixture_test.go
@@ -23,7 +23,6 @@ import (
 
 	"github.com/petermattis/pebble/bloom"
 	"github.com/petermattis/pebble/db"
-	"github.com/pkg/errors"
 )
 
 const (
@@ -88,7 +87,7 @@ var fixtures = map[fixtureOpts]struct {
 func runTestFixtureOutput(opts fixtureOpts) error {
 	fixture, ok := fixtures[opts]
 	if !ok {
-		return errors.Errorf("fixture missing: %+v", opts)
+		return fmt.Errorf("fixture missing: %+v", opts)
 	}
 
 	compression := db.NoCompression
diff --git a/table_cache_test.go b/table_cache_test.go
index 23be6fe..c2aa3b3 100644
--- a/table_cache_test.go
+++ b/table_cache_test.go
@@ -7,7 +7,6 @@ package pebble
 import (
 	"bytes"
 	"fmt"
-	"math/rand"
 	"strings"
 	"sync"
 	"testing"
@@ -16,6 +15,7 @@ import (
 	"github.com/petermattis/pebble/db"
 	"github.com/petermattis/pebble/sstable"
 	"github.com/petermattis/pebble/storage"
+	"golang.org/x/exp/rand"
 )
 
 type tableCacheTestFile struct {