Skip to content

Commit a7d851e

Browse files
committed
Add faster specialization for deserializing vector<float>
1 parent de99af7 commit a7d851e

File tree

2 files changed

+32
-6
lines changed

2 files changed

+32
-6
lines changed

scylla-cql/src/frame/response/result.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use crate::frame::{frame_errors::ParseError, types};
77
use crate::types::deserialize::result::{RowIterator, TypedRowIterator};
88
use crate::types::deserialize::value::{
99
mk_deser_err, BuiltinDeserializationErrorKind, DeserializeValue, MapIterator, UdtIterator,
10+
VectorIterator,
1011
};
1112
use crate::types::deserialize::{DeserializationError, FrameSlice};
1213
use bytes::{Buf, Bytes};
@@ -829,9 +830,15 @@ pub fn deser_cql_value(
829830
.collect::<StdResult<_, _>>()?;
830831
CqlValue::Tuple(t)
831832
}
832-
Vector(_type_name, _) => {
833-
let l = Vec::<CqlValue>::deserialize(typ, v)?;
834-
CqlValue::Vector(l)
833+
// Specialization for faster deserialization of vectors of floats, which are currently
834+
// the only type of vector
835+
Vector(elem_type, _) if matches!(elem_type.as_ref(), Float) => {
836+
let v = VectorIterator::<CqlValue>::deserialize_vector_of_float_to_vec_of_cql_value(typ, v)?;
837+
CqlValue::Vector(v)
838+
}
839+
Vector(_, _) => {
840+
let v = Vec::<CqlValue>::deserialize(typ, v)?;
841+
CqlValue::Vector(v)
835842
}
836843
})
837844
}

scylla-cql/src/types/deserialize/value.rs

+22-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
//! Provides types for dealing with CQL value deserialization.
22
3+
use bytes::Bytes;
34
use std::{
45
collections::{BTreeMap, BTreeSet, HashMap, HashSet},
56
hash::{BuildHasher, Hash},
67
net::IpAddr,
78
};
8-
9-
use bytes::Bytes;
109
use uuid::Uuid;
1110

1211
use std::fmt::{Display, Pointer};
@@ -759,7 +758,7 @@ pub struct VectorIterator<'frame, T> {
759758
}
760759

761760
impl<'frame, T> VectorIterator<'frame, T> {
762-
fn new(
761+
pub fn new(
763762
coll_typ: &'frame ColumnType,
764763
elem_typ: &'frame ColumnType,
765764
count: usize,
@@ -774,6 +773,25 @@ impl<'frame, T> VectorIterator<'frame, T> {
774773
phantom_data: std::marker::PhantomData,
775774
}
776775
}
776+
777+
/// Faster specialization for deserializing a `vector<float>` into `Vec<CqlValue>`.
778+
/// The generic code `Vec<CqlValue>::deserialize(...)` is much slower because it has to
779+
/// match on the element type for every item in the vector.
780+
/// Here we just hardcode `f32` and we can shortcut a lot of code.
781+
///
782+
/// This could be nicer if Rust had generic type specialization in stable,
783+
/// but for now we need a separate method.
784+
pub fn deserialize_vector_of_float_to_vec_of_cql_value(
785+
typ: &'frame ColumnType,
786+
v: Option<FrameSlice<'frame>>,
787+
) -> Result<Vec<CqlValue>, DeserializationError> {
788+
VectorIterator::<'frame, f32>::deserialize(typ, v)
789+
.and_then(|it| {
790+
it.map(|e| e.map(CqlValue::Float))
791+
.collect::<Result<Vec<CqlValue>, DeserializationError>>()
792+
})
793+
.map_err(deser_error_replace_rust_name::<Self>)
794+
}
777795
}
778796

779797
impl<'frame, T> DeserializeValue<'frame> for VectorIterator<'frame, T>
@@ -883,6 +901,7 @@ where
883901
.and_then(|it| it.collect::<Result<_, DeserializationError>>())
884902
.map_err(deser_error_replace_rust_name::<Self>)
885903
}
904+
886905
ColumnType::Vector(_, _) => VectorIterator::<'frame, T>::deserialize(typ, v)
887906
.and_then(|it| it.collect::<Result<_, DeserializationError>>())
888907
.map_err(deser_error_replace_rust_name::<Self>),

0 commit comments

Comments
 (0)