Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
ea7e7a18
Unverified
Commit
ea7e7a18
authored
Apr 30, 2016
by
Clayton Coleman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create a new method UnsafeConvertToVersion for faster convert
Only encode/decode will call this path, to allow us to optimize for unsafe operations.
parent
51b62410
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
118 additions
and
19 deletions
+118
-19
conversion_test.go
pkg/api/conversion_test.go
+6
-6
helper.go
pkg/runtime/helper.go
+21
-0
scheme.go
pkg/runtime/scheme.go
+80
-0
versioning.go
pkg/runtime/serializer/versioning/versioning.go
+11
-13
No files found.
pkg/api/conversion_test.go
View file @
ea7e7a18
...
@@ -50,11 +50,11 @@ func BenchmarkPodConversion(b *testing.B) {
...
@@ -50,11 +50,11 @@ func BenchmarkPodConversion(b *testing.B) {
var
result
*
api
.
Pod
var
result
*
api
.
Pod
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
pod
:=
&
items
[
i
%
width
]
pod
:=
&
items
[
i
%
width
]
versionedObj
,
err
:=
scheme
.
ConvertToVersion
(
pod
,
*
testapi
.
Default
.
GroupVersion
())
versionedObj
,
err
:=
scheme
.
Unsafe
ConvertToVersion
(
pod
,
*
testapi
.
Default
.
GroupVersion
())
if
err
!=
nil
{
if
err
!=
nil
{
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
}
}
obj
,
err
:=
scheme
.
ConvertToVersion
(
versionedObj
,
testapi
.
Default
.
InternalGroupVersion
())
obj
,
err
:=
scheme
.
Unsafe
ConvertToVersion
(
versionedObj
,
testapi
.
Default
.
InternalGroupVersion
())
if
err
!=
nil
{
if
err
!=
nil
{
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
}
}
...
@@ -76,11 +76,11 @@ func BenchmarkNodeConversion(b *testing.B) {
...
@@ -76,11 +76,11 @@ func BenchmarkNodeConversion(b *testing.B) {
scheme
:=
api
.
Scheme
scheme
:=
api
.
Scheme
var
result
*
api
.
Node
var
result
*
api
.
Node
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
versionedObj
,
err
:=
scheme
.
ConvertToVersion
(
&
node
,
*
testapi
.
Default
.
GroupVersion
())
versionedObj
,
err
:=
scheme
.
Unsafe
ConvertToVersion
(
&
node
,
*
testapi
.
Default
.
GroupVersion
())
if
err
!=
nil
{
if
err
!=
nil
{
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
}
}
obj
,
err
:=
scheme
.
ConvertToVersion
(
versionedObj
,
testapi
.
Default
.
InternalGroupVersion
())
obj
,
err
:=
scheme
.
Unsafe
ConvertToVersion
(
versionedObj
,
testapi
.
Default
.
InternalGroupVersion
())
if
err
!=
nil
{
if
err
!=
nil
{
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
}
}
...
@@ -104,11 +104,11 @@ func BenchmarkReplicationControllerConversion(b *testing.B) {
...
@@ -104,11 +104,11 @@ func BenchmarkReplicationControllerConversion(b *testing.B) {
scheme
:=
api
.
Scheme
scheme
:=
api
.
Scheme
var
result
*
api
.
ReplicationController
var
result
*
api
.
ReplicationController
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
versionedObj
,
err
:=
scheme
.
ConvertToVersion
(
&
replicationController
,
*
testapi
.
Default
.
GroupVersion
())
versionedObj
,
err
:=
scheme
.
Unsafe
ConvertToVersion
(
&
replicationController
,
*
testapi
.
Default
.
GroupVersion
())
if
err
!=
nil
{
if
err
!=
nil
{
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
}
}
obj
,
err
:=
scheme
.
ConvertToVersion
(
versionedObj
,
testapi
.
Default
.
InternalGroupVersion
())
obj
,
err
:=
scheme
.
Unsafe
ConvertToVersion
(
versionedObj
,
testapi
.
Default
.
InternalGroupVersion
())
if
err
!=
nil
{
if
err
!=
nil
{
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
b
.
Fatalf
(
"Conversion error: %v"
,
err
)
}
}
...
...
pkg/runtime/helper.go
View file @
ea7e7a18
...
@@ -43,10 +43,31 @@ func (t objectTyperToTyper) ObjectKind(obj Object) (*unversioned.GroupVersionKin
...
@@ -43,10 +43,31 @@ func (t objectTyperToTyper) ObjectKind(obj Object) (*unversioned.GroupVersionKin
return
&
gvk
,
unversionedType
,
nil
return
&
gvk
,
unversionedType
,
nil
}
}
// ObjectTyperToTyper casts the old typer interface to the new typer interface
func
ObjectTyperToTyper
(
typer
ObjectTyper
)
Typer
{
func
ObjectTyperToTyper
(
typer
ObjectTyper
)
Typer
{
return
objectTyperToTyper
{
typer
:
typer
}
return
objectTyperToTyper
{
typer
:
typer
}
}
}
// unsafeObjectConvertor implements ObjectConvertor using the unsafe conversion path.
type
unsafeObjectConvertor
struct
{
*
Scheme
}
var
_
ObjectConvertor
=
unsafeObjectConvertor
{}
// ConvertToVersion converts in to the provided outVersion without copying the input first, which
// is only safe if the output object is not mutated or reused.
func
(
c
unsafeObjectConvertor
)
ConvertToVersion
(
in
Object
,
outVersion
unversioned
.
GroupVersion
)
(
Object
,
error
)
{
return
c
.
Scheme
.
UnsafeConvertToVersion
(
in
,
outVersion
)
}
// UnsafeObjectConvertor performs object conversion without copying the object structure,
// for use when the converted object will not be reused or mutated. Primarily for use within
// versioned codecs, which use the external object for serialization but do not return it.
func
UnsafeObjectConvertor
(
scheme
*
Scheme
)
ObjectConvertor
{
return
unsafeObjectConvertor
{
scheme
}
}
// fieldPtr puts the address of fieldName, which must be a member of v,
// fieldPtr puts the address of fieldName, which must be a member of v,
// into dest, which must be an address of a variable to which this field's
// into dest, which must be an address of a variable to which this field's
// address can be assigned.
// address can be assigned.
...
...
pkg/runtime/scheme.go
View file @
ea7e7a18
...
@@ -523,11 +523,80 @@ func (s *Scheme) ConvertToVersion(in Object, outVersion unversioned.GroupVersion
...
@@ -523,11 +523,80 @@ func (s *Scheme) ConvertToVersion(in Object, outVersion unversioned.GroupVersion
return
out
,
nil
return
out
,
nil
}
}
// UnsafeConvertToVersion will convert in to the provided outVersion if such a conversion is possible,
// but does not guarantee the output object does not share fields with the input object. It attempts to be as
// efficient as possible when doing conversion.
func
(
s
*
Scheme
)
UnsafeConvertToVersion
(
in
Object
,
outVersion
unversioned
.
GroupVersion
)
(
Object
,
error
)
{
switch
t
:=
in
.
(
type
)
{
case
*
Unknown
:
t
.
APIVersion
=
outVersion
.
String
()
return
t
,
nil
case
*
Unstructured
:
t
.
SetAPIVersion
(
outVersion
.
String
())
return
t
,
nil
case
*
UnstructuredList
:
t
.
SetAPIVersion
(
outVersion
.
String
())
return
t
,
nil
}
// determine the incoming kinds with as few allocations as possible.
t
:=
reflect
.
TypeOf
(
in
)
if
t
.
Kind
()
!=
reflect
.
Ptr
{
return
nil
,
fmt
.
Errorf
(
"only pointer types may be converted: %v"
,
t
)
}
t
=
t
.
Elem
()
if
t
.
Kind
()
!=
reflect
.
Struct
{
return
nil
,
fmt
.
Errorf
(
"only pointers to struct types may be converted: %v"
,
t
)
}
kinds
,
ok
:=
s
.
typeToGVK
[
t
]
if
!
ok
||
len
(
kinds
)
==
0
{
return
nil
,
fmt
.
Errorf
(
"%v is not a registered type and cannot be converted into version %q"
,
t
,
outVersion
)
}
// if the Go type is also registered to the destination kind, no conversion is necessary
for
i
:=
range
kinds
{
if
kinds
[
i
]
.
Version
==
outVersion
.
Version
&&
kinds
[
i
]
.
Group
==
outVersion
.
Group
{
setTargetKind
(
in
,
kinds
[
i
])
return
in
,
nil
}
}
// type is unversioned, no conversion necessary
// it should be possible to avoid this allocation
if
unversionedKind
,
ok
:=
s
.
unversionedTypes
[
t
];
ok
{
kind
:=
unversionedKind
outKind
:=
outVersion
.
WithKind
(
kind
.
Kind
)
setTargetKind
(
in
,
outKind
)
return
in
,
nil
}
// allocate a new object as the target using the target kind
// TODO: this should look in the target group version and find the first kind that matches, rather than the
// first kind registered in typeToGVK
kind
:=
kinds
[
0
]
kind
.
Version
=
outVersion
.
Version
kind
.
Group
=
outVersion
.
Group
out
,
err
:=
s
.
New
(
kind
)
if
err
!=
nil
{
return
nil
,
err
}
// TODO: try to avoid the allocations here - in fast paths we are not likely to need these flags or meta
flags
,
meta
:=
s
.
converter
.
DefaultMeta
(
t
)
if
err
:=
s
.
converter
.
Convert
(
in
,
out
,
flags
,
meta
);
err
!=
nil
{
return
nil
,
err
}
setTargetKind
(
out
,
kind
)
return
out
,
nil
}
// generateConvertMeta constructs the meta value we pass to Convert.
// generateConvertMeta constructs the meta value we pass to Convert.
func
(
s
*
Scheme
)
generateConvertMeta
(
srcGroupVersion
,
destGroupVersion
unversioned
.
GroupVersion
,
in
interface
{})
(
conversion
.
FieldMatchingFlags
,
*
conversion
.
Meta
)
{
func
(
s
*
Scheme
)
generateConvertMeta
(
srcGroupVersion
,
destGroupVersion
unversioned
.
GroupVersion
,
in
interface
{})
(
conversion
.
FieldMatchingFlags
,
*
conversion
.
Meta
)
{
return
s
.
converter
.
DefaultMeta
(
reflect
.
TypeOf
(
in
))
return
s
.
converter
.
DefaultMeta
(
reflect
.
TypeOf
(
in
))
}
}
// setTargetVersion is deprecated and should be replaced by use of setTargetKind
func
setTargetVersion
(
obj
Object
,
raw
*
Scheme
,
gv
unversioned
.
GroupVersion
)
{
func
setTargetVersion
(
obj
Object
,
raw
*
Scheme
,
gv
unversioned
.
GroupVersion
)
{
if
gv
.
Version
==
APIVersionInternal
{
if
gv
.
Version
==
APIVersionInternal
{
// internal is a special case
// internal is a special case
...
@@ -537,3 +606,14 @@ func setTargetVersion(obj Object, raw *Scheme, gv unversioned.GroupVersion) {
...
@@ -537,3 +606,14 @@ func setTargetVersion(obj Object, raw *Scheme, gv unversioned.GroupVersion) {
gvk
,
_
:=
raw
.
ObjectKind
(
obj
)
gvk
,
_
:=
raw
.
ObjectKind
(
obj
)
obj
.
GetObjectKind
()
.
SetGroupVersionKind
(
unversioned
.
GroupVersionKind
{
Group
:
gv
.
Group
,
Version
:
gv
.
Version
,
Kind
:
gvk
.
Kind
})
obj
.
GetObjectKind
()
.
SetGroupVersionKind
(
unversioned
.
GroupVersionKind
{
Group
:
gv
.
Group
,
Version
:
gv
.
Version
,
Kind
:
gvk
.
Kind
})
}
}
// setTargetKind sets the kind on an object, taking into account whether the target kind is the internal version.
func
setTargetKind
(
obj
Object
,
kind
unversioned
.
GroupVersionKind
)
{
if
kind
.
Version
==
APIVersionInternal
{
// internal is a special case
// TODO: look at removing the need to special case this
obj
.
GetObjectKind
()
.
SetGroupVersionKind
(
unversioned
.
GroupVersionKind
{})
return
}
obj
.
GetObjectKind
()
.
SetGroupVersionKind
(
kind
)
}
pkg/runtime/serializer/versioning/versioning.go
View file @
ea7e7a18
...
@@ -71,7 +71,7 @@ func NewCodecForScheme(
...
@@ -71,7 +71,7 @@ func NewCodecForScheme(
encodeVersion
[]
unversioned
.
GroupVersion
,
encodeVersion
[]
unversioned
.
GroupVersion
,
decodeVersion
[]
unversioned
.
GroupVersion
,
decodeVersion
[]
unversioned
.
GroupVersion
,
)
runtime
.
Codec
{
)
runtime
.
Codec
{
return
NewCodec
(
encoder
,
decoder
,
scheme
,
scheme
,
scheme
,
runtime
.
ObjectTyperToTyper
(
scheme
),
encodeVersion
,
decodeVersion
)
return
NewCodec
(
encoder
,
decoder
,
runtime
.
UnsafeObjectConvertor
(
scheme
)
,
scheme
,
scheme
,
runtime
.
ObjectTyperToTyper
(
scheme
),
encodeVersion
,
decodeVersion
)
}
}
// NewCodec takes objects in their internal versions and converts them to external versions before
// NewCodec takes objects in their internal versions and converts them to external versions before
...
@@ -263,21 +263,19 @@ func (c *codec) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unv
...
@@ -263,21 +263,19 @@ func (c *codec) EncodeToStream(obj runtime.Object, w io.Writer, overrides ...unv
}
}
// Perform a conversion if necessary
// Perform a conversion if necessary
if
gvk
.
GroupVersion
()
!=
targetGV
{
out
,
err
:=
c
.
convertor
.
ConvertToVersion
(
obj
,
targetGV
)
if
err
!=
nil
{
if
ok
{
return
err
}
}
else
{
obj
=
out
}
}
objectKind
:=
obj
.
GetObjectKind
()
objectKind
:=
obj
.
GetObjectKind
()
old
:=
objectKind
.
GroupVersionKind
()
old
:=
objectKind
.
GroupVersionKind
()
objectKind
.
SetGroupVersionKind
(
unversioned
.
GroupVersionKind
{
Group
:
targetGV
.
Group
,
Version
:
targetGV
.
Version
,
Kind
:
gvk
.
Kind
})
out
,
err
:=
c
.
convertor
.
ConvertToVersion
(
obj
,
targetGV
)
if
err
!=
nil
{
if
ok
{
return
err
}
}
else
{
obj
=
out
}
// Conversion is responsible for setting the proper group, version, and kind onto the outgoing object
err
=
c
.
encoder
.
EncodeToStream
(
obj
,
w
,
overrides
...
)
err
=
c
.
encoder
.
EncodeToStream
(
obj
,
w
,
overrides
...
)
// restore the old GVK, in case conversion returned the same object
objectKind
.
SetGroupVersionKind
(
old
)
objectKind
.
SetGroupVersionKind
(
old
)
return
err
return
err
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment