Merge pull request #38086 from tianshapjq/reduce-decode-times

Automatic merge from submit-queue

Reduce decode times by changing the kubectl.Filter(runtime.Object, *PrintOptions)'s return values

**What this PR does / why we need it**:
In kubectl/cmd/get.go, we use the function filterFuncs.Filter() to decode data and filter the object. But in the following function printer.PrintObj() decodes the data again.
I made these modifications to reduce the decoding times by changing the filterFuncs.Filter()'s returned values. We can get the decoded object from this function and pass it to the following printer.PrintObj(), so not to waste time to decode again.
This commit is contained in:
Kubernetes Submit Queue 2016-12-19 16:23:02 -08:00 committed by GitHub
commit 874fca652d
4 changed files with 35 additions and 20 deletions

View File

@ -458,8 +458,11 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
lastMapping = mapping lastMapping = mapping
} }
// try to convert before apply filter func
decodedObj, _ := kubectl.DecodeUnknownObject(original)
// filter objects if filter has been defined for current object // filter objects if filter has been defined for current object
if isFiltered, err := filterFuncs.Filter(original, filterOpts); isFiltered { if isFiltered, err := filterFuncs.Filter(decodedObj, filterOpts); isFiltered {
if err == nil { if err == nil {
filteredResourceCount++ filteredResourceCount++
continue continue
@ -489,7 +492,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
resourcePrinter.EnsurePrintWithKind(resourceName) resourcePrinter.EnsurePrintWithKind(resourceName)
} }
if err := printer.PrintObj(original, w); err != nil { if err := printer.PrintObj(decodedObj, w); err != nil {
if !errs.Has(err.Error()) { if !errs.Has(err.Error()) {
errs.Insert(err.Error()) errs.Insert(err.Error())
allErrs = append(allErrs, err) allErrs = append(allErrs, err)
@ -497,7 +500,7 @@ func RunGet(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, args [
} }
continue continue
} }
if err := printer.PrintObj(original, w); err != nil { if err := printer.PrintObj(decodedObj, w); err != nil {
if !errs.Has(err.Error()) { if !errs.Has(err.Error()) {
errs.Insert(err.Error()) errs.Insert(err.Error())
allErrs = append(allErrs, err) allErrs = append(allErrs, err)

View File

@ -257,13 +257,23 @@ func TestGetSortedObjects(t *testing.T) {
} }
func verifyObjects(t *testing.T, expected, actual []runtime.Object) { func verifyObjects(t *testing.T, expected, actual []runtime.Object) {
var actualObj runtime.Object
var err error
if len(actual) != len(expected) { if len(actual) != len(expected) {
t.Fatal(actual) t.Fatal(actual)
} }
for i, obj := range actual { for i, obj := range actual {
actualObj, err := runtime.Decode( switch obj.(type) {
api.Codecs.UniversalDecoder(), case runtime.Unstructured, *runtime.Unknown:
[]byte(runtime.EncodeOrDie(api.Codecs.LegacyCodec(), obj))) actualObj, err = runtime.Decode(
api.Codecs.UniversalDecoder(),
[]byte(runtime.EncodeOrDie(api.Codecs.LegacyCodec(), obj)))
default:
actualObj = obj
err = nil
}
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -60,6 +60,20 @@ func filterPods(obj runtime.Object, options PrintOptions) bool {
func (f Filters) Filter(obj runtime.Object, opts *PrintOptions) (bool, error) { func (f Filters) Filter(obj runtime.Object, opts *PrintOptions) (bool, error) {
// check if the object is unstructured. If so, let's attempt to convert it to a type we can understand // check if the object is unstructured. If so, let's attempt to convert it to a type we can understand
// before apply filter func. // before apply filter func.
obj, _ = DecodeUnknownObject(obj)
for _, filter := range f {
if ok := filter(obj, *opts); ok {
return true, nil
}
}
return false, nil
}
// check if the object is unstructured. If so, let's attempt to convert it to a type we can understand.
func DecodeUnknownObject(obj runtime.Object) (runtime.Object, error) {
var err error
switch obj.(type) { switch obj.(type) {
case runtime.Unstructured, *runtime.Unknown: case runtime.Unstructured, *runtime.Unknown:
if objBytes, err := runtime.Encode(api.Codecs.LegacyCodec(), obj); err == nil { if objBytes, err := runtime.Encode(api.Codecs.LegacyCodec(), obj); err == nil {
@ -69,10 +83,5 @@ func (f Filters) Filter(obj runtime.Object, opts *PrintOptions) (bool, error) {
} }
} }
for _, filter := range f { return obj, err
if ok := filter(obj, *opts); ok {
return true, nil
}
}
return false, nil
} }

View File

@ -2394,14 +2394,7 @@ func (h *HumanReadablePrinter) PrintObj(obj runtime.Object, output io.Writer) er
// check if the object is unstructured. If so, let's attempt to convert it to a type we can understand before // check if the object is unstructured. If so, let's attempt to convert it to a type we can understand before
// trying to print, since the printers are keyed by type. This is extremely expensive. // trying to print, since the printers are keyed by type. This is extremely expensive.
switch obj.(type) { obj, _ = DecodeUnknownObject(obj)
case runtime.Unstructured, *runtime.Unknown:
if objBytes, err := runtime.Encode(api.Codecs.LegacyCodec(), obj); err == nil {
if decodedObj, err := runtime.Decode(api.Codecs.UniversalDecoder(), objBytes); err == nil {
obj = decodedObj
}
}
}
t := reflect.TypeOf(obj) t := reflect.TypeOf(obj)
if handler := h.handlerMap[t]; handler != nil { if handler := h.handlerMap[t]; handler != nil {