When goa generates server code for query parameters, it checks each parameter one after another with code that looks something like this:
advRaw := r.URL.Query().Get("adv")
if advRaw != "" {
adv = &advRaw
}
afRaw := r.URL.Query().Get("af")
if afRaw != "" {
af = &afRaw
}
apbndlRaw := r.URL.Query().Get("apbndl")
if apbndlRaw != "" {
apbndl = &apbndlRaw
}
The problem with this code, is that r.URL.Query() is called repeatedly. Each call parses r.URL.RawQuery into a url.Values map. One values is pulled from the map, then the map is left to be garbage collected. It'd be much better to parse the query parameters once and store the result in a variable to be referenced for each query parameter to check.
In a test on one of our projects on an endpoint with many query parameters defined, this resulted in 24.11GB (41.4%) of heap allocations (using the alloc profile) coming from calls to url.(*URL).Query within the generated server.DecodeXXXXRequest.func1.
When goa generates server code for query parameters, it checks each parameter one after another with code that looks something like this:
The problem with this code, is that
r.URL.Query()
is called repeatedly. Each call parsesr.URL.RawQuery
into aurl.Values
map. One values is pulled from the map, then the map is left to be garbage collected. It'd be much better to parse the query parameters once and store the result in a variable to be referenced for each query parameter to check.In a test on one of our projects on an endpoint with many query parameters defined, this resulted in 24.11GB (41.4%) of heap allocations (using the alloc profile) coming from calls to
url.(*URL).Query
within the generatedserver.DecodeXXXXRequest.func1
.