chore: switch to math/rand/v2

This commit is contained in:
Vincent Bernat
2025-10-26 12:14:20 +01:00
parent dd8ef6abcc
commit ee6e197e8e
12 changed files with 115 additions and 100 deletions

View File

@@ -11,7 +11,7 @@ import (
"image/draw"
"image/png"
"io/fs"
"math/rand"
"math/rand/v2"
"net/http"
"akvorado/common/embed"
@@ -31,7 +31,7 @@ func (c *Component) UserAvatarHandlerFunc(gc *gin.Context) {
info := gc.MustGet("user").(UserInformation)
hash := fnv.New64()
hash.Write([]byte(info.Login))
randSource := rand.New(rand.NewSource(int64(hash.Sum64())))
randSource := rand.New(rand.NewPCG(hash.Sum64(), 0))
etag := fmt.Sprintf(`"%x"`, hash.Sum64())
// Do we have a If-None-Match header?
@@ -70,7 +70,7 @@ func (c *Component) UserAvatarHandlerFunc(gc *gin.Context) {
gc.JSON(http.StatusInternalServerError, gin.H{"message": "Cannot build avatar."})
return
}
parts[idx] = p[randSource.Intn(len(p))]
parts[idx] = p[randSource.IntN(len(p))]
}
// Compose the images

View File

@@ -8,7 +8,7 @@ import (
"hash/fnv"
"math"
"math/bits"
"math/rand"
"math/rand/v2"
"net/netip"
"time"
@@ -39,11 +39,8 @@ func randomIP(prefix netip.Prefix, r *rand.Rand) netip.Addr {
result[i] = prefix.Addr().AsSlice()[i]
continue
}
shiftMask := prefix.Bits() - i*8
if shiftMask < 0 {
shiftMask = 0
}
randomByte := byte(int(r.Int31n(256)))
shiftMask := max(0, prefix.Bits()-i*8)
randomByte := byte(r.IntN(256))
randomByte = randomByte & ^bits.Reverse8(byte((1<<shiftMask)-1))
result[i] = randomByte | prefix.Addr().AsSlice()[i]
}
@@ -69,7 +66,7 @@ func chooseRandom[T any](r *rand.Rand, slice []T) T {
if len(slice) == 1 {
return slice[0]
}
return slice[r.Intn(len(slice))]
return slice[r.IntN(len(slice))]
}
// generateFlows generate a set of flows using the provided
@@ -83,7 +80,7 @@ func generateFlows(flowConfigs []FlowConfiguration, seed int64, now time.Time) [
// Initialize the random number generator to a known state
hash := fnv.New64()
fmt.Fprintf(hash, "%d %d", now.Unix(), seed)
r := rand.New(rand.NewSource(int64(hash.Sum64())))
r := rand.New(rand.NewPCG(hash.Sum64(), 0))
nowTime := now.Sub(now.Truncate(time.Hour * 24))
for _, flowConfig := range flowConfigs {
@@ -104,7 +101,7 @@ func generateFlows(flowConfigs []FlowConfiguration, seed int64, now time.Time) [
},
}
if flowConfig.Size == 0 {
flow.Octets = uint32(r.Int31n(1200) + 300)
flow.Octets = uint32(r.Int32N(1200) + 300)
} else {
flow.Octets = uint32(float64(flowConfig.Size) * (r.NormFloat64()*0.3 + 1))
if flow.Octets > 9000 {
@@ -122,12 +119,12 @@ func generateFlows(flowConfigs []FlowConfiguration, seed int64, now time.Time) [
if srcPort := chooseRandom(r, flowConfig.SrcPort); srcPort != 0 {
flow.SrcPort = srcPort
} else {
flow.SrcPort = uint16(r.Int31n(2000) + 33000)
flow.SrcPort = uint16(r.Int32N(2000) + 33000)
}
if dstPort := chooseRandom(r, flowConfig.DstPort); dstPort != 0 {
flow.DstPort = dstPort
} else {
flow.DstPort = uint16(r.Int31n(2000) + 33000)
flow.DstPort = uint16(r.Int32N(2000) + 33000)
}
}
if flow.SrcAddr.Is4() {

View File

@@ -6,7 +6,7 @@ package flows
import (
"fmt"
"math"
"math/rand"
"math/rand/v2"
"net/netip"
"testing"
"time"
@@ -41,7 +41,7 @@ func TestRandomIP(t *testing.T) {
"2001:db8:a:b::/64",
"2001:db8:a:c:d::1/128",
}
r := rand.New(rand.NewSource(0))
r := rand.New(rand.NewPCG(0, 0))
for _, p := range prefixes {
prefix := netip.MustParsePrefix(p)
for range 1000 {
@@ -89,7 +89,7 @@ func TestChooseRandom(t *testing.T) {
{6},
{1, 2, 3, 4, 10, 12},
}
r := rand.New(rand.NewSource(0))
r := rand.New(rand.NewPCG(0, 0))
for _, tc := range cases {
t.Run(fmt.Sprintf("%v", tc), func(t *testing.T) {
results := map[int]bool{}
@@ -146,15 +146,15 @@ func TestGenerateFlows(t *testing.T) {
},
Expected: []generatedFlow{
{
SrcAddr: netip.MustParseAddr("192.0.2.36"),
DstAddr: netip.MustParseAddr("203.0.113.91"),
SrcAddr: netip.MustParseAddr("192.0.2.155"),
DstAddr: netip.MustParseAddr("203.0.113.59"),
EType: 0x800,
IPFlow: IPFlow{
Octets: 1365,
Octets: 1011,
Packets: 1,
Proto: 6,
SrcPort: 443,
DstPort: 34905,
DstPort: 33550,
InputInt: 10,
OutputInt: 21,
SrcAS: 65201,
@@ -164,17 +164,35 @@ func TestGenerateFlows(t *testing.T) {
DstMask: 24,
},
}, {
SrcAddr: netip.MustParseAddr("192.0.2.30"),
DstAddr: netip.MustParseAddr("203.0.113.220"),
SrcAddr: netip.MustParseAddr("192.0.2.3"),
DstAddr: netip.MustParseAddr("203.0.113.52"),
EType: 0x800,
IPFlow: IPFlow{
Octets: 1500,
Octets: 1478,
Packets: 1,
Proto: 6,
SrcPort: 443,
DstPort: 33618,
DstPort: 33200,
InputInt: 10,
OutputInt: 21,
OutputInt: 20,
SrcAS: 65201,
DstAS: 65202,
ForwardStatus: 64,
SrcMask: 24,
DstMask: 24,
},
}, {
SrcAddr: netip.MustParseAddr("192.0.2.151"),
DstAddr: netip.MustParseAddr("203.0.113.245"),
EType: 2048,
IPFlow: IPFlow{
Packets: 1,
Octets: 1311,
Proto: 6,
InputInt: 10,
OutputInt: 20,
SrcPort: 443,
DstPort: 33389,
SrcAS: 65201,
DstAS: 65202,
ForwardStatus: 64,
@@ -202,13 +220,13 @@ func TestGenerateFlows(t *testing.T) {
Expected: []generatedFlow{
{
SrcAddr: netip.MustParseAddr("2001:db8::1"),
DstAddr: netip.MustParseAddr("2001:db8:2:0:245b:11f7:351e:dc1a"),
DstAddr: netip.MustParseAddr("2001:db8:2:0:9b3b:48ac:f003:34f4"),
EType: 0x86dd,
IPFlow: IPFlow{
Octets: 1170,
Octets: 866,
Packets: 1,
Proto: 6,
SrcPort: 34045,
SrcPort: 33820,
DstPort: 443,
InputInt: 20,
OutputInt: 11,
@@ -240,13 +258,13 @@ func TestGenerateFlows(t *testing.T) {
Expected: []generatedFlow{
{
SrcAddr: netip.MustParseAddr("2001:db8::1"),
DstAddr: netip.MustParseAddr("2001:db8:2:0:245b:11f7:351e:dc1a"),
DstAddr: netip.MustParseAddr("2001:db8:2:0:9b3b:48ac:f003:34f4"),
EType: 0x86dd,
IPFlow: IPFlow{
Octets: 1170,
Octets: 866,
Packets: 1,
Proto: 6,
SrcPort: 34045,
SrcPort: 33820,
DstPort: 443,
InputInt: 20,
OutputInt: 11,
@@ -258,13 +276,13 @@ func TestGenerateFlows(t *testing.T) {
},
}, {
DstAddr: netip.MustParseAddr("2001:db8::1"),
SrcAddr: netip.MustParseAddr("2001:db8:2:0:245b:11f7:351e:dc1a"),
SrcAddr: netip.MustParseAddr("2001:db8:2:0:9b3b:48ac:f003:34f4"),
EType: 0x86dd,
IPFlow: IPFlow{
Octets: 1170 / 10,
Octets: 866 / 10,
Packets: 1,
Proto: 6,
DstPort: 34045,
DstPort: 33820,
SrcPort: 443,
OutputInt: 20,
InputInt: 11,

View File

@@ -6,7 +6,7 @@ package kafka
import (
"context"
"fmt"
"math/rand"
"math/rand/v2"
"sync"
"testing"
"time"
@@ -49,10 +49,10 @@ func TestFakeKafka(t *testing.T) {
msg1 := make([]byte, 50)
msg2 := make([]byte, 50)
for i := range msg1 {
msg1[i] = letters[rand.Intn(len(letters))]
msg1[i] = letters[rand.IntN(len(letters))]
}
for i := range msg2 {
msg2[i] = letters[rand.Intn(len(letters))]
msg2[i] = letters[rand.IntN(len(letters))]
}
var wg sync.WaitGroup
wg.Add(2)

View File

@@ -8,7 +8,7 @@ import (
"context"
"encoding/binary"
"fmt"
"math/rand"
"math/rand/v2"
"strings"
"time"

View File

@@ -6,7 +6,7 @@ package kafka
import (
"context"
"fmt"
"math/rand"
"math/rand/v2"
"testing"
"time"

View File

@@ -6,7 +6,7 @@ package clickhouse
import (
"context"
"fmt"
"math/rand"
"math/rand/v2"
"strconv"
"time"

View File

@@ -6,7 +6,7 @@ package kafka
import (
"context"
"fmt"
"math/rand"
"math/rand/v2"
"strconv"
"strings"
"sync/atomic"

View File

@@ -8,7 +8,7 @@ import (
"fmt"
"io/fs"
"math"
"math/rand"
"math/rand/v2"
"net/netip"
"path/filepath"
"slices"
@@ -419,8 +419,8 @@ func TestConcurrentOperations(t *testing.T) {
nowLock.RLock()
now := now
nowLock.RUnlock()
ip := rand.Intn(10)
iface := rand.Intn(100)
ip := rand.IntN(10)
iface := rand.IntN(100)
sc.Put(now, provider.Query{
ExporterIP: netip.MustParseAddr(fmt.Sprintf("::ffff:127.0.0.%d", ip)),
IfIndex: uint(iface),
@@ -443,8 +443,8 @@ func TestConcurrentOperations(t *testing.T) {
nowLock.RLock()
now := now
nowLock.RUnlock()
ip := rand.Intn(10)
iface := rand.Intn(100)
ip := rand.IntN(10)
iface := rand.IntN(100)
sc.Lookup(now, provider.Query{
ExporterIP: netip.MustParseAddr(fmt.Sprintf("::ffff:127.0.0.%d", ip)),
IfIndex: uint(iface),

View File

@@ -8,7 +8,7 @@ import (
"crypto/tls"
"errors"
"fmt"
"math/rand"
"math/rand/v2"
"net/netip"
"sync"
"time"
@@ -244,7 +244,7 @@ func (p *Provider) chooseRouter(agent netip.Addr) (netip.Addr, *RISInstanceRunti
// Randomly select a ris providing the router ID we selected earlier.
// In the future, we might also want to exclude currently unavailable ris instances
chosenRis = p.routers[chosenRouterID][rand.Intn(len(p.routers[chosenRouterID]))]
chosenRis = p.routers[chosenRouterID][rand.IntN(len(p.routers[chosenRouterID]))]
if chosenRis == nil || chosenRouterID.IsUnspecified() {
return chosenRouterID, nil, errNoInstance

View File

@@ -6,7 +6,7 @@ package bmp
import (
"fmt"
"iter"
"math/rand"
"math/rand/v2"
"net/netip"
"runtime"
"slices"
@@ -30,7 +30,7 @@ var prefixSizeDistribution = [33]int{
}
func init() {
prng := rand.New(rand.NewSource(0))
prng := rand.New(rand.NewPCG(0, 0))
// Data from https://bgp.potaroo.net/as2.0/bgp-asbyhop-vector.txt
asDistanceDistribution := []int{
1, 2, 366, 9645, 29251, 28984, 7340, 1423, 383, 63, 14, 2, 4, 4, 4, 4, 1, 0,
@@ -46,7 +46,7 @@ func init() {
for i := range uniqueASPaths {
// Generate AS path length based on distribution
asPathLen := 1
r := prng.Intn(totalAS)
r := prng.IntN(totalAS)
cumulative := 0
for len, count := range asDistanceDistribution {
cumulative += count
@@ -62,7 +62,7 @@ func init() {
// Generate unique AS path
asPath := make([]uint32, asPathLen)
for j := 0; j < asPathLen; j++ {
asPath[j] = uint32(prng.Intn(64494) + 1)
asPath[j] = uint32(prng.IntN(64494) + 1)
}
asPathCache[i] = asPath
}
@@ -87,7 +87,7 @@ func randomRealWorldRoutes4(prngPrefixes, prngASPaths *rand.Rand, n int) iter.Se
for range n {
// Generate prefix length based on distribution
prefixLen := 0
r := prngPrefixes.Intn(totalRoutes)
r := prngPrefixes.IntN(totalRoutes)
cumulative := 0
for len, count := range prefixSizeDistribution {
cumulative += count
@@ -99,34 +99,34 @@ func randomRealWorldRoutes4(prngPrefixes, prngASPaths *rand.Rand, n int) iter.Se
// Generate random IPv4 prefix
ip := netip.AddrFrom4([4]byte{
byte(prngPrefixes.Intn(224)),
byte(prngPrefixes.Intn(256)),
byte(prngPrefixes.Intn(256)),
byte(prngPrefixes.Intn(256)),
byte(prngPrefixes.IntN(224)),
byte(prngPrefixes.IntN(256)),
byte(prngPrefixes.IntN(256)),
byte(prngPrefixes.IntN(256)),
})
prefix := netip.PrefixFrom(ip, prefixLen).Masked()
// Select a random AS path from the pre-generated cache
asPath := asPathCache[prngASPaths.Intn(len(asPathCache))]
asPath := asPathCache[prngASPaths.IntN(len(asPathCache))]
// Generate communities (0-5 communities per route)
numCommunities := max(0, prngASPaths.Intn(10)-4)
numCommunities := max(0, prngASPaths.IntN(10)-4)
communities := make([]uint32, numCommunities)
for j := range numCommunities {
asFromPath := asPath[prngASPaths.Intn(len(asPath))]
communities[j] = asFromPath<<16 | uint32(prngASPaths.Intn(3))
asFromPath := asPath[prngASPaths.IntN(len(asPath))]
communities[j] = asFromPath<<16 | uint32(prngASPaths.IntN(3))
}
slices.Sort(communities)
communities = slices.Compact(communities)
// Generate large communities (0-3 per route, but they are rare)
numLargeCommunities := max(0, prngASPaths.Intn(100)-97)
numLargeCommunities := max(0, prngASPaths.IntN(100)-97)
largeCommunities := make([]bgp.LargeCommunity, numLargeCommunities)
for j := range numLargeCommunities {
largeCommunities[j] = bgp.LargeCommunity{
ASN: asPath[prngASPaths.Intn(len(asPath))],
LocalData1: uint32(prngASPaths.Intn(2)) + 1,
LocalData2: uint32(prngASPaths.Intn(2)) + 1,
ASN: asPath[prngASPaths.IntN(len(asPath))],
LocalData1: uint32(prngASPaths.IntN(2)) + 1,
LocalData2: uint32(prngASPaths.IntN(2)) + 1,
}
}
@@ -145,23 +145,23 @@ func randomRealWorldRoutes4(prngPrefixes, prngASPaths *rand.Rand, n int) iter.Se
}
func TestRandomRealWorldRoutes4(t *testing.T) {
prng1 := rand.New(rand.NewSource(1))
prng2 := rand.New(rand.NewSource(2))
prng1 := rand.New(rand.NewPCG(1, 1))
prng2 := rand.New(rand.NewPCG(2, 2))
routes := []randomRoute{}
for route := range randomRealWorldRoutes4(prng1, prng2, 2) {
routes = append(routes, route)
}
expectedRoutes := []randomRoute{
{
Prefix: netip.MustParsePrefix("79.199.187.0/24"),
ASPath: []uint32{29418, 57855, 38297},
Communities: []uint32{1927938050, 2509832194},
Prefix: netip.MustParsePrefix("22.172.220.0/24"),
ASPath: []uint32{5310, 16496, 48042, 23205},
Communities: []uint32{347996161, 1081081858, 1520762881, 1520762882, 3148480513},
LargeCommunities: []bgp.LargeCommunity{},
},
{
Prefix: netip.MustParsePrefix("185.172.72.0/24"),
ASPath: []uint32{25258, 9490, 64459, 11892, 37685},
Communities: []uint32{},
Prefix: netip.MustParsePrefix("181.109.115.0/24"),
ASPath: []uint32{9514, 53442, 28732, 62632, 53821},
Communities: []uint32{623509505, 1882980354, 4104650753},
LargeCommunities: []bgp.LargeCommunity{},
},
}
@@ -171,8 +171,8 @@ func TestRandomRealWorldRoutes4(t *testing.T) {
}
func TestRandomRealWorldRoutes4Distribution(t *testing.T) {
prng1 := rand.New(rand.NewSource(42))
prng2 := rand.New(rand.NewSource(43))
prng1 := rand.New(rand.NewPCG(42, 42))
prng2 := rand.New(rand.NewPCG(43, 43))
totalRoutes := 0
for _, v := range prefixSizeDistribution {
@@ -220,10 +220,10 @@ func BenchmarkRIBInsertion(b *testing.B) {
for b.Loop() {
rib = newRIB()
nh := netip.MustParseAddr("::ffff:198.51.100.0")
prng1 := rand.New(rand.NewSource(10))
prng1 := rand.New(rand.NewPCG(10, 10))
prng2 := make([]*rand.Rand, peers)
for p := range peers {
prng2[p] = rand.New(rand.NewSource(int64(p)))
prng2[p] = rand.New(rand.NewPCG(uint64(p), uint64(p)))
}
for p := range peers {
nh = nh.Next()
@@ -236,7 +236,7 @@ func BenchmarkRIBInsertion(b *testing.B) {
b.StartTimer()
for _, r := range randomPrefixes {
if prng2[p].Intn(10) == 0 {
if prng2[p].IntN(10) == 0 {
continue
}
pfx := netip.PrefixFrom(netip.AddrFrom16(r.Prefix.Addr().As16()), r.Prefix.Bits()+96)
@@ -272,8 +272,8 @@ func BenchmarkRIBInsertion(b *testing.B) {
func BenchmarkRIBLookup(b *testing.B) {
for _, routes := range []int{1_000, 10_000, 100_000, 1_000_000} {
prng1 := rand.New(rand.NewSource(10))
prng2 := rand.New(rand.NewSource(0))
prng1 := rand.New(rand.NewPCG(10, 10))
prng2 := rand.New(rand.NewPCG(0, 0))
randomPrefixes := []randomRoute{}
for r := range randomRealWorldRoutes4(prng1, prng2, routes/10) {
randomPrefixes = append(randomPrefixes, r)
@@ -284,15 +284,15 @@ func BenchmarkRIBLookup(b *testing.B) {
b.Run(name, func(b *testing.B) {
rib := newRIB()
nh := netip.MustParseAddr("::ffff:198.51.100.0")
prng1 := rand.New(rand.NewSource(10))
prng1 := rand.New(rand.NewPCG(10, 10))
prng2 := make([]*rand.Rand, peers)
for p := range peers {
prng2[p] = rand.New(rand.NewSource(int64(p)))
prng2[p] = rand.New(rand.NewPCG(uint64(p), uint64(p)))
}
for p := range peers {
nh = nh.Next()
for r := range randomRealWorldRoutes4(prng1, prng2[p], routes) {
if prng2[p].Intn(10) == 0 {
if prng2[p].IntN(10) == 0 {
continue
}
pfx := netip.PrefixFrom(netip.AddrFrom16(r.Prefix.Addr().As16()), r.Prefix.Bits()+96)
@@ -333,15 +333,15 @@ func BenchmarkRIBFlush(b *testing.B) {
b.StopTimer()
rib := newRIB()
nh := netip.MustParseAddr("::ffff:198.51.100.0")
prng1 := rand.New(rand.NewSource(10))
prng1 := rand.New(rand.NewPCG(10, 10))
prng2 := make([]*rand.Rand, peers)
for p := range peers {
prng2[p] = rand.New(rand.NewSource(int64(p)))
prng2[p] = rand.New(rand.NewPCG(uint64(p), uint64(p)))
}
for p := range peers {
nh = nh.Next()
for r := range randomRealWorldRoutes4(prng1, prng2[p], routes) {
if prng2[p].Intn(10) == 0 {
if prng2[p].IntN(10) == 0 {
continue
}
pfx := netip.PrefixFrom(netip.AddrFrom16(r.Prefix.Addr().As16()), r.Prefix.Bits()+96)

View File

@@ -5,7 +5,7 @@ package bmp
import (
"fmt"
"math/rand"
"math/rand/v2"
"net/netip"
"testing"
"unsafe"
@@ -331,7 +331,7 @@ func TestRemoveRoutes(t *testing.T) {
func TestRIBHarness(t *testing.T) {
for run := range 5 {
random := rand.New(rand.NewSource(int64(run)))
random := rand.New(rand.NewPCG(uint64(run), 0))
run++
// Ramp up the test
@@ -378,17 +378,17 @@ func TestRIBHarness(t *testing.T) {
for j := range peerPerExporter {
peer := uint32((i << 16) + int(j))
peers = append(peers, peer)
toAdd := random.Intn(maxInitialRoutePerPeer)
toAdd := random.IntN(maxInitialRoutePerPeer)
added := 0
for range toAdd {
lookup := lookup{
peer: peer,
addr: netip.MustParseAddr(fmt.Sprintf("2001:db8:f:%x::",
random.Intn(300))),
random.IntN(300))),
nextHop: netip.MustParseAddr(
fmt.Sprintf("2001:db8:c::%x", random.Intn(500))),
rd: RD(random.Intn(3)),
asn: uint32(random.Intn(1000)),
fmt.Sprintf("2001:db8:c::%x", random.IntN(500))),
rd: RD(random.IntN(3)),
asn: uint32(random.IntN(1000)),
comment: "added during first pass",
}
added += r.AddPrefix(netip.PrefixFrom(lookup.addr, 64),
@@ -405,12 +405,12 @@ func TestRIBHarness(t *testing.T) {
}
t.Logf("Run %d: added = %d/%d", run, added, toAdd)
toRemove := random.Intn(maxRemovedRoutePerPeer)
toRemove := random.IntN(maxRemovedRoutePerPeer)
removed := 0
for range toRemove {
prefix := netip.MustParseAddr(fmt.Sprintf("2001:db8:f:%x::",
random.Intn(300)))
rd := RD(random.Intn(4))
random.IntN(300)))
rd := RD(random.IntN(4))
if nlriRef, ok := r.nlris.Ref(nlri{
rd: rd,
}); ok {
@@ -428,16 +428,16 @@ func TestRIBHarness(t *testing.T) {
}
t.Logf("Run %d: removed = %d/%d", run, removed, toRemove)
toAdd = random.Intn(maxReaddedRoutePerPeer)
toAdd = random.IntN(maxReaddedRoutePerPeer)
added = 0
for range toAdd {
lookup := lookup{
peer: peer,
addr: netip.MustParseAddr(fmt.Sprintf("2001:db8:f:%x::",
random.Intn(300))),
random.IntN(300))),
nextHop: netip.MustParseAddr(
fmt.Sprintf("2001:db8:c::%x", random.Uint32()%500)),
asn: uint32(random.Intn(1010)),
asn: uint32(random.IntN(1010)),
comment: "added during third pass",
}
added += r.AddPrefix(netip.PrefixFrom(lookup.addr, 64),