Skip to content

Commit c312ec4

Browse files
konardclaude
andcommitted
Split benched.rs into benched/ subdirectory with separate backend files
Reorganized src/benched.rs into: - src/benched/mod.rs - Benched trait definition with documentation - src/benched/doublets_benched.rs - Doublets storage implementations - src/benched/psql_benched.rs - PostgreSQL storage implementations This follows the same pattern used in Neo4jVSDoublets for clear separation between backend implementations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8214027 commit c312ec4

4 files changed

Lines changed: 201 additions & 111 deletions

File tree

rust/src/benched.rs

Lines changed: 0 additions & 111 deletions
This file was deleted.
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
//! # Doublets Backend Implementations
2+
//!
3+
//! This module contains [`Benched`] trait implementations for all Doublets
4+
//! storage variants.
5+
//!
6+
//! ## Storage Backends
7+
//!
8+
//! | Backend | Description |
9+
//! |----------------------------------|--------------------------------|
10+
//! | `unit::Store<T, FileMapped<_>>` | File-mapped unit storage |
11+
//! | `unit::Store<T, Alloc<_>>` | In-memory unit storage |
12+
//! | `split::Store<T, FileMapped<_>>` | File-mapped split storage |
13+
//! | `split::Store<T, Alloc<_>>` | In-memory split storage |
14+
//!
15+
//! ## Cleanup Strategy
16+
//!
17+
//! Each backend's `unfork()` implementation calls `delete_all()` to clean up
18+
//! all links created during the benchmark iteration.
19+
20+
use crate::{map_file, Result};
21+
use doublets::{
22+
data::LinkType,
23+
mem::{Alloc, FileMapped},
24+
split::{self, DataPart, IndexPart},
25+
unit::{self, LinkPart},
26+
Doublets,
27+
};
28+
use std::alloc::Global;
29+
30+
use super::Benched;
31+
32+
/// Benched implementation for file-mapped unit storage.
33+
impl<T: LinkType> Benched for unit::Store<T, FileMapped<LinkPart<T>>> {
34+
type Builder<'a> = &'a str;
35+
36+
fn setup(builder: Self::Builder<'_>) -> Result<Self> {
37+
Self::new(map_file(builder)?).map_err(Into::into)
38+
}
39+
40+
unsafe fn unfork(&mut self) {
41+
let _ = self.delete_all();
42+
}
43+
}
44+
45+
/// Benched implementation for in-memory unit storage.
46+
impl<T: LinkType> Benched for unit::Store<T, Alloc<LinkPart<T>, Global>> {
47+
type Builder<'a> = ();
48+
49+
fn setup(_: Self::Builder<'_>) -> Result<Self> {
50+
Self::new(Alloc::new(Global)).map_err(Into::into)
51+
}
52+
53+
unsafe fn unfork(&mut self) {
54+
let _ = self.delete_all();
55+
}
56+
}
57+
58+
/// Benched implementation for file-mapped split storage.
59+
impl<T: LinkType> Benched for split::Store<T, FileMapped<DataPart<T>>, FileMapped<IndexPart<T>>> {
60+
type Builder<'a> = (&'a str, &'a str);
61+
62+
fn setup((data, index): Self::Builder<'_>) -> Result<Self> {
63+
Self::new(map_file(data)?, map_file(index)?).map_err(Into::into)
64+
}
65+
66+
unsafe fn unfork(&mut self) {
67+
let _ = self.delete_all();
68+
}
69+
}
70+
71+
/// Benched implementation for in-memory split storage.
72+
impl<T: LinkType> Benched
73+
for split::Store<T, Alloc<DataPart<T>, Global>, Alloc<IndexPart<T>, Global>>
74+
{
75+
type Builder<'a> = ();
76+
77+
fn setup(_: Self::Builder<'_>) -> Result<Self> {
78+
Self::new(Alloc::new(Global), Alloc::new(Global)).map_err(Into::into)
79+
}
80+
81+
unsafe fn unfork(&mut self) {
82+
let _ = self.delete_all();
83+
}
84+
}

rust/src/benched/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//! # Benchmark Lifecycle Management
2+
//!
3+
//! This module defines the [`Benched`] trait that provides setup/teardown lifecycle
4+
//! for benchmark iterations. Both PostgreSQL and Doublets storage backends implement
5+
//! this trait to enable fair benchmarking.
6+
//!
7+
//! ## Module Structure
8+
//!
9+
//! The implementations are split into separate files for clear comparison:
10+
//!
11+
//! - **[`doublets_benched`]** - Doublets storage backend implementations
12+
//! - **[`psql_benched`]** - PostgreSQL storage backend implementations
13+
14+
mod doublets_benched;
15+
mod psql_benched;
16+
17+
use crate::Fork;
18+
19+
/// Trait for types that can be benchmarked.
20+
///
21+
/// Provides the setup/teardown lifecycle for benchmark iterations:
22+
/// - [`Benched::setup`] - Initialize the storage backend
23+
/// - [`Benched::fork`] - Create an isolated environment for a single iteration
24+
/// - [`Benched::unfork`] - Clean up after the iteration
25+
pub trait Benched: Sized {
26+
/// Builder parameter type for constructing this storage.
27+
type Builder<'params>;
28+
29+
/// Set up a new storage backend for benchmarking.
30+
fn setup<'a>(builder: Self::Builder<'a>) -> crate::Result<Self>;
31+
32+
/// Create a fork for a single benchmark iteration.
33+
///
34+
/// This allows each iteration to run in isolation without affecting others.
35+
fn fork(&mut self) -> Fork<Self> {
36+
Fork(self)
37+
}
38+
39+
/// Clean up after a benchmark iteration.
40+
///
41+
/// # Safety
42+
/// This method may perform unsafe operations like clearing all data.
43+
unsafe fn unfork(&mut self);
44+
}

rust/src/benched/psql_benched.rs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//! # PostgreSQL Backend Implementations
2+
//!
3+
//! This module contains [`Benched`] trait implementations for PostgreSQL
4+
//! storage variants.
5+
//!
6+
//! ## Storage Backends
7+
//!
8+
//! | Backend | Description |
9+
//! |----------------------------|-------------------------------------|
10+
//! | `Exclusive<Client<T>>` | Direct SQL execution (no transaction) |
11+
//! | `Exclusive<Transaction<T>>`| SQL execution within transaction |
12+
//!
13+
//! ## Table Management
14+
//!
15+
//! Each backend's lifecycle manages a `links` table:
16+
//! - `fork()` calls `CREATE TABLE` to set up the table
17+
//! - `unfork()` calls `DROP TABLE` to clean up
18+
//!
19+
//! ## SQL Schema
20+
//!
21+
//! The `links` table has the following structure:
22+
//! ```sql
23+
//! CREATE TABLE links (
24+
//! id BIGINT PRIMARY KEY,
25+
//! source BIGINT NOT NULL,
26+
//! target BIGINT NOT NULL
27+
//! )
28+
//! ```
29+
30+
use crate::{Client, Exclusive, Fork, Result, Sql, Transaction};
31+
use doublets::data::LinkType;
32+
33+
use super::Benched;
34+
35+
/// Benched implementation for PostgreSQL client (non-transactional).
36+
impl<T: LinkType> Benched for Exclusive<Client<T>> {
37+
type Builder<'a> = ();
38+
39+
fn setup(_: Self::Builder<'_>) -> Result<Self> {
40+
// Safety: Exclusive wrapper ensures single-threaded access
41+
unsafe { Ok(Exclusive::new(crate::connect()?)) }
42+
}
43+
44+
fn fork(&mut self) -> Fork<Self> {
45+
let _ = self.create_table();
46+
Fork(self)
47+
}
48+
49+
unsafe fn unfork(&mut self) {
50+
let _ = self.drop_table();
51+
}
52+
}
53+
54+
/// Benched implementation for PostgreSQL transaction.
55+
impl<'a, T: LinkType> Benched for Exclusive<Transaction<'a, T>> {
56+
type Builder<'b> = &'a mut Client<T>;
57+
58+
fn setup(builder: Self::Builder<'_>) -> Result<Self> {
59+
let mut transaction = builder.transaction()?;
60+
transaction.create_table()?;
61+
// Safety: Exclusive wrapper ensures single-threaded access
62+
unsafe { Ok(Exclusive::new(transaction)) }
63+
}
64+
65+
fn fork(&mut self) -> Fork<Self> {
66+
let _ = self.create_table();
67+
Fork(self)
68+
}
69+
70+
unsafe fn unfork(&mut self) {
71+
let _ = self.drop_table();
72+
}
73+
}

0 commit comments

Comments
 (0)