From 0328f159d6f2cbe8b87468ff88f631b0d4d16953 Mon Sep 17 00:00:00 2001 From: Albert Nigmatzianov Date: Wed, 5 Apr 2017 10:32:46 +0200 Subject: Cache sorted flags As you can't delete flags in FlagSet, this method works Gainful performance improvement: benchmark old ns/op new ns/op delta BenchmarkVisitAll10Flags-4 1549 33.9 -97.81% BenchmarkVisit10Flags-4 1704 34.2 -97.99% benchmark old allocs new allocs delta BenchmarkVisitAll10Flags-4 3 0 -100.00% BenchmarkVisit10Flags-4 3 0 -100.00% benchmark old bytes new bytes delta BenchmarkVisitAll10Flags-4 272 0 -100.00% BenchmarkVisit10Flags-4 272 0 -100.00% --- flag.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/flag.go b/flag.go index 3a2e255..2bfedff 100644 --- a/flag.go +++ b/flag.go @@ -142,8 +142,10 @@ type FlagSet struct { parsed bool actual map[NormalizedName]*Flag orderedActual []*Flag + sortedActual []*Flag formal map[NormalizedName]*Flag orderedFormal []*Flag + sortedFormal []*Flag shorthands map[byte]*Flag args []string // arguments after flags argsLenAtDash int // len(args) when a '--' was located when parsing, or -1 if no -- @@ -200,6 +202,7 @@ func sortFlags(flags map[NormalizedName]*Flag) []*Flag { // "--getUrl" which may also be translated to "geturl" and everything will work. func (f *FlagSet) SetNormalizeFunc(n func(f *FlagSet, name string) NormalizedName) { f.normalizeNameFunc = n + f.sortedFormal = f.sortedFormal[:0] for k, v := range f.orderedFormal { delete(f.formal, NormalizedName(v.Name)) nname := f.normalizeFlagName(v.Name) @@ -240,9 +243,16 @@ func (f *FlagSet) SetOutput(output io.Writer) { // in primordial order if f.SortFlags is false, calling fn for each. // It visits all flags, even those not set. func (f *FlagSet) VisitAll(fn func(*Flag)) { + if len(f.formal) == 0 { + return + } + var flags []*Flag if f.SortFlags { - flags = sortFlags(f.formal) + if len(f.formal) != len(f.sortedFormal) { + f.sortedFormal = sortFlags(f.formal) + } + flags = f.sortedFormal } else { flags = f.orderedFormal } @@ -279,9 +289,16 @@ func VisitAll(fn func(*Flag)) { // in primordial order if f.SortFlags is false, calling fn for each. // It visits only those flags that have been set. func (f *FlagSet) Visit(fn func(*Flag)) { + if len(f.actual) == 0 { + return + } + var flags []*Flag if f.SortFlags { - flags = sortFlags(f.actual) + if len(f.actual) != len(f.sortedActual) { + f.sortedActual = sortFlags(f.actual) + } + flags = f.sortedActual } else { flags = f.orderedActual } -- cgit v1.2.3