Skip to content

Commit d7951e2

Browse files
xaionaro@dx.centerxaionaro@dx.center
authored andcommitted
perf(bindercli): defer generated command registration until needed
Built-in commands (service, aidl, camera) and --help no longer pay the cost of constructing thousands of generated cobra commands at startup. Generated commands are only registered on retry when the first execution attempt returns an "unknown command" error. Before: ~47ms for --help, ~46ms for service --help (x86) After: ~6ms for --help, ~7ms for service --help (x86)
1 parent c266563 commit d7951e2

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

cmd/bindercli/main.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package main
22

33
import (
44
"fmt"
5+
"io"
56
"os"
67
"runtime/pprof"
8+
"strings"
79

810
"github.com/facebookincubator/go-belt"
911
"github.com/facebookincubator/go-belt/tool/logger"
@@ -109,13 +111,44 @@ and invoking Android Binder services using AIDL-generated Go bindings.`,
109111
cmd.AddCommand(newServiceCmd())
110112
cmd.AddCommand(newAIDLCmd())
111113
cmd.AddCommand(newCameraCmd())
112-
addGeneratedCommands(cmd)
113114

114115
return cmd
115116
}
116117

118+
// isUnknownCommandError reports whether err is cobra's "unknown command" error,
119+
// which means the user invoked a subcommand that doesn't exist yet (likely a
120+
// generated proxy command that hasn't been registered).
121+
func isUnknownCommandError(err error) bool {
122+
return err != nil && strings.HasPrefix(err.Error(), "unknown command ")
123+
}
124+
117125
func main() {
118-
if err := newRootCmd().Execute(); err != nil {
126+
// Phase 1: try executing with only the lightweight built-in commands
127+
// (service, aidl, camera). Suppress cobra's error output so that an
128+
// "unknown command" failure for a generated proxy command is invisible.
129+
// Stdout is left alone so --help and normal command output still work.
130+
cmd := newRootCmd()
131+
cmd.SilenceErrors = true
132+
cmd.SilenceUsage = true
133+
cmd.SetErr(io.Discard)
134+
135+
err := cmd.Execute()
136+
switch {
137+
case err == nil:
138+
return
139+
case isUnknownCommandError(err):
140+
// Phase 2: the user invoked a generated command. Register all
141+
// generated commands and retry with normal output.
142+
addGeneratedCommands(cmd)
143+
cmd.SilenceErrors = false
144+
cmd.SilenceUsage = false
145+
cmd.SetErr(os.Stderr)
146+
if err := cmd.Execute(); err != nil {
147+
os.Exit(1)
148+
}
149+
default:
150+
// A built-in command failed. Print the error ourselves since
151+
// cobra's error printing was silenced for phase 1.
119152
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
120153
os.Exit(1)
121154
}

0 commit comments

Comments
 (0)