Skip to content

Commit

Permalink
Memoise calls to fullyQualifiedNameToSwaggerName to speed it up for l…
Browse files Browse the repository at this point in the history
…arge registries (#421)

Memoise calls to fullyQualifiedNameToSwaggerName for all registries ever seen instead of just the last one.
  • Loading branch information
peterebden authored and achew22 committed Jul 24, 2017
1 parent 1a03ca3 commit f2862b4
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 4 deletions.
19 changes: 16 additions & 3 deletions protoc-gen-swagger/genswagger/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"regexp"
"strconv"
"strings"
"sync"

pbdescriptor "github.com/golang/protobuf/protoc-gen-go/descriptor"
"github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway/descriptor"
Expand Down Expand Up @@ -329,17 +330,29 @@ func renderEnumerationsAsDefinition(enums enumMap, d swaggerDefinitionsObject, r

// Take in a FQMN or FQEN and return a swagger safe version of the FQMN
func fullyQualifiedNameToSwaggerName(fqn string, reg *descriptor.Registry) string {
return resolveFullyQualifiedNameToSwaggerName(fqn, append(reg.GetAllFQMNs(), reg.GetAllFQENs()...))
registriesSeenMutex.Lock()
defer registriesSeenMutex.Unlock()
if mapping, present := registriesSeen[reg]; present {
return mapping[fqn]
}
mapping := resolveFullyQualifiedNameToSwaggerNames(append(reg.GetAllFQMNs(), reg.GetAllFQENs()...))
registriesSeen[reg] = mapping
return mapping[fqn]
}

// registriesSeen is used to memoise calls to resolveFullyQualifiedNameToSwaggerNames so
// we don't repeat it unnecessarily, since it can take some time.
var registriesSeen = map[*descriptor.Registry]map[string]string{}
var registriesSeenMutex sync.Mutex

// Take the names of every proto and "uniq-ify" them. The idea is to produce a
// set of names that meet a couple of conditions. They must be stable, they
// must be unique, and they must be shorter than the FQN.
//
// This likely could be made better. This will always generate the same names
// but may not always produce optimal names. This is a reasonably close
// approximation of what they should look like in most cases.
func resolveFullyQualifiedNameToSwaggerName(fqn string, messages []string) string {
func resolveFullyQualifiedNameToSwaggerNames(messages []string) map[string]string {
packagesByDepth := make(map[int][][]string)
uniqueNames := make(map[string]string)

Expand Down Expand Up @@ -379,7 +392,7 @@ func resolveFullyQualifiedNameToSwaggerName(fqn string, messages []string) strin
}
}
}
return uniqueNames[fqn]
return uniqueNames
}

// Swagger expects paths of the form /path/{string_value} but grpc-gateway paths are expected to be of the form /path/{string_value=strprefix/*}. This should reformat it correctly.
Expand Down
3 changes: 2 additions & 1 deletion protoc-gen-swagger/genswagger/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -758,7 +758,8 @@ func TestResolveFullyQualifiedNameToSwaggerName(t *testing.T) {
}

for _, data := range tests {
output := resolveFullyQualifiedNameToSwaggerName(data.input, data.listOfFQMNs)
names := resolveFullyQualifiedNameToSwaggerNames(data.listOfFQMNs)
output := names[data.input]
if output != data.output {
t.Errorf("Expected fullyQualifiedNameToSwaggerName(%v) to be %s but got %s",
data.input, data.output, output)
Expand Down

0 comments on commit f2862b4

Please sign in to comment.