Skip to content

Commit bcee44e

Browse files
benjirewissaghm
authored andcommitted
RUST-611 direct copy of benchmarks from unreviewed-impl
1 parent a92707c commit bcee44e

File tree

14 files changed

+1125
-0
lines changed

14 files changed

+1125
-0
lines changed

benchmarks/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/target
2+
**/*.rs.bk
3+
/data

benchmarks/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "rust-driver-bench"
3+
version = "0.1.0"
4+
authors = ["benjirewis <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
mongodb = { path = ".." }
9+
bson = "0.13.0"
10+
serde_json = "1.0.39"
11+
lazy_static = "1.3.0"
12+
num_cpus = "1.10.1"
13+
clap = "2.33.0"
14+
indicatif = "0.11.0"

benchmarks/README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Rust Driver Benchmark Suite
2+
3+
This suite implements the benchmarks described in this (spec)[https://github.com/mongodb/specifications/blob/master/source/benchmarking/benchmarking.rst].
4+
5+
In order to run the microbenchmarks, first run `../etc/microbenchmark-test-data.sh` to download the data.
6+
7+
Note: make sure you run the download script and the microbenchmarks binary from the benchmark root (the directory containing this README).
8+
9+
To execute all benchmarks, run `cargo run --release` with a mongod instance running on port 27017 (or, you can specify a custom
10+
connection string by setting the `MONGODB_URI` environment variable). You can specify a custom name for the used database or
11+
collection by setting the `DATABASE_NAME` or `COLL_NAME` environment variables respectively.
12+
13+
Additionally, you can specify custom time frames for the benchmarks by setting the `MAX_EXECUTION_TIME`, `MIN_EXECUTION_TIME`
14+
and `MAX_ITERATIONS` environment variables.
15+
16+
Run `cargo run --release -- --help` to see a full list of testing options.
17+
18+
When running the benchmarks with the `--ids` flag, you can refer to each benchmark by their unique id. You can refer to multiple
19+
benchmarks by separating each benchmark's id with a comma. For example `cargo run --release -- --ids 1,2,3,4` would run all
20+
the single-doc benchmarks. By default, all benchmarks are executed. The table below lists each benchmark's id.
21+
22+
| Benchmark | ID |
23+
|--------------------------------|----|
24+
| Run command | 1 |
25+
| Find one by ID | 2 |
26+
| Small doc insertOne | 3 |
27+
| Large doc insertOne | 4 |
28+
| Find many and empty the cursor | 5 |
29+
| Small doc bulk insert | 6 |
30+
| Large doc bulk insert | 7 |
31+
| LDJSON multi-file import | 8 |
32+
| LDJSON multi-file export | 9 |
33+
| All benchmarks | all|
34+
35+
Note that in order to compare against the other drivers, an inMemory mongod instance should be used.
36+
37+
At this point, BSON and GridFS benchmarks are not implemented because we do not own the Rust BSON library, and GridFS has not been implemented
38+
in the driver.
39+
40+
Also note that the parallel benchmarks are implemented to mirror the C++ driver's interpretation of the spec.

benchmarks/rustfmt.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../rustfmt.toml

benchmarks/src/bench/find_many.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use std::{fs::File, path::PathBuf};
2+
3+
use bson::Bson;
4+
use mongodb::{Client, Collection, Database};
5+
use serde_json::Value;
6+
7+
use crate::{
8+
bench::{Benchmark, COLL_NAME, DATABASE_NAME},
9+
error::{Error, Result},
10+
};
11+
12+
pub struct FindManyBenchmark {
13+
db: Database,
14+
coll: Collection,
15+
}
16+
17+
// Specifies the options to `FindManyBenchmark::setup` operation.
18+
pub struct Options {
19+
pub num_iter: usize,
20+
pub path: PathBuf,
21+
pub uri: String,
22+
}
23+
24+
impl Benchmark for FindManyBenchmark {
25+
type Options = Options;
26+
27+
fn setup(options: Self::Options) -> Result<Self> {
28+
let client = Client::with_uri_str(&options.uri)?;
29+
let db = client.database(&DATABASE_NAME);
30+
db.drop()?;
31+
32+
let mut file = File::open(options.path)?;
33+
34+
let json: Value = serde_json::from_reader(&mut file)?;
35+
let doc = match json.into() {
36+
Bson::Document(doc) => doc,
37+
_ => return Err(Error::UnexpectedJson("invalid json test file".to_string())),
38+
};
39+
40+
let coll = db.collection(&COLL_NAME);
41+
let docs = vec![doc.clone(); options.num_iter];
42+
coll.insert_many(docs, None)?;
43+
44+
Ok(FindManyBenchmark { db, coll })
45+
}
46+
47+
fn do_task(&self) -> Result<()> {
48+
let cursor = self.coll.find(None, None)?;
49+
for doc in cursor {
50+
doc?;
51+
}
52+
53+
Ok(())
54+
}
55+
56+
fn teardown(&self) -> Result<()> {
57+
self.db.drop()?;
58+
59+
Ok(())
60+
}
61+
}

benchmarks/src/bench/find_one.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use std::{fs::File, path::PathBuf};
2+
3+
use bson::Bson;
4+
use mongodb::{options::FindOptions, Client, Collection, Database};
5+
use serde_json::Value;
6+
7+
use crate::{
8+
bench::{Benchmark, COLL_NAME, DATABASE_NAME},
9+
error::{Error, Result},
10+
};
11+
12+
pub struct FindOneBenchmark {
13+
db: Database,
14+
num_iter: usize,
15+
coll: Collection,
16+
}
17+
18+
// Specifies the options to a `FindOneBenchmark::setup` operation.
19+
pub struct Options {
20+
pub num_iter: usize,
21+
pub path: PathBuf,
22+
pub uri: String,
23+
}
24+
25+
impl Benchmark for FindOneBenchmark {
26+
type Options = Options;
27+
28+
fn setup(options: Self::Options) -> Result<Self> {
29+
let client = Client::with_uri_str(&options.uri)?;
30+
let db = client.database(&DATABASE_NAME);
31+
db.drop()?;
32+
33+
let mut file = File::open(options.path)?;
34+
35+
let json: Value = serde_json::from_reader(&mut file)?;
36+
let mut doc = match json.into() {
37+
Bson::Document(doc) => doc,
38+
_ => return Err(Error::UnexpectedJson("invalid json test file".to_string())),
39+
};
40+
41+
let coll = db.collection(&COLL_NAME);
42+
for i in 0..options.num_iter {
43+
doc.insert("_id", i as i32);
44+
coll.insert_one(doc.clone(), None)?;
45+
}
46+
47+
Ok(FindOneBenchmark {
48+
db,
49+
num_iter: options.num_iter,
50+
coll,
51+
})
52+
}
53+
54+
fn do_task(&self) -> Result<()> {
55+
let find_options = FindOptions::builder().limit(Some(1)).build();
56+
for i in 0..self.num_iter {
57+
let mut cursor = self
58+
.coll
59+
.find(Some(doc! { "_id": i as i32 }), Some(find_options.clone()))?;
60+
let _doc = cursor.next();
61+
}
62+
63+
Ok(())
64+
}
65+
66+
fn teardown(&self) -> Result<()> {
67+
self.db.drop()?;
68+
69+
Ok(())
70+
}
71+
}

benchmarks/src/bench/insert_many.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
use std::{fs::File, path::PathBuf};
2+
3+
use bson::{Bson, Document};
4+
use mongodb::{Client, Collection, Database};
5+
use serde_json::Value;
6+
7+
use crate::{
8+
bench::{Benchmark, COLL_NAME, DATABASE_NAME},
9+
error::{Error, Result},
10+
};
11+
12+
pub struct InsertManyBenchmark {
13+
db: Database,
14+
num_copies: usize,
15+
coll: Collection,
16+
doc: Document,
17+
}
18+
19+
// Specifies the options to a `InsertManyBenchmark::setup` operation.
20+
pub struct Options {
21+
pub num_copies: usize,
22+
pub path: PathBuf,
23+
pub uri: String,
24+
}
25+
26+
impl Benchmark for InsertManyBenchmark {
27+
type Options = Options;
28+
29+
fn setup(options: Self::Options) -> Result<Self> {
30+
let client = Client::with_uri_str(&options.uri)?;
31+
let db = client.database(&DATABASE_NAME);
32+
db.drop()?;
33+
34+
let mut file = File::open(options.path)?;
35+
36+
let json: Value = serde_json::from_reader(&mut file)?;
37+
38+
let coll = db.collection(&COLL_NAME);
39+
40+
Ok(InsertManyBenchmark {
41+
db,
42+
num_copies: options.num_copies,
43+
coll,
44+
doc: match json.into() {
45+
Bson::Document(doc) => doc,
46+
_ => return Err(Error::UnexpectedJson("invalid json test file".to_string())),
47+
},
48+
})
49+
}
50+
51+
fn before_task(&mut self) -> Result<()> {
52+
self.coll.drop()?;
53+
self.db.create_collection(&COLL_NAME, None)?;
54+
55+
Ok(())
56+
}
57+
58+
fn do_task(&self) -> Result<()> {
59+
let insertions = vec![self.doc.clone(); self.num_copies];
60+
self.coll.insert_many(insertions, None)?;
61+
62+
Ok(())
63+
}
64+
65+
fn teardown(&self) -> Result<()> {
66+
self.db.drop()?;
67+
68+
Ok(())
69+
}
70+
}

benchmarks/src/bench/insert_one.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use std::{fs::File, path::PathBuf};
2+
3+
use bson::{Bson, Document};
4+
use mongodb::{Client, Collection, Database};
5+
use serde_json::Value;
6+
7+
use crate::{
8+
bench::{Benchmark, COLL_NAME, DATABASE_NAME},
9+
error::{Error, Result},
10+
};
11+
12+
pub struct InsertOneBenchmark {
13+
db: Database,
14+
num_iter: usize,
15+
coll: Collection,
16+
doc: Document,
17+
}
18+
19+
// Specifies the options to a `InsertOneBenchmark::setup` operation.
20+
pub struct Options {
21+
pub num_iter: usize,
22+
pub path: PathBuf,
23+
pub uri: String,
24+
}
25+
26+
impl Benchmark for InsertOneBenchmark {
27+
type Options = Options;
28+
29+
fn setup(options: Self::Options) -> Result<Self> {
30+
let client = Client::with_uri_str(&options.uri)?;
31+
let db = client.database(&DATABASE_NAME);
32+
db.drop()?;
33+
34+
let mut file = File::open(options.path)?;
35+
36+
let json: Value = serde_json::from_reader(&mut file)?;
37+
38+
let coll = db.collection(&COLL_NAME);
39+
40+
Ok(InsertOneBenchmark {
41+
db,
42+
num_iter: options.num_iter,
43+
coll,
44+
doc: match json.into() {
45+
Bson::Document(doc) => doc,
46+
_ => return Err(Error::UnexpectedJson("invalid json test file".to_string())),
47+
},
48+
})
49+
}
50+
51+
fn before_task(&mut self) -> Result<()> {
52+
self.coll.drop()?;
53+
self.db.create_collection(&COLL_NAME, None)?;
54+
55+
Ok(())
56+
}
57+
58+
fn do_task(&self) -> Result<()> {
59+
for _ in 0..self.num_iter {
60+
self.coll.insert_one(self.doc.clone(), None)?;
61+
}
62+
63+
Ok(())
64+
}
65+
66+
fn teardown(&self) -> Result<()> {
67+
self.db.drop()?;
68+
69+
Ok(())
70+
}
71+
}

0 commit comments

Comments
 (0)