Optimize random string generator to avoid multiple locks & use bitmasking

This commit is contained in:
Shyam Jeedigunta 2017-10-12 13:40:00 +02:00
parent 0564d52985
commit c279a53ca0
2 changed files with 41 additions and 16 deletions

View File

@ -73,7 +73,7 @@ func tokenSecretReferences() []v1.ObjectReference {
// addTokenSecretReference adds a reference to the ServiceAccountToken that will be created
func addTokenSecretReference(refs []v1.ObjectReference) []v1.ObjectReference {
return addNamedTokenSecretReference(refs, "default-token-stdpg")
return addNamedTokenSecretReference(refs, "default-token-xn8fg")
}
// addNamedTokenSecretReference adds a reference to the named ServiceAccountToken
@ -118,9 +118,9 @@ func opaqueSecret() *v1.Secret {
}
// createdTokenSecret returns the ServiceAccountToken secret posted when creating a new token secret.
// Named "default-token-stdpg", since that is the first generated name after rand.Seed(1)
// Named "default-token-xn8fg", since that is the first generated name after rand.Seed(1)
func createdTokenSecret(overrideName ...string) *v1.Secret {
return namedCreatedTokenSecret("default-token-stdpg")
return namedCreatedTokenSecret("default-token-xn8fg")
}
// namedTokenSecret returns the ServiceAccountToken secret posted when creating a new token secret with the given name.
@ -264,12 +264,12 @@ func TestTokenCreation(t *testing.T) {
// Attempt 2
core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, "default"),
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-jk9rt")),
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-txhzt")),
// Attempt 3
core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, "default"),
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-684pg")),
core.NewUpdateAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, serviceAccount(addNamedTokenSecretReference(emptySecretReferences(), "default-token-684pg"))),
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-vnmz7")),
core.NewUpdateAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, serviceAccount(addNamedTokenSecretReference(emptySecretReferences(), "default-token-vnmz7"))),
},
},
"new serviceaccount with no secrets encountering unending create error": {
@ -293,10 +293,10 @@ func TestTokenCreation(t *testing.T) {
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, createdTokenSecret()),
// Retry 1
core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, "default"),
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-jk9rt")),
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-txhzt")),
// Retry 2
core.NewGetAction(schema.GroupVersionResource{Version: "v1", Resource: "serviceaccounts"}, metav1.NamespaceDefault, "default"),
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-684pg")),
core.NewCreateAction(schema.GroupVersionResource{Version: "v1", Resource: "secrets"}, metav1.NamespaceDefault, namedCreatedTokenSecret("default-token-vnmz7")),
},
},
"new serviceaccount with missing secrets": {

View File

@ -70,16 +70,41 @@ func Perm(n int) []int {
return rng.rand.Perm(n)
}
// We omit vowels from the set of available characters to reduce the chances
// of "bad words" being formed.
var alphanums = []rune("bcdfghjklmnpqrstvwxz2456789")
const (
// We omit vowels from the set of available characters to reduce the chances
// of "bad words" being formed.
alphanums = "bcdfghjklmnpqrstvwxz2456789"
// No. of bits required to index into alphanums string.
alphanumsIdxBits = 5
// Mask used to extract last alphanumsIdxBits of an int.
alphanumsIdxMask = 1<<alphanumsIdxBits - 1
// No. of random letters we can extract from a single int63.
maxAlphanumsPerInt = 63 / alphanumsIdxBits
)
// String generates a random alphanumeric string, without vowels, which is n
// characters long. This will panic if n is less than zero.
func String(length int) string {
b := make([]rune, length)
for i := range b {
b[i] = alphanums[Intn(len(alphanums))]
// How the random string is created:
// - we generate random int63's
// - from each int63, we are extracting multiple random letters by bit-shifting and masking
// - if some index is out of range of alphanums we neglect it (unlikely to happen multiple times in a row)
func String(n int) string {
b := make([]byte, n)
rng.Lock()
defer rng.Unlock()
randomInt63 := rng.rand.Int63()
remaining := maxAlphanumsPerInt
for i := 0; i < n; {
if remaining == 0 {
randomInt63, remaining = rng.rand.Int63(), maxAlphanumsPerInt
}
if idx := int(randomInt63 & alphanumsIdxMask); idx < len(alphanums) {
b[i] = alphanums[idx]
i++
}
randomInt63 >>= alphanumsIdxBits
remaining--
}
return string(b)
}
@ -87,7 +112,7 @@ func String(length int) string {
// SafeEncodeString encodes s using the same characters as rand.String. This reduces the chances of bad words and
// ensures that strings generated from hash functions appear consistent throughout the API.
func SafeEncodeString(s string) string {
r := make([]rune, len(s))
r := make([]byte, len(s))
for i, b := range []rune(s) {
r[i] = alphanums[(int(b) % len(alphanums))]
}