Skip to content

Commit

Permalink
internal/grpcrand: New package for concurrency-safe randoms (#2106)
Browse files Browse the repository at this point in the history
  • Loading branch information
dfawley authored May 29, 2018
1 parent 1fa3750 commit bd7f82c
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 10 deletions.
5 changes: 3 additions & 2 deletions backoff.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
package grpc

import (
"math/rand"
"time"

"google.golang.org/grpc/internal/grpcrand"
)

// DefaultBackoffConfig uses values specified for backoff in
Expand Down Expand Up @@ -88,7 +89,7 @@ func (bc BackoffConfig) backoff(retries int) time.Duration {
}
// Randomize backoff delays so that if a cluster of requests start at
// the same time, they won't operate in lockstep.
backoff *= 1 + bc.jitter*(rand.Float64()*2-1)
backoff *= 1 + bc.jitter*(grpcrand.Float64()*2-1)
if backoff < 0 {
return 0
}
Expand Down
56 changes: 56 additions & 0 deletions internal/grpcrand/grpcrand.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
*
* Copyright 2018 gRPC authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

// Package grpcrand implements math/rand functions in a concurrent-safe way
// with a global random source, independent of math/rand's global source.
package grpcrand

import (
"math/rand"
"sync"
"time"
)

var (
r = rand.New(rand.NewSource(time.Now().UnixNano()))
mu sync.Mutex
)

// Int63n implements rand.Int63n on the grpcrand global source.
func Int63n(n int64) int64 {
mu.Lock()
res := r.Int63n(n)
mu.Unlock()
return res
}

// Intn implements rand.Intn on the grpcrand global source.
func Intn(n int) int {
mu.Lock()
res := r.Intn(n)
mu.Unlock()
return res
}

// Float64 implements rand.Float64 on the grpcrand global source.
func Float64() float64 {
mu.Lock()
res := r.Float64()
mu.Unlock()
return res
}
5 changes: 2 additions & 3 deletions resolver/dns/dns_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"net"
"os"
"strconv"
Expand All @@ -34,6 +33,7 @@ import (

"golang.org/x/net/context"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/internal/grpcrand"
"google.golang.org/grpc/resolver"
)

Expand All @@ -52,7 +52,6 @@ const (

var (
errMissingAddr = errors.New("missing address")
randomGen = rand.New(rand.NewSource(time.Now().UnixNano()))
)

// NewBuilder creates a dnsBuilder which is used to factory DNS resolvers.
Expand Down Expand Up @@ -346,7 +345,7 @@ func chosenByPercentage(a *int) bool {
if a == nil {
return true
}
return randomGen.Intn(100)+1 <= *a
return grpcrand.Intn(100)+1 <= *a
}

func canaryingSC(js string) string {
Expand Down
6 changes: 2 additions & 4 deletions transport/http2_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"fmt"
"io"
"math"
"math/rand"
"net"
"strconv"
"sync"
Expand All @@ -39,6 +38,7 @@ import (
"google.golang.org/grpc/channelz"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/internal/grpcrand"
"google.golang.org/grpc/keepalive"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
Expand Down Expand Up @@ -1125,14 +1125,12 @@ func (t *http2Server) getOutFlowWindow() int64 {
}
}

var rgen = rand.New(rand.NewSource(time.Now().UnixNano()))

func getJitter(v time.Duration) time.Duration {
if v == infinity {
return 0
}
// Generate a jitter between +/- 10% of the value.
r := int64(v / 10)
j := rgen.Int63n(2*r) - r
j := grpcrand.Int63n(2*r) - r
return time.Duration(j)
}
3 changes: 2 additions & 1 deletion vet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ if git status --porcelain | read; then
fi

git ls-files "*.go" | xargs grep -L "\(Copyright [0-9]\{4,\} gRPC authors\)\|DO NOT EDIT" 2>&1 | tee /dev/stderr | (! read)
git ls-files "*.go" | xargs grep -l "\"unsafe\"" 2>&1 | (! grep -v '_test.go') | tee /dev/stderr | (! read)
git ls-files "*.go" | xargs grep -l '"unsafe"' 2>&1 | (! grep -v '_test.go') | tee /dev/stderr | (! read)
git ls-files "*.go" | xargs grep -l '"math/rand"' 2>&1 | (! grep -v '^examples\|^stress\|grpcrand') | tee /dev/stderr | (! read)
gofmt -s -d -l . 2>&1 | tee /dev/stderr | (! read)
goimports -l . 2>&1 | tee /dev/stderr | (! read)
golint ./... 2>&1 | (grep -vE "(_mock|\.pb)\.go:" || true) | tee /dev/stderr | (! read)
Expand Down

0 comments on commit bd7f82c

Please sign in to comment.