Skip to content

Commit

Permalink
Merge pull request #600 from tdakkota/perf/optimize-name-rules
Browse files Browse the repository at this point in the history
perf(naming): use hashmap to search naming rules
  • Loading branch information
ernado authored Oct 3, 2022
2 parents ec7503c + c18a232 commit 86f0d9f
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 37 deletions.
4 changes: 2 additions & 2 deletions gen/ir/description.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"unicode"
"unicode/utf8"

"github.com/ogen-go/ogen/internal/capitalize"
"github.com/ogen-go/ogen/internal/naming"
)

func splitLine(s string, limit int) (r []string) {
Expand Down Expand Up @@ -49,7 +49,7 @@ func prettyDoc(s, deprecation string) (r []string) {
r = append(r, splitLine(line, lineLimit)...)
}
if len(r) > 0 {
r[0] = capitalize.Capitalize(r[0])
r[0] = naming.Capitalize(r[0])

if last := r[len(r)-1]; len(last) > 0 && last[len(last)-1] != '.' {
r[len(r)-1] = last + "."
Expand Down
4 changes: 2 additions & 2 deletions gen/ir/description_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

"github.com/stretchr/testify/require"

"github.com/ogen-go/ogen/internal/capitalize"
"github.com/ogen-go/ogen/internal/naming"
)

func Test_prettyDoc(t *testing.T) {
Expand Down Expand Up @@ -65,7 +65,7 @@ func Test_prettyDoc(t *testing.T) {
{
input: strings.Repeat("a", lineLimit-4) + string(rune(12288)) + strings.Repeat("a", 10),
wantR: []string{
capitalize.Capitalize(strings.Repeat("a", lineLimit-4)),
naming.Capitalize(strings.Repeat("a", lineLimit-4)),
strings.Repeat("a", 10) + ".",
},
},
Expand Down
8 changes: 4 additions & 4 deletions gen/ir/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"sort"
"strings"

"github.com/ogen-go/ogen/internal/capitalize"
"github.com/ogen-go/ogen/internal/naming"
"github.com/ogen-go/ogen/jsonschema"
)

Expand Down Expand Up @@ -124,7 +124,7 @@ func (j JSON) Format() string {
typePrefix := func(f string) string {
switch s.Type {
case jsonschema.String:
return "String" + capitalize.Capitalize(f)
return "String" + naming.Capitalize(f)
default:
return f
}
Expand Down Expand Up @@ -156,7 +156,7 @@ func (j JSON) Format() string {
if s.Type != jsonschema.String {
return ""
}
return "String" + capitalize.Capitalize(f)
return "String" + naming.Capitalize(f)
case "unix", "unix-seconds":
return typePrefix("UnixSeconds")
case "unix-nano":
Expand Down Expand Up @@ -290,7 +290,7 @@ func (j JSON) Fn() string {
s := j.t.Primitive.String()
return strings.ToUpper(s[:2]) + s[2:]
default:
return capitalize.Capitalize(j.t.Primitive.String())
return naming.Capitalize(j.t.Primitive.String())
}
}

Expand Down
8 changes: 4 additions & 4 deletions gen/ir/template_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"strings"

"github.com/ogen-go/ogen/internal/capitalize"
"github.com/ogen-go/ogen/internal/naming"
"github.com/ogen-go/ogen/jsonschema"
)

Expand All @@ -27,7 +27,7 @@ func (t *Type) EncodeFn() string {
Uint, Uint8, Uint16, Uint32, Uint64,
Float32, Float64,
String, Bool:
return capitalize.Capitalize(t.Primitive.String())
return naming.Capitalize(t.Primitive.String())
case UUID, Time, IP, Duration, URL:
return afterDot(t.Primitive.String())
default:
Expand All @@ -39,7 +39,7 @@ func (t Type) uriFormat() string {
if s := t.Schema; s != nil {
switch f := s.Format; f {
case "time", "date":
return capitalize.Capitalize(f)
return naming.Capitalize(f)
case "date-time":
return "DateTime"
case "int8",
Expand All @@ -54,7 +54,7 @@ func (t Type) uriFormat() string {
if s.Type != jsonschema.String {
break
}
return "String" + capitalize.Capitalize(f)
return "String" + naming.Capitalize(f)
case "unix", "unix-seconds":
return "UnixSeconds"
case "unix-nano":
Expand Down
6 changes: 3 additions & 3 deletions gen/ir/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"regexp"
"strings"

"github.com/ogen-go/ogen/internal/capitalize"
"github.com/ogen-go/ogen/internal/naming"
"github.com/ogen-go/ogen/jsonschema"
)

Expand Down Expand Up @@ -177,7 +177,7 @@ func (t *Type) NamePostfix() string {
typePrefix := func(f string) string {
switch s.Type {
case jsonschema.String:
return "String" + capitalize.Capitalize(f)
return "String" + naming.Capitalize(f)
default:
return f
}
Expand Down Expand Up @@ -205,7 +205,7 @@ func (t *Type) NamePostfix() string {
if s.Type != jsonschema.String {
return t.Primitive.String()
}
return "String" + capitalize.Capitalize(f)
return "String" + naming.Capitalize(f)
case "unix", "unix-seconds":
return typePrefix("UnixSeconds")
case "unix-nano":
Expand Down
20 changes: 4 additions & 16 deletions gen/names.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"unicode"

"github.com/go-faster/errors"

"github.com/ogen-go/ogen/internal/naming"
)

func cleanRef(ref string) string {
Expand Down Expand Up @@ -147,23 +149,9 @@ func (g *nameGen) isAllowed(r rune) bool {
}

func (g *nameGen) checkPart(part string) string {
rules := []string{
"ACL", "API", "ASCII", "AWS", "CPU", "CSS", "DNS", "EOF", "GB", "GUID",
"HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "KB", "LHS", "MAC", "MB",
"QPS", "RAM", "RHS", "RPC", "SLA", "SMTP", "SQL", "SSH", "SSO", "TCP",
"TLS", "TTL", "UDP", "UI", "UID", "URI", "URL", "UTF8", "UUID", "VM",
"XML", "XMPP", "XSRF", "XSS", "SMS", "CDN", "TCP", "UDP", "DC", "PFS",
"P2P", "SHA256", "SHA1", "MD5", "SRP", "2FA", "OAuth", "OAuth2",

"PNG", "JPG", "GIF", "MP4", "WEBP",
if rule, ok := naming.Rule(part); ok {
return rule
}

for _, rule := range rules {
if strings.EqualFold(part, rule) {
return rule
}
}

return part
}

Expand Down
4 changes: 2 additions & 2 deletions gen/schema_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"go.uber.org/zap"

"github.com/ogen-go/ogen/gen/ir"
"github.com/ogen-go/ogen/internal/capitalize"
"github.com/ogen-go/ogen/internal/naming"
"github.com/ogen-go/ogen/jsonschema"
)

Expand Down Expand Up @@ -44,7 +44,7 @@ func newSchemaGen(filename string, lookupRef func(ref string) (*ir.Type, bool))
}

func variantFieldName(t *ir.Type) string {
return capitalize.Capitalize(t.NamePostfix())
return naming.Capitalize(t.NamePostfix())
}

func (g *schemaGen) generate(name string, schema *jsonschema.Schema, optional bool) (*ir.Type, error) {
Expand Down
4 changes: 2 additions & 2 deletions gen/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"github.com/go-faster/errors"

"github.com/ogen-go/ogen/gen/ir"
"github.com/ogen-go/ogen/internal/capitalize"
"github.com/ogen-go/ogen/internal/naming"
)

// RouterElem is variable helper for router generation.
Expand Down Expand Up @@ -69,7 +69,7 @@ func templateFunctions() template.FuncMap {
},
"pascalSpecial": pascalSpecial,
"camelSpecial": camelSpecial,
"capitalize": capitalize.Capitalize,
"capitalize": naming.Capitalize,
"upper": strings.ToUpper,

// Helpers for recursive encoding and decoding.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// Package capitalize contains capitalize function.
package capitalize
package naming

import (
"unicode"
Expand Down
2 changes: 2 additions & 0 deletions internal/naming/naming.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package naming contains some utilities for generating names.
package naming
37 changes: 37 additions & 0 deletions internal/naming/rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package naming

import (
"strings"
)

var (
rules = [...]string{
"ACL", "API", "ASCII", "AWS", "CPU", "CSS", "DNS", "EOF", "GB", "GUID",
"HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "KB", "LHS", "MAC", "MB",
"QPS", "RAM", "RHS", "RPC", "SLA", "SMTP", "SQL", "SSH", "SSO", "TLS",
"TTL", "UI", "UID", "URI", "URL", "UTF8", "UUID", "VM", "XML", "XMPP",
"XSRF", "XSS", "SMS", "CDN", "TCP", "UDP", "DC", "PFS", "P2P",
"SHA256", "SHA1", "MD5", "SRP", "2FA", "OAuth", "OAuth2",

"PNG", "JPG", "GIF", "MP4", "WEBP",
}
// rulesMap is a map of lowered rules to their canonical form.
//
// NOTE: we're using a map instead of a linear/binary search because
// lowered string allocation is much cheaper than string comparison.
// Also, ToLower doesn't allocate if the string is already in lower case.
rulesMap = func() (r map[string]string) {
r = make(map[string]string)
for _, v := range rules {
r[strings.ToLower(v)] = v
}
return r
}()
)

// Rule returns the rule for the given part, if any.
// Otherwise, it returns ("", false).
func Rule(part string) (string, bool) {
v, ok := rulesMap[strings.ToLower(part)]
return v, ok
}
77 changes: 77 additions & 0 deletions internal/naming/rules_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package naming

import (
"strings"
"testing"

"github.com/stretchr/testify/require"
)

func TestRule(t *testing.T) {
a := require.New(t)
for _, rule := range rules {
testFind := func(key string) {
v, ok := Rule(key)
a.True(ok)
a.Equal(rule, v)
}
testFind(rule)
testFind(strings.ToLower(rule))
testFind(strings.ToUpper(rule))
testFind(strings.ToLower(rule[:1]) + rule[1:])
}
}

func BenchmarkRule(b *testing.B) {
suite := [...]string{
"wifi",
"WiFi",
"ASCII",
"mp3",
"Oauth",
"WebP",
"JPEG",
}

b.Run("Rule", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()

var (
v string
ok bool
)
for i := 0; i < b.N; i++ {
rule := suite[i%len(suite)]
v, ok = Rule(rule)
}
if ok && v == "" {
b.Fatal("sink is empty")
}
})

linear := func(s string) (string, bool) {
for _, rule := range &rules {
if strings.EqualFold(s, rule) {
return rule, true
}
}
return "", false
}
b.Run("LinearSearch", func(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()

var (
v string
ok bool
)
for i := 0; i < b.N; i++ {
rule := suite[i%len(suite)]
v, ok = linear(rule)
}
if ok && v == "" {
b.Fatal("sink is empty")
}
})
}

0 comments on commit 86f0d9f

Please sign in to comment.