Skip to content

Commit

Permalink
Memoize read-only arrays to improve performance (#139)
Browse files Browse the repository at this point in the history
Use the `sync` module to memoize read-only arrays with `Once` method to improve performance by making Go build `[]string` only one time.
  • Loading branch information
sean- authored Jun 1, 2023
1 parent 5d0f88f commit 190b989
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 37 deletions.
7 changes: 5 additions & 2 deletions faker.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"math"
"math/rand"
"sort"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -229,7 +230,7 @@ func (f Faker) RandomLetter() string {
}

func (f Faker) RandomStringWithLength(l int) string {
var r []string
r := make([]string, 0, l)

for i := 0; i < l; i++ {
r = append(r, f.RandomLetter())
Expand All @@ -249,6 +250,7 @@ func (f Faker) RandomStringMapKey(m map[string]string) string {
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)

i := f.IntBetween(0, len(keys)-1)
return keys[i]
Expand All @@ -260,6 +262,7 @@ func (f Faker) RandomStringMapValue(m map[string]string) string {
for k := range m {
values = append(values, m[k])
}
sort.Strings(values)

i := f.IntBetween(0, len(values)-1)
return values[i]
Expand Down Expand Up @@ -365,7 +368,7 @@ func (f Faker) Map() map[string]interface{} {
}

randSlice := func() []string {
var sl []string
sl := make([]string, 0, 10)
for ii := 0; ii < f.IntBetween(3, 10); ii++ {
sl = append(sl, lorem.Word())
}
Expand Down
25 changes: 14 additions & 11 deletions internet.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,11 @@ type Internet struct {
Faker *Faker
}

var validEmailOnlyValidCharacters = regexp.MustCompile(`[^a-z0-9._%+\-]+`)

func (Internet) transformIntoValidEmailName(name string) string {
name = strings.ToLower(name)
onlyValidCharacters := regexp.MustCompile(`[^a-z0-9._%+\-]+`)
name = onlyValidCharacters.ReplaceAllString(name, "_")
name = validEmailOnlyValidCharacters.ReplaceAllString(name, "_")
return name
}

Expand Down Expand Up @@ -155,38 +156,40 @@ func (i Internet) URL() string {

// Ipv4 returns a fake ipv4 for Internet
func (i Internet) Ipv4() string {
ips := []string{}
ips := make([]string, 0, 4)

for j := 0; j < 4; j++ {
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(1, 255)))
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(1, 255)))
for j := 0; j < 3; j++ {
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(0, 255)))
}

return strings.Join(ips, ".")
}

// LocalIpv4 returns a fake local ipv4 for Internet
func (i Internet) LocalIpv4() string {
ips := []string{i.Faker.RandomStringElement([]string{"10", "172", "192"})}
ips := make([]string, 0, 4)
ips = append(ips, i.Faker.RandomStringElement([]string{"10", "172", "192"}))

if ips[0] == "10" {
for j := 0; j < 3; j++ {
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(1, 255)))
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(0, 255)))
}
}

if ips[0] == "172" {
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(16, 31)))

for j := 0; j < 2; j++ {
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(1, 255)))
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(0, 255)))
}
}

if ips[0] == "192" {
ips = append(ips, "168")

for j := 0; j < 2; j++ {
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(1, 255)))
ips = append(ips, strconv.Itoa(i.Faker.IntBetween(0, 255)))
}
}

Expand All @@ -195,7 +198,7 @@ func (i Internet) LocalIpv4() string {

// Ipv6 returns a fake ipv6 for Internet
func (i Internet) Ipv6() string {
ips := []string{}
ips := make([]string, 0, 8)

for j := 0; j < 8; j++ {
block := ""
Expand All @@ -213,7 +216,7 @@ func (i Internet) Ipv6() string {
func (i Internet) MacAddress() string {
values := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"}

mac := []string{}
mac := make([]string, 0, 6)
for j := 0; j < 6; j++ {
m := i.Faker.RandomStringElement(values)
m = m + i.Faker.RandomStringElement(values)
Expand Down
15 changes: 9 additions & 6 deletions lorem.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ func (l Lorem) Word() string {
}

// Words returns fake words for Lorem
func (l Lorem) Words(nbWords int) (words []string) {
func (l Lorem) Words(nbWords int) []string {
words := make([]string, 0, nbWords)
for i := 0; i < nbWords; i++ {
words = append(words, l.Word())
}

return
return words
}

// Sentence returns a fake sentence for Lorem
Expand All @@ -32,12 +33,13 @@ func (l Lorem) Sentence(nbWords int) string {
}

// Sentences returns fake sentences for Lorem
func (l Lorem) Sentences(nbSentences int) (sentences []string) {
func (l Lorem) Sentences(nbSentences int) []string {
sentences := make([]string, 0, nbSentences)
for i := 0; i < nbSentences; i++ {
sentences = append(sentences, l.Sentence(l.Faker.RandomNumber(2)))
}

return
return sentences
}

// Paragraph returns a fake paragraph for Lorem
Expand All @@ -46,12 +48,13 @@ func (l Lorem) Paragraph(nbSentences int) string {
}

// Paragraphs returns fake paragraphs for Lorem
func (l Lorem) Paragraphs(nbParagraph int) (out []string) {
func (l Lorem) Paragraphs(nbParagraph int) []string {
out := make([]string, 0, nbParagraph)
for i := 0; i < nbParagraph; i++ {
out = append(out, l.Paragraph(l.Faker.RandomNumber(2)))
}

return
return out
}

// Text returns a fake text for Lorem
Expand Down
31 changes: 23 additions & 8 deletions person.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"strconv"
"strings"
"sync"
)

var (
Expand Down Expand Up @@ -114,6 +115,20 @@ var (
suffix = []string{"Jr.", "Sr.", "I", "II", "III", "IV", "V", "MD", "DDS", "PhD", "DVM"}
)

var (
cacheFirstNames []string
cacheFirstNamesOnce sync.Once
cacheFirstNamesFunc = func() {
cacheFirstNames = append(firstNameMale, firstNameFemale...)
}

cacheNameFormats []string
cacheNameFormatsOnce sync.Once
cacheNameFormatsFunc = func() {
cacheNameFormats = append(maleNameFormats, femaleNameFormats...)
}
)

// Person is a faker struct for Person
type Person struct {
Faker *Faker
Expand Down Expand Up @@ -173,8 +188,8 @@ func (p Person) FirstNameFemale() string {

// FirstName returns a fake first name for Person
func (p Person) FirstName() string {
names := append(firstNameMale, firstNameFemale...)
return p.Faker.RandomStringElement(names)
cacheFirstNamesOnce.Do(cacheFirstNamesFunc)
return p.Faker.RandomStringElement(cacheFirstNames)
}

// LastName returns a fake last name for Person
Expand All @@ -185,25 +200,25 @@ func (p Person) LastName() string {

// Name returns a fake name for Person
func (p Person) Name() string {
formats := append(maleNameFormats, femaleNameFormats...)
name := formats[p.Faker.IntBetween(0, len(formats)-1)]
cacheNameFormatsOnce.Do(cacheNameFormatsFunc)
name := cacheNameFormats[p.Faker.IntBetween(0, len(cacheNameFormats)-1)]

// {{titleMale}}
name = strings.Replace(name, "{{titleMale}}", p.TitleMale(), 1)

//{{firstNameMale}}
// {{firstNameMale}}
name = strings.Replace(name, "{{firstNameMale}}", p.FirstNameMale(), 1)

// {{titleFemale}}
name = strings.Replace(name, "{{titleFemale}}", p.TitleFemale(), 1)

//{{firstNameFemale}}
// {{firstNameFemale}}
name = strings.Replace(name, "{{firstNameFemale}}", p.FirstNameFemale(), 1)

//{{lastName}}
// {{lastName}}
name = strings.Replace(name, "{{lastName}}", p.LastName(), 1)

//{{suffix}}
// {{suffix}}
name = strings.Replace(name, "{{suffix}}", p.Suffix(), 1)

return name
Expand Down
18 changes: 14 additions & 4 deletions pet.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
package faker

import "sync"

var (
dogNames = []string{"Alfie", "Archie", "Bailey", "Banjo", "Barney", "Baxter", "Bear", "Beau", "Bella", "Benji", "Bentley", "Billie", "Billy", "Bonnie", "Bruce", "Bruno", "Buddy", "Buster", "Charlie", "Chester", "Chilli", "Chloe", "Cleo", "Coco", "Cookie", "Cooper", "Daisy", "Dexter", "Diesel", "Duke", "Ella", "Ellie", "Frankie", "George", "Gus", "Harley", "Harry", "Harvey", "Henry", "Holly", "Honey", "Hugo", "Jack", "Jasper", "Jax", "Jessie", "Jet", "Leo", "Lexi", "Lilly", "Lily", "Loki", "Lola", "Louie", "Louis", "Lucky", "Lucy", "Lulu", "Luna", "Maggie", "Marley", "Max", "Mia", "Millie", "Milly", "Milo", "Missy", "Molly", "Monty", "Murphy", "Nala", "Ollie", "Oscar", "Penny", "Pepper", "Pippa", "Poppy", "Ralph", "Rex", "Rocky", "Rosie", "Roxy", "Ruby", "Rusty", "Sam", "Sasha", "Scout", "Shadow", "Simba", "Sophie", "Stella", "Teddy", "Tilly", "Toby", "Willow", "Winston", "Zeus", "Ziggy", "Zoe"}
catNames = []string{"Bella", "Tigger", "Chloe", "Shadow", "Luna", "Oreo", "Oliver", "Kitty", "Lucy", "Molly", "Jasper", "Smokey", "Gizmo", "Simba", "Tiger", "Charlie", "Angel", "Jack", "Lily", "Peanut", "Toby", "Baby", "Loki", "Midnight", "Milo", "Princess", "Sophie", "Harley", "Max", "Missy", "Rocky", "Zoe", "CoCo", "Misty", "Nala", "Oscar", "Pepper", "Sasha", "Buddy", "Pumpkin", "Kiki", "Mittens", "Bailey", "Callie", "Lucky", "Patches", "Simon", "Garfield", "George", "Maggie", "Sammy", "Sebastian", "Boots", "Cali", "Felix", "Lilly", "Phoebe", "Sassy", "Tucker", "Bandit", "Dexter", "Fiona", "Jake", "Precious", "Romeo", "Snickers", "Socks", "Daisy", "Gracie", "Lola", "Sadie", "Sox", "Casper", "Fluffy", "Marley", "Minnie", "Sweetie", "Ziggy", "Belle", "Blackie", "Chester", "Frankie", "Ginger", "Muffin", "Murphy", "Rusty", "Scooter", "Batman", "Boo", "Cleo", "Izzy", "Jasmine", "Mimi", "Sugar", "Cupcake", "Dusty", "Leo", "Noodle", "Panda", "Peaches"}
)

var (
cachePetNames []string
cachePetNamesOnce sync.Once
cachePetNamesFunc = func() {
cachePetNames = make([]string, 0, len(catNames)+len(dogNames))
cachePetNames = append(cachePetNames, catNames...)
cachePetNames = append(cachePetNames, dogNames...)
}
)

// Pet is a faker struct for Pet
type Pet struct {
Faker *Faker
Expand All @@ -22,8 +34,6 @@ func (p Pet) Cat() string {

// Name returns a fake pet name for App
func (p Pet) Name() string {
petNames := []string{}
petNames = append(petNames, catNames...)
petNames = append(petNames, dogNames...)
return p.Faker.RandomStringElement(petNames)
cachePetNamesOnce.Do(cachePetNamesFunc)
return p.Faker.RandomStringElement(cachePetNames)
}
22 changes: 16 additions & 6 deletions user_agent.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package faker

import "sync"

var (
internetExplorerUserAgents = []string{
"Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Geckoe$",
Expand Down Expand Up @@ -4279,6 +4281,18 @@ var (
}
)

var (
cacheUserAgents []string
cacheUserAgentsOnce sync.Once
cacheUserAgentsFunc = func() {
cacheUserAgents = make([]string, 0, len(chromeUserAgents)+len(firefoxUserAgents)+len(operaUserAgents)+len(safariUserAgents))
cacheUserAgents = append(cacheUserAgents, chromeUserAgents...)
cacheUserAgents = append(cacheUserAgents, firefoxUserAgents...)
cacheUserAgents = append(cacheUserAgents, operaUserAgents...)
cacheUserAgents = append(cacheUserAgents, safariUserAgents...)
}
)

// UserAgent is a faker struct for UserAgent
type UserAgent struct {
Faker *Faker
Expand Down Expand Up @@ -4311,10 +4325,6 @@ func (u UserAgent) Safari() string {

// UserAgent returns a fake browser user agent for Internet
func (u UserAgent) UserAgent() string {
userAgents := []string{}
userAgents = append(userAgents, chromeUserAgents...)
userAgents = append(userAgents, firefoxUserAgents...)
userAgents = append(userAgents, operaUserAgents...)
userAgents = append(userAgents, safariUserAgents...)
return u.Faker.RandomStringElement(userAgents)
cacheUserAgentsOnce.Do(cacheUserAgentsFunc)
return u.Faker.RandomStringElement(cacheUserAgents)
}

0 comments on commit 190b989

Please sign in to comment.