From 4e8e0cda7e429fecf4b91f992037439a42943a80 Mon Sep 17 00:00:00 2001 From: steviez Date: Fri, 16 Sep 2022 18:38:28 -0500 Subject: [PATCH] Remove extra data copy from several Rocks get() methods (#27693) Several of the get() methods return a deserialized object (as opposed to a Vec) by first getting a byte array out of Rocks, and then using bincode::deserialize() to get the underlying type. However, deserialize() only requires a u8 slice, not an owned Vec. So, we can use get_pinned_cf() to reference memory owned by Rocks and avoid an unnecessary copy. --- ledger/src/blockstore_db.rs | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/ledger/src/blockstore_db.rs b/ledger/src/blockstore_db.rs index c9ef03703..e170e869d 100644 --- a/ledger/src/blockstore_db.rs +++ b/ledger/src/blockstore_db.rs @@ -386,6 +386,11 @@ impl Rocks { Ok(opt) } + fn get_pinned_cf(&self, cf: &ColumnFamily, key: &[u8]) -> Result> { + let opt = self.db.get_pinned_cf(cf, key)?; + Ok(opt) + } + fn put_cf(&self, cf: &ColumnFamily, key: &[u8], value: &[u8]) -> Result<()> { self.db.put_cf(cf, key, value)?; Ok(()) @@ -1017,9 +1022,11 @@ impl Database { where C: TypedColumn + ColumnName, { - if let Some(serialized_value) = self.backend.get_cf(self.cf_handle::(), &C::key(key))? { - let value = deserialize(&serialized_value)?; - + if let Some(pinnable_slice) = self + .backend + .get_pinned_cf(self.cf_handle::(), &C::key(key))? + { + let value = deserialize(pinnable_slice.as_ref())?; Ok(Some(value)) } else { Ok(None) @@ -1287,9 +1294,8 @@ where self.column_options.rocks_perf_sample_interval, &self.read_perf_status, ); - if let Some(serialized_value) = self.backend.get_cf(self.handle(), &C::key(key))? { - let value = deserialize(&serialized_value)?; - + if let Some(pinnable_slice) = self.backend.get_pinned_cf(self.handle(), &C::key(key))? { + let value = deserialize(pinnable_slice.as_ref())?; result = Ok(Some(value)) } @@ -1356,7 +1362,7 @@ where self.column_options.rocks_perf_sample_interval, &self.read_perf_status, ); - let result = self.backend.get_cf(self.handle(), &C::key(key)); + let result = self.backend.get_pinned_cf(self.handle(), &C::key(key)); if let Some(op_start_instant) = is_perf_enabled { report_rocksdb_read_perf( C::NAME, @@ -1366,10 +1372,10 @@ where ); } - if let Some(serialized_value) = result? { - let value = match C::Type::decode(&serialized_value[..]) { + if let Some(pinnable_slice) = result? { + let value = match C::Type::decode(pinnable_slice.as_ref()) { Ok(value) => value, - Err(_) => deserialize::(&serialized_value)?.into(), + Err(_) => deserialize::(pinnable_slice.as_ref())?.into(), }; Ok(Some(value)) } else { @@ -1382,7 +1388,7 @@ where self.column_options.rocks_perf_sample_interval, &self.read_perf_status, ); - let result = self.backend.get_cf(self.handle(), &C::key(key)); + let result = self.backend.get_pinned_cf(self.handle(), &C::key(key)); if let Some(op_start_instant) = is_perf_enabled { report_rocksdb_read_perf( C::NAME, @@ -1392,8 +1398,8 @@ where ); } - if let Some(serialized_value) = result? { - Ok(Some(C::Type::decode(&serialized_value[..])?)) + if let Some(pinnable_slice) = result? { + Ok(Some(C::Type::decode(pinnable_slice.as_ref())?)) } else { Ok(None) }