diff options
| author | Laytan Laats <laytanlaats@hotmail.com> | 2024-07-08 00:37:40 +0200 |
|---|---|---|
| committer | Laytan Laats <laytanlaats@hotmail.com> | 2024-07-08 00:37:40 +0200 |
| commit | db3b4ceb4a4c3fc3f6ac1a43185c12f3b9690dee (patch) | |
| tree | ddbe76b867218fc313cbe0016d52258894ab9e48 /core/encoding | |
| parent | 39e9b65c59eba124d5e0647ffc6cb45c8377e6c2 (diff) | |
encoding/cbor: improve perf of marshalling array-like types
Diffstat (limited to 'core/encoding')
| -rw-r--r-- | core/encoding/cbor/marshal.odin | 72 |
1 files changed, 56 insertions, 16 deletions
diff --git a/core/encoding/cbor/marshal.odin b/core/encoding/cbor/marshal.odin index d64d22d9c..2cdf384c3 100644 --- a/core/encoding/cbor/marshal.odin +++ b/core/encoding/cbor/marshal.odin @@ -54,7 +54,7 @@ marshal_into_bytes :: proc(v: any, flags := ENCODE_SMALL, allocator := context.a defer if err != nil { strings.builder_destroy(&b) } - if err = marshal_into_builder(&b, v, flags, temp_allocator, loc=loc); err != nil { + if err = marshal_into_builder(&b, v, flags, temp_allocator); err != nil { return } @@ -63,20 +63,20 @@ marshal_into_bytes :: proc(v: any, flags := ENCODE_SMALL, allocator := context.a // Marshals the given value into a CBOR byte stream written to the given builder. // See docs on the `marshal_into` proc group for more info. -marshal_into_builder :: proc(b: ^strings.Builder, v: any, flags := ENCODE_SMALL, temp_allocator := context.temp_allocator, loc := #caller_location) -> Marshal_Error { - return marshal_into_writer(strings.to_writer(b), v, flags, temp_allocator, loc=loc) +marshal_into_builder :: proc(b: ^strings.Builder, v: any, flags := ENCODE_SMALL, temp_allocator := context.temp_allocator) -> Marshal_Error { + return marshal_into_writer(strings.to_writer(b), v, flags, temp_allocator) } // Marshals the given value into a CBOR byte stream written to the given writer. // See docs on the `marshal_into` proc group for more info. -marshal_into_writer :: proc(w: io.Writer, v: any, flags := ENCODE_SMALL, temp_allocator := context.temp_allocator, loc := #caller_location) -> Marshal_Error { +marshal_into_writer :: proc(w: io.Writer, v: any, flags := ENCODE_SMALL, temp_allocator := context.temp_allocator) -> Marshal_Error { encoder := Encoder{flags, w, temp_allocator} - return marshal_into_encoder(encoder, v, loc=loc) + return marshal_into_encoder(encoder, v) } // Marshals the given value into a CBOR byte stream written to the given encoder. // See docs on the `marshal_into` proc group for more info. -marshal_into_encoder :: proc(e: Encoder, v: any, loc := #caller_location) -> (err: Marshal_Error) { +marshal_into_encoder :: proc(e: Encoder, v: any) -> (err: Marshal_Error) { e := e if e.temp_allocator.procedure == nil { @@ -97,11 +97,14 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc := #caller_location) -> (e return impl->marshal(e, v) } - ti := runtime.type_info_base(type_info_of(v.id)) - a := any{v.data, ti.id} + ti := runtime.type_info_core(type_info_of(v.id)) + return _marshal_into_encoder(e, v, ti) +} +_marshal_into_encoder :: proc(e: Encoder, v: any, ti: ^runtime.Type_Info) -> (err: Marshal_Error) { + a := any{v.data, ti.id} #partial switch info in ti.variant { - case runtime.Type_Info_Named: + case runtime.Type_Info_Named, runtime.Type_Info_Enum, runtime.Type_Info_Bit_Field: unreachable() case runtime.Type_Info_Pointer: @@ -223,18 +226,38 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc := #caller_location) -> (e } err_conv(_encode_u64(e, u64(info.count), .Array)) or_return + + if impl, ok := _tag_implementations_type[info.elem.id]; ok { + for i in 0..<info.count { + data := uintptr(v.data) + uintptr(i*info.elem_size) + impl->marshal(e, any{rawptr(data), info.elem.id}) or_return + } + return + } + + elem_ti := runtime.type_info_core(type_info_of(info.elem.id)) for i in 0..<info.count { data := uintptr(v.data) + uintptr(i*info.elem_size) - marshal_into(e, any{rawptr(data), info.elem.id}) or_return + _marshal_into_encoder(e, any{rawptr(data), info.elem.id}, elem_ti) or_return } return case runtime.Type_Info_Enumerated_Array: // index := runtime.type_info_base(info.index).variant.(runtime.Type_Info_Enum) err_conv(_encode_u64(e, u64(info.count), .Array)) or_return + + if impl, ok := _tag_implementations_type[info.elem.id]; ok { + for i in 0..<info.count { + data := uintptr(v.data) + uintptr(i*info.elem_size) + impl->marshal(e, any{rawptr(data), info.elem.id}) or_return + } + return + } + + elem_ti := runtime.type_info_core(type_info_of(info.elem.id)) for i in 0..<info.count { data := uintptr(v.data) + uintptr(i*info.elem_size) - marshal_into(e, any{rawptr(data), info.elem.id}) or_return + _marshal_into_encoder(e, any{rawptr(data), info.elem.id}, elem_ti) or_return } return @@ -246,9 +269,19 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc := #caller_location) -> (e array := (^mem.Raw_Dynamic_Array)(v.data) err_conv(_encode_u64(e, u64(array.len), .Array)) or_return + + if impl, ok := _tag_implementations_type[info.elem.id]; ok { + for i in 0..<array.len { + data := uintptr(array.data) + uintptr(i*info.elem_size) + impl->marshal(e, any{rawptr(data), info.elem.id}) or_return + } + return + } + + elem_ti := runtime.type_info_core(type_info_of(info.elem.id)) for i in 0..<array.len { data := uintptr(array.data) + uintptr(i*info.elem_size) - marshal_into(e, any{rawptr(data), info.elem.id}) or_return + _marshal_into_encoder(e, any{rawptr(data), info.elem.id}, elem_ti) or_return } return @@ -260,9 +293,19 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc := #caller_location) -> (e array := (^mem.Raw_Slice)(v.data) err_conv(_encode_u64(e, u64(array.len), .Array)) or_return + + if impl, ok := _tag_implementations_type[info.elem.id]; ok { + for i in 0..<array.len { + data := uintptr(array.data) + uintptr(i*info.elem_size) + impl->marshal(e, any{rawptr(data), info.elem.id}) or_return + } + return + } + + elem_ti := runtime.type_info_core(type_info_of(info.elem.id)) for i in 0..<array.len { data := uintptr(array.data) + uintptr(i*info.elem_size) - marshal_into(e, any{rawptr(data), info.elem.id}) or_return + _marshal_into_encoder(e, any{rawptr(data), info.elem.id}, elem_ti) or_return } return @@ -542,9 +585,6 @@ marshal_into_encoder :: proc(e: Encoder, v: any, loc := #caller_location) -> (e return marshal_into(e, any{v.data, vti.id}) - case runtime.Type_Info_Enum: - return marshal_into(e, any{v.data, info.base.id}) - case runtime.Type_Info_Bit_Set: // Store bit_set as big endian just like the protocol. do_byte_swap := !reflect.bit_set_is_big_endian(v) |