Skip to content

Commit 3312975

Browse files
authored
RUST-536 Eliminate redundant clones (#377)
1 parent 2f6d83b commit 3312975

File tree

53 files changed

+414
-319
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+414
-319
lines changed

benchmarks/Cargo.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2018"
66

77
[features]
88
default = ["tokio-runtime"]
9-
tokio-runtime = ["tokio/fs", "tokio/macros", "tokio/rt-core", "tokio/rt-threaded"]
9+
tokio-runtime = ["tokio/fs", "tokio/macros", "tokio/rt", "tokio/rt-multi-thread", "tokio-stream"]
1010
async-std-runtime = ["async-std"]
1111

1212
[dependencies]
@@ -16,8 +16,9 @@ lazy_static = "1.4.0"
1616
clap = "2.33.3"
1717
indicatif = "0.15.0"
1818
async-trait = "0.1.41"
19-
tokio = { version = "0.2.23", features = ["sync"] }
19+
tokio = { version = "1.6", features = ["sync"] }
20+
tokio-stream = { version = "0.1.6", features = ["io-util"], optional = true }
2021
# "unstable" feature is needed for `spawn_blocking`, which is only used in task setup
21-
async-std = { version = "=1.6.2", optional = true, features = ["attributes", "unstable"] }
22+
async-std = { version = "1.9.0", optional = true, features = ["attributes", "unstable"] }
2223
futures = "0.3.8"
2324
anyhow = "1.0.34"

benchmarks/src/bench/find_many.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::{convert::TryInto, path::PathBuf};
22

33
use anyhow::{bail, Result};
44
use futures::stream::StreamExt;
5-
use mongodb::{bson::Bson, Client, Collection, Database};
5+
use mongodb::{Client, Collection, Database, bson::{Bson, Document}};
66
use serde_json::Value;
77

88
use crate::{
@@ -12,7 +12,7 @@ use crate::{
1212

1313
pub struct FindManyBenchmark {
1414
db: Database,
15-
coll: Collection,
15+
coll: Collection<Document>,
1616
}
1717

1818
// Specifies the options to `FindManyBenchmark::setup` operation.

benchmarks/src/bench/find_one.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
use std::{convert::TryInto, path::PathBuf};
22

33
use anyhow::{bail, Result};
4-
use mongodb::{
5-
bson::{doc, Bson},
6-
Client,
7-
Collection,
8-
Database,
9-
};
4+
use mongodb::{Client, Collection, Database, bson::{Bson, Document, doc}};
105
use serde_json::Value;
116

127
use crate::{
@@ -17,7 +12,7 @@ use crate::{
1712
pub struct FindOneBenchmark {
1813
db: Database,
1914
num_iter: usize,
20-
coll: Collection,
15+
coll: Collection<Document>,
2116
}
2217

2318
// Specifies the options to a `FindOneBenchmark::setup` operation.

benchmarks/src/bench/insert_many.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::bench::{Benchmark, COLL_NAME, DATABASE_NAME};
1414
pub struct InsertManyBenchmark {
1515
db: Database,
1616
num_copies: usize,
17-
coll: Collection,
17+
coll: Collection<Document>,
1818
doc: Document,
1919
}
2020

@@ -45,7 +45,7 @@ impl Benchmark for InsertManyBenchmark {
4545
let mut file = spawn_blocking_and_await!(File::open(options.path))?;
4646
let json: Value = spawn_blocking_and_await!(serde_json::from_reader(&mut file))?;
4747

48-
let coll = db.collection(&COLL_NAME);
48+
let coll = db.collection(COLL_NAME.as_str());
4949

5050
Ok(InsertManyBenchmark {
5151
db,
@@ -60,13 +60,13 @@ impl Benchmark for InsertManyBenchmark {
6060

6161
async fn before_task(&mut self) -> Result<()> {
6262
self.coll.drop(None).await?;
63-
self.db.create_collection(&COLL_NAME, None).await?;
63+
self.db.create_collection(COLL_NAME.as_str(), None).await?;
6464

6565
Ok(())
6666
}
6767

6868
async fn do_task(&self) -> Result<()> {
69-
let insertions = vec![self.doc.clone(); self.num_copies];
69+
let insertions = vec![&self.doc; self.num_copies];
7070
self.coll.insert_many(insertions, None).await?;
7171

7272
Ok(())

benchmarks/src/bench/insert_one.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::bench::{Benchmark, COLL_NAME, DATABASE_NAME};
1414
pub struct InsertOneBenchmark {
1515
db: Database,
1616
num_iter: usize,
17-
coll: Collection,
17+
coll: Collection<Document>,
1818
doc: Document,
1919
}
2020

@@ -60,14 +60,14 @@ impl Benchmark for InsertOneBenchmark {
6060

6161
async fn before_task(&mut self) -> Result<()> {
6262
self.coll.drop(None).await?;
63-
self.db.create_collection(&COLL_NAME, None).await?;
63+
self.db.create_collection(COLL_NAME.as_str(), None).await?;
6464

6565
Ok(())
6666
}
6767

6868
async fn do_task(&self) -> Result<()> {
6969
for _ in 0..self.num_iter {
70-
self.coll.insert_one(self.doc.clone(), None).await?;
70+
self.coll.insert_one(&self.doc, None).await?;
7171
}
7272

7373
Ok(())

benchmarks/src/bench/json_multi_export.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::path::PathBuf;
22

33
use anyhow::Result;
44
use futures::stream::{FuturesUnordered, StreamExt, TryStreamExt};
5-
use mongodb::{bson::doc, Client, Collection, Database};
5+
use mongodb::{Client, Collection, Database, bson::{Document, doc}};
66

77
use crate::{
88
bench::{parse_json_file_to_documents, Benchmark, COLL_NAME, DATABASE_NAME},
@@ -13,7 +13,7 @@ const TOTAL_FILES: usize = 100;
1313

1414
pub struct JsonMultiExportBenchmark {
1515
db: Database,
16-
coll: Collection,
16+
coll: Collection<Document>,
1717
}
1818

1919
// Specifies the options to a `JsonMultiExportBenchmark::setup` operation.

benchmarks/src/bench/json_multi_import.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::path::PathBuf;
22

33
use anyhow::Result;
44
use futures::stream::{FuturesUnordered, StreamExt};
5-
use mongodb::{options::InsertManyOptions, Client, Collection, Database};
5+
use mongodb::{Client, Collection, Database, bson::Document, options::InsertManyOptions};
66

77
use crate::{
88
bench::{parse_json_file_to_documents, Benchmark, COLL_NAME, DATABASE_NAME},
@@ -13,7 +13,7 @@ const TOTAL_FILES: usize = 100;
1313

1414
pub struct JsonMultiImportBenchmark {
1515
db: Database,
16-
coll: Collection,
16+
coll: Collection<Document>,
1717
path: PathBuf,
1818
}
1919

@@ -43,7 +43,7 @@ impl Benchmark for JsonMultiImportBenchmark {
4343

4444
async fn before_task(&mut self) -> Result<()> {
4545
self.coll.drop(None).await?;
46-
self.db.create_collection(&COLL_NAME, None).await?;
46+
self.db.create_collection(COLL_NAME.as_str(), None).await?;
4747

4848
Ok(())
4949
}
@@ -68,7 +68,7 @@ impl Benchmark for JsonMultiImportBenchmark {
6868

6969
docs.append(&mut new_docs);
7070

71-
let opts = Some(InsertManyOptions::builder().ordered(Some(false)).build());
71+
let opts = Some(InsertManyOptions::builder().ordered(false).build());
7272
coll_ref.insert_many(docs, opts).await.unwrap();
7373
});
7474
}

benchmarks/src/fs.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ impl BufReader {
5959
}
6060

6161
pub(crate) fn lines(self) -> impl Stream<Item = std::io::Result<String>> {
62-
self.inner.lines()
62+
#[cfg(feature = "tokio-runtime")]
63+
{
64+
tokio_stream::wrappers::LinesStream::new(self.inner.lines())
65+
}
66+
67+
#[cfg(feature = "async-std-runtime")]
68+
{
69+
self.inner.lines()
70+
}
6371
}
6472
}

benchmarks/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ use crate::bench::{
3737
json_multi_export::JsonMultiExportBenchmark,
3838
json_multi_import::JsonMultiImportBenchmark,
3939
run_command::RunCommandBenchmark,
40-
TARGET_ITERATION_COUNT,
4140
};
4241

4342
lazy_static! {
@@ -52,7 +51,12 @@ fn get_nth_percentile(durations: &[Duration], n: f64) -> Duration {
5251
fn score_test(durations: Vec<Duration>, name: &str, task_size: f64, more_info: bool) -> f64 {
5352
let median = get_nth_percentile(&durations, 50.0);
5453
let score = task_size / (median.as_millis() as f64 / 1000.0);
55-
println!("TEST: {} -- Score: {}\n", name, score);
54+
println!(
55+
"TEST: {} -- Score: {}, Median Iteration Time: {:.3}ms\n",
56+
name,
57+
score,
58+
median.as_secs_f64()
59+
);
5660

5761
if more_info {
5862
println!(

src/bson_util/mod.rs

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{convert::TryFrom, time::Duration};
55
use serde::{de::Error, ser, Deserialize, Deserializer, Serialize, Serializer};
66

77
use crate::{
8-
bson::{doc, oid::ObjectId, Binary, Bson, Document, JavaScriptCodeWithScope, Regex},
8+
bson::{doc, Binary, Bson, Document, JavaScriptCodeWithScope, Regex},
99
error::{ErrorKind, Result},
1010
};
1111

@@ -31,11 +31,6 @@ pub(crate) fn get_u64(val: &Bson) -> Option<u64> {
3131
}
3232
}
3333

34-
pub(crate) fn add_id(doc: &mut Document) {
35-
doc.entry("_id".to_string())
36-
.or_insert_with(|| Bson::ObjectId(ObjectId::new()));
37-
}
38-
3934
pub(crate) fn to_bson_array(docs: &[Document]) -> Bson {
4035
Bson::Array(docs.iter().map(|doc| Bson::Document(doc.clone())).collect())
4136
}
@@ -171,7 +166,7 @@ where
171166
.ok_or_else(|| D::Error::custom(format!("could not deserialize u64 from {:?}", bson)))
172167
}
173168

174-
pub fn doc_size_bytes(doc: &Document) -> usize {
169+
pub fn doc_size_bytes(doc: &Document) -> u64 {
175170
//
176171
// * i32 length prefix (4 bytes)
177172
// * for each element:
@@ -182,19 +177,19 @@ pub fn doc_size_bytes(doc: &Document) -> usize {
182177
// * null terminator (1 byte)
183178
4 + doc
184179
.into_iter()
185-
.map(|(key, val)| 1 + key.len() + 1 + size_bytes(val))
186-
.sum::<usize>()
180+
.map(|(key, val)| 1 + key.len() as u64 + 1 + size_bytes(val))
181+
.sum::<u64>()
187182
+ 1
188183
}
189184

190-
pub fn size_bytes(val: &Bson) -> usize {
185+
pub fn size_bytes(val: &Bson) -> u64 {
191186
match val {
192187
Bson::Double(_) => 8,
193188
//
194189
// * length prefix (4 bytes)
195190
// * number of UTF-8 bytes
196191
// * null terminator (1 byte)
197-
Bson::String(s) => 4 + s.len() + 1,
192+
Bson::String(s) => 4 + s.len() as u64 + 1,
198193
// An array is serialized as a document with the keys "0", "1", "2", etc., so the size of
199194
// an array is:
200195
//
@@ -210,7 +205,7 @@ pub fn size_bytes(val: &Bson) -> usize {
210205
.iter()
211206
.enumerate()
212207
.map(|(i, val)| 1 + num_decimal_digits(i) + 1 + size_bytes(val))
213-
.sum::<usize>()
208+
.sum::<u64>()
214209
+ 1
215210
}
216211
Bson::Document(doc) => doc_size_bytes(doc),
@@ -220,21 +215,21 @@ pub fn size_bytes(val: &Bson) -> usize {
220215
// * number of UTF-8 bytes
221216
// * null terminator (1 byte)
222217
Bson::RegularExpression(Regex { pattern, options }) => {
223-
pattern.len() + 1 + options.len() + 1
218+
pattern.len() as u64 + 1 + options.len() as u64 + 1
224219
}
225220
//
226221
// * length prefix (4 bytes)
227222
// * number of UTF-8 bytes
228223
// * null terminator (1 byte)
229-
Bson::JavaScriptCode(code) => 4 + code.len() + 1,
224+
Bson::JavaScriptCode(code) => 4 + code.len() as u64 + 1,
230225
//
231226
// * i32 length prefix (4 bytes)
232227
// * i32 length prefix for code (4 bytes)
233228
// * number of UTF-8 bytes in code
234229
// * null terminator for code (1 byte)
235230
// * length of document
236231
Bson::JavaScriptCodeWithScope(JavaScriptCodeWithScope { code, scope }) => {
237-
4 + 4 + code.len() + 1 + doc_size_bytes(scope)
232+
4 + 4 + code.len() as u64 + 1 + doc_size_bytes(scope)
238233
}
239234
Bson::Int32(_) => 4,
240235
Bson::Int64(_) => 8,
@@ -243,14 +238,14 @@ pub fn size_bytes(val: &Bson) -> usize {
243238
// * i32 length prefix (4 bytes)
244239
// * subtype (1 byte)
245240
// * number of bytes
246-
Bson::Binary(Binary { bytes, .. }) => 4 + 1 + bytes.len(),
241+
Bson::Binary(Binary { bytes, .. }) => 4 + 1 + bytes.len() as u64,
247242
Bson::ObjectId(_) => 12,
248243
Bson::DateTime(_) => 8,
249244
//
250245
// * i32 length prefix (4 bytes)
251246
// * subtype (1 byte)
252247
// * number of UTF-8 bytes
253-
Bson::Symbol(s) => 4 + 1 + s.len(),
248+
Bson::Symbol(s) => 4 + 1 + s.len() as u64,
254249
Bson::Decimal128(..) => 128 / 8,
255250
Bson::Undefined | Bson::MaxKey | Bson::MinKey => 0,
256251
// DbPointer doesn't have public details exposed by the BSON library, but it comprises of a
@@ -267,7 +262,19 @@ pub fn size_bytes(val: &Bson) -> usize {
267262
}
268263
}
269264

270-
fn num_decimal_digits(n: usize) -> usize {
265+
/// The size in bytes of the provided document's entry in a BSON array at the given index.
266+
pub(crate) fn array_entry_size_bytes(index: usize, doc: &Document) -> u64 {
267+
//
268+
// * type (1 byte)
269+
// * number of decimal digits in key
270+
// * null terminator for the key (1 byte)
271+
// * size of value
272+
1 + num_decimal_digits(index) + 1 + doc_size_bytes(&doc)
273+
}
274+
275+
/// The number of digits in `n` in base 10.
276+
/// Useful for calculating the size of an array entry in BSON.
277+
fn num_decimal_digits(n: usize) -> u64 {
271278
let mut digits = 1;
272279
let mut curr = 10;
273280

@@ -332,6 +339,6 @@ mod test {
332339
let mut serialized_bytes = Vec::new();
333340
doc.to_writer(&mut serialized_bytes).unwrap();
334341

335-
assert_eq!(size_bytes, serialized_bytes.len());
342+
assert_eq!(size_bytes, serialized_bytes.len() as u64);
336343
}
337344
}

0 commit comments

Comments
 (0)