From 9a19bbd38c5ab7d4726c8c88cb7aed2468a1f2a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ko=C5=82aczkowski?= Date: Thu, 15 Aug 2024 08:40:09 +0200 Subject: [PATCH] Don't needlessly call element destructors of CqlValue::Vector --- scylla-cql/src/frame/response/result.rs | 60 ++++++++++++++++++++++--- scylla-cql/src/lib.rs | 2 +- scylla-cql/src/types/serialize/value.rs | 3 +- scylla/src/utils/pretty.rs | 7 ++- 4 files changed, 63 insertions(+), 9 deletions(-) diff --git a/scylla-cql/src/frame/response/result.rs b/scylla-cql/src/frame/response/result.rs index 359c8e3cea..de373dc81c 100644 --- a/scylla-cql/src/frame/response/result.rs +++ b/scylla-cql/src/frame/response/result.rs @@ -12,7 +12,9 @@ use crate::types::deserialize::value::{ use crate::types::deserialize::{DeserializationError, FrameSlice}; use bytes::{Buf, Bytes}; use std::borrow::Cow; -use std::{convert::TryInto, net::IpAddr, result::Result as StdResult, str}; +use std::{convert::TryInto, mem, net::IpAddr, result::Result as StdResult, str}; +use std::mem::ManuallyDrop; +use std::ops::Deref; use uuid::Uuid; #[derive(Debug)] @@ -96,7 +98,7 @@ pub enum CqlValue { List(Vec), Map(Vec<(CqlValue, CqlValue)>), Set(Vec), - Vector(Vec), + Vector(DropOptimizedVec), UserDefinedType { keyspace: String, type_name: String, @@ -115,6 +117,52 @@ pub enum CqlValue { Varint(CqlVarint), } + +#[derive(Clone, Debug, PartialEq)] +pub struct DropOptimizedVec { + data: Vec, + drop_elements: bool +} + +impl DropOptimizedVec { + pub fn new(data: Vec, drop_elements: bool) -> DropOptimizedVec { + DropOptimizedVec { + data, + drop_elements, + } + } + + pub fn dropping(data: Vec) -> DropOptimizedVec { + Self::new(data, true) + } + + pub fn non_dropping(data: Vec) -> DropOptimizedVec { + Self::new(data, false) + } + + pub fn into_vec(mut self) -> Vec { + let mut vec = vec![]; + mem::swap(&mut self.data, &mut vec); + vec + } +} + +impl Deref for DropOptimizedVec { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.data + } +} + +impl Drop for DropOptimizedVec { + fn drop(&mut self) { + if !self.drop_elements { + unsafe { self.data.set_len(0); } + } + } +} + impl<'a> TableSpec<'a> { pub const fn borrowed(ks: &'a str, table: &'a str) -> Self { Self { @@ -355,7 +403,7 @@ impl CqlValue { pub fn as_list(&self) -> Option<&Vec> { match self { Self::List(s) => Some(s), - Self::Vector(s) => Some(s), + Self::Vector(s) => Some(&s), _ => None, } } @@ -385,7 +433,7 @@ impl CqlValue { match self { Self::List(s) => Some(s), Self::Set(s) => Some(s), - Self::Vector(s) => Some(s), + Self::Vector(s) => Some(s.into_vec()), _ => None, } } @@ -836,11 +884,11 @@ pub fn deser_cql_value( let v = VectorIterator::::deserialize_vector_of_float_to_vec_of_cql_value( typ, v, )?; - CqlValue::Vector(v) + CqlValue::Vector(DropOptimizedVec::non_dropping(v)) } Vector(_, _) => { let v = Vec::::deserialize(typ, v)?; - CqlValue::Vector(v) + CqlValue::Vector(DropOptimizedVec::dropping(v)) } }) } diff --git a/scylla-cql/src/lib.rs b/scylla-cql/src/lib.rs index 61d9f345c5..071c454589 100644 --- a/scylla-cql/src/lib.rs +++ b/scylla-cql/src/lib.rs @@ -29,7 +29,7 @@ pub mod _macro_internal { pub use crate::frame::response::cql_to_rust::{ FromCqlVal, FromCqlValError, FromRow, FromRowError, }; - pub use crate::frame::response::result::{ColumnSpec, ColumnType, CqlValue, Row}; + pub use crate::frame::response::result::{ColumnSpec, ColumnType, CqlValue, DropOptimizedVec, Row}; pub use crate::frame::value::{ LegacySerializedValues, SerializedResult, Value, ValueList, ValueTooBig, }; diff --git a/scylla-cql/src/types/serialize/value.rs b/scylla-cql/src/types/serialize/value.rs index fa9692d346..2a8de41084 100644 --- a/scylla-cql/src/types/serialize/value.rs +++ b/scylla-cql/src/types/serialize/value.rs @@ -4,6 +4,7 @@ use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::fmt::Display; use std::hash::BuildHasher; use std::net::IpAddr; +use std::ops::Deref; use std::sync::Arc; use thiserror::Error; @@ -576,7 +577,7 @@ fn serialize_cql_value<'b>( } CqlValue::Uuid(u) => <_ as SerializeValue>::serialize(&u, typ, writer), CqlValue::Varint(v) => <_ as SerializeValue>::serialize(&v, typ, writer), - CqlValue::Vector(v) => <_ as SerializeValue>::serialize(&v, typ, writer), + CqlValue::Vector(v) => <_ as SerializeValue>::serialize(v.deref(), typ, writer), } } diff --git a/scylla/src/utils/pretty.rs b/scylla/src/utils/pretty.rs index 3136012dd3..b811168723 100644 --- a/scylla/src/utils/pretty.rs +++ b/scylla/src/utils/pretty.rs @@ -116,7 +116,12 @@ where .fmt(f)?; f.write_str(")")?; } - CqlValue::List(v) | CqlValue::Vector(v) => { + CqlValue::List(v) => { + f.write_str("[")?; + CommaSeparatedDisplayer(v.iter().map(CqlValueDisplayer)).fmt(f)?; + f.write_str("]")?; + } + CqlValue::Vector(v) => { f.write_str("[")?; CommaSeparatedDisplayer(v.iter().map(CqlValueDisplayer)).fmt(f)?; f.write_str("]")?;