@@ -5,20 +5,15 @@ use std::fmt::Debug;
55
66use vortex_dtype:: DType ;
77use vortex_error:: VortexResult ;
8- use vortex_error:: vortex_bail;
98use vortex_error:: vortex_ensure;
109use vortex_scalar:: Scalar ;
1110use vortex_scalar:: ScalarValue ;
1211use vortex_session:: VortexSession ;
1312
1413use crate :: ArrayRef ;
15- use crate :: DeserializeMetadata ;
1614use crate :: ExecutionCtx ;
1715use crate :: IntoArray ;
18- use crate :: ProstMetadata ;
19- use crate :: SerializeMetadata ;
2016use crate :: arrays:: ConstantArray ;
21- use crate :: arrays:: constant:: ConstantMetadata ;
2217use crate :: arrays:: constant:: compute:: rules:: PARENT_RULES ;
2318use crate :: arrays:: constant:: vtable:: canonical:: constant_canonicalize;
2419use crate :: buffer:: BufferHandle ;
@@ -44,12 +39,20 @@ impl ConstantVTable {
4439
4540/// Maximum size (in bytes) of a protobuf-encoded scalar value that will be inlined
4641/// into the array metadata. Values larger than this are stored only in the buffer.
47- const CONSTANT_INLINE_THRESHOLD : usize = 1024 ;
42+ pub ( crate ) const CONSTANT_INLINE_THRESHOLD : usize = 1024 ;
4843
4944impl VTable for ConstantVTable {
5045 type Array = ConstantArray ;
5146
52- type Metadata = ProstMetadata < ConstantMetadata > ;
47+ /// Optional inlined scalar constant.
48+ ///
49+ /// When the scalar value is small enough (<= `CONSTANT_INLINE_THRESHOLD` bytes), it is stored
50+ /// directly in the metadata to avoid an extra buffer allocation and potential
51+ /// device-to-host copy during deserialization.
52+ ///
53+ /// Currently, scalars are **always** stored in a separate buffer, regardless of if we inline a
54+ /// small scalar into the metadata.
55+ type Metadata = Option < Scalar > ;
5356
5457 type ArrayVTable = Self ;
5558 type OperationsVTable = Self ;
@@ -61,28 +64,34 @@ impl VTable for ConstantVTable {
6164 }
6265
6366 fn metadata ( array : & ConstantArray ) -> VortexResult < Self :: Metadata > {
64- let constant = & array. scalar ( ) ;
65- let proto_bytes : Vec < u8 > = ScalarValue :: to_proto_bytes ( constant . value ( ) ) ;
66- let scalar_value = ( proto_bytes . len ( ) <= CONSTANT_INLINE_THRESHOLD ) . then_some ( proto_bytes ) ;
67- Ok ( ProstMetadata ( ConstantMetadata { scalar_value } ) )
67+ let constant = array. scalar ( ) ;
68+
69+ // If the scalar is small enough, we can simply carry it around as metadata.
70+ Ok ( ( constant . nbytes ( ) <= CONSTANT_INLINE_THRESHOLD ) . then_some ( constant . clone ( ) ) )
6871 }
6972
7073 fn serialize ( metadata : Self :: Metadata ) -> VortexResult < Option < Vec < u8 > > > {
71- Ok ( Some ( metadata. serialize ( ) ) )
74+ // If we do not have a scalar to serialize, just return empty bytes.
75+ Ok ( Some ( metadata. map_or_else ( Vec :: new, |c| {
76+ // Note that we **only** serialize the optional scalar value (not including the dtype).
77+ ScalarValue :: to_proto_bytes ( c. value ( ) )
78+ } ) ) )
7279 }
7380
7481 fn deserialize (
7582 bytes : & [ u8 ] ,
76- _dtype : & DType ,
83+ dtype : & DType ,
7784 _len : usize ,
7885 _session : & VortexSession ,
7986 ) -> VortexResult < Self :: Metadata > {
8087 // Empty bytes indicates an old writer that didn't produce metadata.
8188 if bytes. is_empty ( ) {
82- return Ok ( ProstMetadata ( ConstantMetadata { scalar_value : None } ) ) ;
89+ return Ok ( None ) ;
8390 }
84- let metadata = <Self :: Metadata as DeserializeMetadata >:: deserialize ( bytes) ?;
85- Ok ( ProstMetadata ( metadata) )
91+
92+ // Otherwise, deserialize the constant scalar from the metadata.
93+ let scalar_value = ScalarValue :: from_proto_bytes ( bytes, dtype) ?;
94+ Some ( Scalar :: try_new ( dtype. clone ( ) , scalar_value) ) . transpose ( )
8695 }
8796
8897 fn build (
@@ -93,22 +102,22 @@ impl VTable for ConstantVTable {
93102 _children : & dyn ArrayChildren ,
94103 ) -> VortexResult < ConstantArray > {
95104 // Prefer reading the scalar from inlined metadata to avoid device-to-host copies.
96- let scalar = if let Some ( proto_bytes) = & metadata. scalar_value {
97- let scalar_value = ScalarValue :: from_proto_bytes ( proto_bytes, dtype) ?;
98-
99- Scalar :: try_new ( dtype. clone ( ) , scalar_value)
100- } else {
101- if buffers. len ( ) != 1 {
102- vortex_bail ! ( "Expected 1 buffer, got {}" , buffers. len( ) ) ;
103- }
105+ if let Some ( constant) = metadata {
106+ return Ok ( ConstantArray :: new ( constant. clone ( ) , len) ) ;
107+ }
104108
105- let buffer = buffers[ 0 ] . clone ( ) . try_to_host_sync ( ) ?;
106- let bytes: & [ u8 ] = buffer. as_ref ( ) ;
109+ // Otherwise, get the constant scalar from the buffers.
110+ vortex_ensure ! (
111+ buffers. len( ) == 1 ,
112+ "Expected 1 buffer, got {}" ,
113+ buffers. len( )
114+ ) ;
107115
108- let scalar_value = ScalarValue :: from_proto_bytes ( bytes, dtype) ?;
116+ let buffer = buffers[ 0 ] . clone ( ) . try_to_host_sync ( ) ?;
117+ let bytes: & [ u8 ] = buffer. as_ref ( ) ;
109118
110- Scalar :: try_new ( dtype . clone ( ) , scalar_value )
111- } ?;
119+ let scalar_value = ScalarValue :: from_proto_bytes ( bytes , dtype ) ? ;
120+ let scalar = Scalar :: try_new ( dtype . clone ( ) , scalar_value ) ?;
112121
113122 Ok ( ConstantArray :: new ( scalar, len) )
114123 }
0 commit comments