Skip to content

Commit 1ffc041

Browse files
authored
use go:generate and stringer to replace maps with arrays for performance (#27)
* use go:generate and stringer to replace maps with arrays for performance * simplification * lint
1 parent 63e7039 commit 1ffc041

11 files changed

+148
-61
lines changed

.golangci.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ linters:
8484
enable:
8585
- megacheck
8686
- govet
87+
- exportloopref
88+
- errcheck
8789
enable-all: false
8890
disable:
8991
- maligned
@@ -92,6 +94,7 @@ linters:
9294
- funlen
9395
- gocognit
9496
- gocyclo
97+
- scopelint
9598
presets:
9699
- bugs
97100
- unused

Makefile

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
3+
all:
4+
go install golang.org/x/tools/...@latest
5+
go generate
6+
go test
7+
golangci-lint run

bind.go

-6
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,6 @@ func doBind(sc *Collection, originalInvokeF *provider, originalInitF *provider,
2121
if err != nil {
2222
return err
2323
}
24-
if invokeF.flows == nil {
25-
return fmt.Errorf("internal error #4: no flows for invoke")
26-
}
2724
nonStaticTypes := make(map[typeCode]bool)
2825
for _, tc := range invokeF.flows[outputParams] {
2926
nonStaticTypes[tc] = true
@@ -59,9 +56,6 @@ func doBind(sc *Collection, originalInvokeF *provider, originalInitF *provider,
5956
if err != nil {
6057
return err
6158
}
62-
if initF.flows == nil {
63-
return fmt.Errorf("internal error #5: no flows for initF")
64-
}
6559
funcs = append(funcs, initF)
6660
}
6761

characterize.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ type charContext struct {
1313
inputsAreStatic bool
1414
}
1515

16-
type flowMapType map[flowType][]typeCode
16+
type flowMapType [bypassParams + 1][]typeCode
1717

1818
type characterization struct {
1919
name string
@@ -525,7 +525,7 @@ Match:
525525
}
526526
a.fm.upRmap = make(map[typeCode]typeCode)
527527
a.fm.downRmap = make(map[typeCode]typeCode)
528-
a.fm.flows = make(flowMapType)
528+
a.fm.flows = [lastFlowType][]typeCode{}
529529
match.mutate(a)
530530
return a.fm, nil
531531
}

characterize_test.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ type doesJ struct {
5252
func (dj *doesJ) I() int { return dj.j * 3 }
5353

5454
func params() flowMapType {
55-
return make(flowMapType)
55+
return [bypassParams + 1][]typeCode{}
5656
}
5757

5858
func (flows flowMapType) returns(f ...typeCode) flowMapType {
@@ -185,21 +185,21 @@ var characterizeTests = []struct {
185185
func() {},
186186
injectorFunc,
187187
lastF, staticF, panicF,
188-
nil,
188+
params(),
189189
},
190190
{
191191
"cacheable notCacheable",
192192
Cacheable(NotCacheable(func() {})),
193193
injectorFunc,
194194
lastF, staticT, panicF,
195-
nil,
195+
params(),
196196
},
197197
{
198198
"cacheable notCacheable",
199199
Cacheable(NotCacheable(func() {})),
200200
injectorFunc,
201201
lastF, staticF, panicF,
202-
nil,
202+
params(),
203203
},
204204
{
205205
"minimal fallible injector",
@@ -244,14 +244,14 @@ var characterizeTests = []struct {
244244
func(int) func() { return func() {} },
245245
finalFunc,
246246
lastT, staticF, panicT,
247-
nil,
247+
params(),
248248
},
249249
{
250250
"invalid: anonymous func that isn't a wrap #2",
251251
func(func(), int) {},
252252
finalFunc,
253253
lastT, staticF, panicT,
254-
nil,
254+
params(),
255255
},
256256
{
257257
"middleware func",
@@ -296,14 +296,14 @@ var characterizeTests = []struct {
296296
&nadaFunc,
297297
invokeFunc,
298298
lastF, staticF, panicF,
299-
nil,
299+
params(),
300300
},
301301
{
302302
"init: nada",
303303
&nadaFunc,
304304
initFunc,
305305
lastF, staticT, panicF,
306-
nil,
306+
params(),
307307
},
308308
{
309309
"literal: int",
@@ -317,7 +317,7 @@ var characterizeTests = []struct {
317317
"foobar",
318318
literalValue,
319319
lastF, staticF, panicT,
320-
nil,
320+
params(),
321321
},
322322
}
323323

@@ -389,13 +389,13 @@ func TestCharacterize(t *testing.T) {
389389
}
390390
}
391391
for ft, ev := range test.flows {
392-
t.Logf("flow %s: %s", ft, een(ev))
393-
assert.EqualValues(t, een(ev), een(fm.flows[ft]), fmt.Sprintf("%s flow: %s", ft, test.name))
392+
t.Logf("flow %s: %s", flowType(ft), een(ev))
393+
assert.EqualValues(t, een(ev), een(fm.flows[ft]), fmt.Sprintf("%s flow: %s", flowType(ft), test.name))
394394
}
395395
for ft, gv := range fm.flows {
396396
if test.flows[ft] == nil {
397-
t.Logf("flow %s: %s", ft, een(gv))
398-
assert.EqualValues(t, een(test.flows[ft]), een(gv), fmt.Sprintf("%s flow %s", ft, test.name))
397+
t.Logf("flow %s: %s", flowType(ft), een(gv))
398+
assert.EqualValues(t, een(test.flows[ft]), een(gv), fmt.Sprintf("%s flow %s", flowType(ft), test.name))
399399
}
400400
}
401401
}

debug.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func dumpF(context string, fm *provider) {
132132
out += fmt.Sprintf("\n\tclass: %s\n\tgroup: %s", fm.class, fm.group)
133133
for name, flow := range fm.flows {
134134
if len(flow) > 0 {
135-
out += fmt.Sprintf("\n\t%s flow: %s", name, formatFlow(flow))
135+
out += fmt.Sprintf("\n\t%s flow: %s", flowType(name), formatFlow(flow))
136136
}
137137
}
138138
for upDown, rMap := range map[string]map[typeCode]typeCode{
@@ -168,7 +168,7 @@ func dumpF(context string, fm *provider) {
168168
}
169169
for param, users := range fm.d.usesDetail {
170170
for tc, dep := range users {
171-
out += fmt.Sprintf("\n\tUSES: %s (%s %s)", dep, param, tc)
171+
out += fmt.Sprintf("\n\tUSES: %s (%s %s)", dep, flowType(param), tc)
172172
}
173173
}
174174
for _, dep := range fm.d.usedBy {

generate.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,7 @@ func generateParameterMap(
3131
vmap map[typeCode]int, // map of types in valueCollection to their positions
3232
purpose string, // debug string
3333
) (parameterMap, error) {
34-
flow, found := fm.flows[param]
35-
if !found {
36-
return parameterMap{}, fm.errorf("internal error #12: flow %s missing", param)
37-
}
34+
flow := fm.flows[param]
3835
m := make([]int, len(flow))
3936
types := make([]reflect.Type, len(flow))
4037
for i, p := range flow {
@@ -380,6 +377,8 @@ func generateWrappers(
380377
case invokeFunc, initFunc, literalValue:
381378
// handled elsewhere
382379
return nil
380+
case unsetClassType:
381+
fallthrough
383382
default:
384383
return fmt.Errorf("internal error #11: unexpected class")
385384
}

include.go

+10-10
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import (
55
)
66

77
type includeWorkingData struct {
8-
usesDetail map[flowType]map[typeCode][]*provider
8+
usesDetail [lastFlowType]map[typeCode][]*provider
99
uses []*provider
10-
usesError map[flowType]map[typeCode]error
10+
usesError [lastFlowType]map[typeCode]error
1111
usedBy []*provider
12-
usedByDetail map[flowType]map[typeCode][]*provider
13-
mustConsumeFlow map[flowType]bool
12+
usedByDetail [lastFlowType]map[typeCode][]*provider
13+
mustConsumeFlow [lastFlowType]bool
1414
excluded error
1515
clusterMembers []*provider
1616
wantedInCluster bool
@@ -78,7 +78,7 @@ func computeDependenciesAndInclusion(funcs []*provider, initF *provider) error {
7878
fm.d.clusterMembers = []*provider{fm}
7979
}
8080
}
81-
fm.d.mustConsumeFlow = make(map[flowType]bool)
81+
fm.d.mustConsumeFlow = [lastFlowType]bool{}
8282
if fm.mustConsume {
8383
fm.d.mustConsumeFlow[outputParams] = true
8484
}
@@ -276,7 +276,7 @@ func checkFlows(funcs []*provider, numFuncs int, canRemoveDesired bool) error {
276276
debugf("\t\t\tcannot provide %s %s: %s: %s", param, tc, p, p.cannotInclude)
277277
extra = fmt.Sprintf(" (not provided by %s because %s)", p, p.cannotInclude)
278278
}
279-
fm.cannotInclude = fmt.Errorf("no provider for %s in %s%s", tc, param, extra)
279+
fm.cannotInclude = fmt.Errorf("no provider for %s in %s%s", tc, flowType(param), extra)
280280
redo = append(redo, fm)
281281
debugf("\t\tno source %s %s %s: %s", param, tc, fm, fm.cannotInclude)
282282
continue Todo
@@ -299,7 +299,7 @@ func checkFlows(funcs []*provider, numFuncs int, canRemoveDesired bool) error {
299299
debugf("\t\t\tcannot consume %s %s: %s: %s", param, tc, p, p.cannotInclude)
300300
extra = fmt.Sprintf(" (not consumed by %s because %s)", p, p.cannotInclude)
301301
}
302-
fm.cannotInclude = fmt.Errorf("no consumer for %s in %s%s", tc, param, extra)
302+
fm.cannotInclude = fmt.Errorf("no consumer for %s in %s%s", tc, flowType(param), extra)
303303
redo = append(redo, fm)
304304
debugf("\t\tnot consumed %s %s %s: %s", param, tc, fm, fm.cannotInclude)
305305
continue Todo
@@ -317,10 +317,10 @@ func checkFlows(funcs []*provider, numFuncs int, canRemoveDesired bool) error {
317317
func providesReturns(funcs []*provider, initF *provider) error {
318318
debugln("calculating provides/returns")
319319
for _, fm := range funcs {
320-
fm.d.usedByDetail = make(map[flowType]map[typeCode][]*provider)
321-
fm.d.usesDetail = make(map[flowType]map[typeCode][]*provider)
320+
fm.d.usedByDetail = [lastFlowType]map[typeCode][]*provider{}
321+
fm.d.usesDetail = [lastFlowType]map[typeCode][]*provider{}
322322
fm.d.uses = nil
323-
fm.d.usesError = make(map[flowType]map[typeCode]error)
323+
fm.d.usesError = [lastFlowType]map[typeCode]error{}
324324
fm.d.usedBy = nil
325325
}
326326
provide := make(interfaceMap)

nject.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ func (fm *provider) String() string {
162162
t = reflect.TypeOf(fm.fn).String()
163163
}
164164
class := ""
165-
if fm.class != "" {
166-
class = string(fm.class) + ": "
165+
if fm.class != unsetClassType {
166+
class = fm.class.String() + ": "
167167
}
168168
if fm.index >= 0 {
169169
return fmt.Sprintf("%s%s(%d) [%s]", class, fm.origin, fm.index, t)

stringer_generated.go

+75
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)