Skip to content

Commit ae392c9

Browse files
committed
graph: Add a tool to test how long adding to a RowGroup takes
1 parent ec2fef9 commit ae392c9

File tree

2 files changed

+139
-0
lines changed

2 files changed

+139
-0
lines changed

graph/examples/append_row.rs

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
use std::{collections::HashSet, sync::Arc, time::Instant};
2+
3+
use anyhow::anyhow;
4+
use clap::Parser;
5+
use graph::{
6+
components::store::write::{EntityModification, RowGroupForPerfTest as RowGroup},
7+
data::{
8+
store::{Id, Value},
9+
subgraph::DeploymentHash,
10+
value::Word,
11+
},
12+
schema::{EntityType, InputSchema},
13+
};
14+
use lazy_static::lazy_static;
15+
use rand::{rng, Rng};
16+
17+
#[derive(Parser)]
18+
#[clap(
19+
name = "append_row",
20+
about = "Measure time it takes to append rows to a row group"
21+
)]
22+
struct Opt {
23+
/// Number of repetitions of the test
24+
#[clap(short, long, default_value = "5")]
25+
niter: usize,
26+
/// Number of rows
27+
#[clap(short, long, default_value = "10000")]
28+
rows: usize,
29+
/// Number of blocks
30+
#[clap(short, long, default_value = "300")]
31+
blocks: usize,
32+
/// Number of ids
33+
#[clap(short, long, default_value = "500")]
34+
ids: usize,
35+
}
36+
37+
// A very fake schema that allows us to get the entity types we need
38+
const GQL: &str = r#"
39+
type Thing @entity { id: ID!, count: Int! }
40+
type RowGroup @entity { id: ID! }
41+
type Entry @entity { id: ID! }
42+
"#;
43+
lazy_static! {
44+
static ref DEPLOYMENT: DeploymentHash = DeploymentHash::new("batchAppend").unwrap();
45+
static ref SCHEMA: InputSchema = InputSchema::parse_latest(GQL, DEPLOYMENT.clone()).unwrap();
46+
static ref THING_TYPE: EntityType = SCHEMA.entity_type("Thing").unwrap();
47+
static ref ROW_GROUP_TYPE: EntityType = SCHEMA.entity_type("RowGroup").unwrap();
48+
static ref ENTRY_TYPE: EntityType = SCHEMA.entity_type("Entry").unwrap();
49+
}
50+
51+
pub fn main() -> anyhow::Result<()> {
52+
let opt = Opt::parse();
53+
let next_block = opt.blocks as f64 / opt.rows as f64;
54+
for _ in 0..opt.niter {
55+
let ids = (0..opt.ids)
56+
.map(|n| Id::String(Word::from(format!("00{n}010203040506"))))
57+
.collect::<Vec<_>>();
58+
let mut existing: HashSet<Id> = HashSet::new();
59+
let mut mods = Vec::new();
60+
let mut block = 0;
61+
let mut block_pos = Vec::new();
62+
for _ in 0..opt.rows {
63+
if rng().random_bool(next_block) {
64+
block += 1;
65+
block_pos.clear();
66+
}
67+
68+
let mut attempt = 0;
69+
let pos = loop {
70+
if attempt > 20 {
71+
return Err(anyhow!(
72+
"Failed to find a position in 20 attempts. Increase `ids`"
73+
));
74+
}
75+
attempt += 1;
76+
let pos = rng().random_range(0..opt.ids);
77+
if block_pos.contains(&pos) {
78+
continue;
79+
}
80+
block_pos.push(pos);
81+
break pos;
82+
};
83+
let id = &ids[pos];
84+
let data = vec![
85+
(Word::from("id"), Value::String(id.to_string())),
86+
(Word::from("count"), Value::Int(block as i32)),
87+
];
88+
let data = Arc::new(SCHEMA.make_entity(data).unwrap());
89+
let md = if existing.contains(id) {
90+
EntityModification::Overwrite {
91+
key: THING_TYPE.key(id.clone()),
92+
data,
93+
block,
94+
end: None,
95+
}
96+
} else {
97+
existing.insert(id.clone());
98+
EntityModification::Insert {
99+
key: THING_TYPE.key(id.clone()),
100+
data,
101+
block,
102+
end: None,
103+
}
104+
};
105+
mods.push(md);
106+
}
107+
let mut group = RowGroup::new(THING_TYPE.clone(), false);
108+
109+
let start = Instant::now();
110+
for md in mods {
111+
group.append_row(md).unwrap();
112+
}
113+
let elapsed = start.elapsed();
114+
println!(
115+
"Adding {} rows with {} ids across {} blocks took {:?}",
116+
opt.rows,
117+
existing.len(),
118+
block,
119+
elapsed
120+
);
121+
}
122+
Ok(())
123+
}

graph/src/components/store/write.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,22 @@ impl RowGroup {
501501
}
502502
}
503503

504+
pub struct RowGroupForPerfTest(RowGroup);
505+
506+
impl RowGroupForPerfTest {
507+
pub fn new(entity_type: EntityType, immutable: bool) -> Self {
508+
Self(RowGroup::new(entity_type, immutable))
509+
}
510+
511+
pub fn push(&mut self, emod: EntityModification, block: BlockNumber) -> Result<(), StoreError> {
512+
self.0.push(emod, block)
513+
}
514+
515+
pub fn append_row(&mut self, row: EntityModification) -> Result<(), StoreError> {
516+
self.0.append_row(row)
517+
}
518+
}
519+
504520
struct ClampsByBlockIterator<'a> {
505521
position: usize,
506522
rows: &'a [EntityModification],

0 commit comments

Comments
 (0)