Change:
/kind bug What happened: takes ~11 seconds when there are thousands of CRDs and is around 28KiB. logs the following message once per resource: Removing unnecessary entries from reduces the runtime by around ten seconds. What you expected to happen: only parses once, and therefore doesn't run unnecessarily slowly. How to reproduce it (as minimally and precisely as possible): shows the config being loaded multiple times (assuming you have multiple pods in the current cluster). Alternatively, add 10-15 clusters to and create ~3000 of a cheap resource (eg custom resources or empty config maps). Run on this resource and observe that it is unnecessarily slow. Anything else we need to know?: I've created a CPU profile using the latest CI build of kubectl, which shows ~12 seconds being spent in . Environment: Kubernetes version (use ): v1.12.1 (also Cloud provider or hardware configuration: GKE or minikube --vm-driver=none OS (e.g. from /etc/os-release): Debian Buster-like Kernel (e.g. ): 4.17.0
/sig cli
/assign
Same problem here. I have less resources but more contexts in my kubeconfig file. With 90 pods and ~300 contexts in the kubeconfig it also takes ~10 seconds for a simple kubectl get pods Note: I tried it with kubectl: 1.11.0, 1.12. With kubectl 1.10.5 the kubeconfig was loaded only once.
I'm unable to reproduce this as of the latest master. My kubeconfig is only loaded 4 times, no matter how many resources are loaded.
When I try a kubectl v1.13.0-alpha.3 against unfortunately a 1.9.11 Kubernetes Cluster I still have the problem: `
Maybe the bug is Linux-only? Presumably the kubeconfig location is different on different platforms, so maybe it has a different code path. I can repro on latest master:
I filed to fixed this. You can try to help validate it. Thanks.
Works for me, thanks!

Discussion:
addProfilingFlags(flags) <del> kubeConfigFlags := genericclioptions.NewConfigFlags() </del> <ins> kubeConfigFlags := genericclioptions.NewConfigFlags(true) </ins> kubeConfigFlags.AddFlags(flags) matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags) matchVersionKubeConfigFlags.AddFlags(cmds.PersistentFlags())

"path/filepath" "regexp" "strings" <ins> "sync" </ins> "time" "github.com/spf13/pflag"

Username         *string Password         *string Timeout          *string <ins> clientConfig clientcmd.ClientConfig lock         sync.Mutex // If set to true, will use persistent client config and // propagate the config to the places that need it, rather than // loading the config multiple times usePersistentConfig bool </ins> } // ToRESTConfig implements RESTClientGetter.

// Returns an interactive clientConfig if the password flag is enabled, // or a non-interactive clientConfig otherwise. func (f *ConfigFlags) ToRawKubeConfigLoader() clientcmd.ClientConfig { <ins> if f.usePersistentConfig { return f.toRawKubePersistentConfigLoader() } return f.toRawKubeConfigLoader() } func (f *ConfigFlags) toRawKubeConfigLoader() clientcmd.ClientConfig { </ins> loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() // use the standard defaults for this client command // DEPRECATED: remove and replace with something more accurate

return clientConfig } <ins> // toRawKubePersistentConfigLoader binds config flag values to config overrides // Returns a persistent clientConfig for propagation. func (f *ConfigFlags) toRawKubePersistentConfigLoader() clientcmd.ClientConfig { f.lock.Lock() defer f.lock.Unlock() if f.clientConfig == nil { f.clientConfig = f.toRawKubeConfigLoader() } return f.clientConfig } </ins> // ToDiscoveryClient implements RESTClientGetter. // Expects the AddFlags method to have been called. // Returns a CachedDiscoveryInterface using a computed RESTConfig.

} // NewConfigFlags returns ConfigFlags with default values set <del> func NewConfigFlags() *ConfigFlags { </del> <ins> func NewConfigFlags(usePersistentConfig bool) *ConfigFlags { </ins> impersonateGroup := []string{} insecure := false

BearerToken:      stringptr(""), Impersonate:      stringptr(""), ImpersonateGroup: &impersonateGroup, <ins> usePersistentConfig: usePersistentConfig, </ins> } }

// NewNamespaceOptions provides an instance of NamespaceOptions with default values func NewNamespaceOptions(streams genericclioptions.IOStreams) *NamespaceOptions { return &NamespaceOptions{ <del> configFlags: genericclioptions.NewConfigFlags(), </del> <ins> configFlags: genericclioptions.NewConfigFlags(true), </ins> IOStreams: streams, }