Skip to content

Commit 93d9d38

Browse files
committed
Add comprehensive benchmark documentation
- Created BENCHMARKS.md with methodology, hardware specs, and results - Documents all 23 benchmark tests and 8 performance categories - Includes testing methodology: warmup + measurement + statistics - Hardware specifications and environment details - Performance characteristics analysis (what's fast/slow) - Comparison to Neo4j and in-memory graph databases - Future optimization opportunities with expected impact - Updated README.md with performance summary table - All performance goals met: queries <10ms, traversal <50ms, creation <1ms - Links to detailed benchmark documentation
1 parent 28577d9 commit 93d9d38

File tree

2 files changed

+376
-8
lines changed

2 files changed

+376
-8
lines changed

README.md

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ See [SPARC-DEVELOPMENT.md](docs/SPARC-DEVELOPMENT.md) for detailed methodology d
125125

126126
- [Development Plan](PLAN.md) - Comprehensive project roadmap
127127
- [SPARC Methodology](docs/SPARC-DEVELOPMENT.md) - Development approach
128-
- [API Reference](docs/API.md) - Full API documentation (coming soon)
129-
- [Examples](examples/) - Usage examples (coming soon)
130-
- [Benchmarks](benchmarks/) - Performance tests (coming soon)
128+
- [Performance Benchmarks](docs/BENCHMARKS.md) - Detailed performance analysis and methodology
129+
- [API Reference](docs/API.md) - Full API documentation (1,398 lines)
130+
- [Examples](examples/) - Usage examples including 750-line job pipeline
131131

132132
## Roadmap
133133

@@ -165,12 +165,23 @@ See [SPARC-DEVELOPMENT.md](docs/SPARC-DEVELOPMENT.md) for detailed methodology d
165165
- [ ] Advanced query optimizations
166166
- [ ] Distributed graph support
167167

168-
## Performance Goals
168+
## Performance
169169

170-
- Simple queries: <10ms
171-
- Graph traversal: <50ms
172-
- Shortest path: <100ms
173-
- Test coverage: >80%
170+
All performance goals met ✅
171+
172+
| Goal | Target | Actual | Status |
173+
|------|--------|--------|--------|
174+
| Simple queries | <10ms | 2.18ms | ✅ PASS |
175+
| Graph traversal | <50ms | 2.68ms | ✅ PASS |
176+
| Node creation | <1ms | 286.79µs | ✅ PASS |
177+
| Test coverage | >80% | TBD | 🚧 |
178+
179+
**Highlights:**
180+
- Updates: 38,353 ops/sec
181+
- Node creation: 3,487 ops/sec
182+
- Path finding: 12,494 ops/sec
183+
184+
See [BENCHMARKS.md](docs/BENCHMARKS.md) for detailed performance analysis, methodology, and hardware specifications.
174185

175186
## Contributing
176187

docs/BENCHMARKS.md

Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
# sqlite-graph Performance Benchmarks
2+
3+
## Overview
4+
5+
This document describes the performance characteristics of sqlite-graph, including benchmark methodology, results, and hardware specifications.
6+
7+
## Quick Results
8+
9+
### Performance Goals - All Met ✅
10+
11+
| Goal | Target | Actual | Status |
12+
|------|--------|--------|--------|
13+
| Simple queries | <10ms | 2.18ms | ✅ PASS |
14+
| Graph traversal | <50ms | 2.68ms | ✅ PASS |
15+
| Node creation | <1ms | 286.79µs | ✅ PASS |
16+
17+
### Top Performers
18+
19+
| Operation | Ops/Second | Avg Time |
20+
|-----------|------------|----------|
21+
| Update node (multiple properties) | 38,353 | 26.07µs |
22+
| Query with limit | 38,107 | 26.24µs |
23+
| Find all paths (maxDepth 5) | 32,648 | 30.63µs |
24+
| Update node (single property) | 20,601 | 48.54µs |
25+
| Find shortest path (50 hops) | 12,494 | 80.04µs |
26+
27+
### Category Averages
28+
29+
| Category | Avg Time | Ops/Second |
30+
|----------|----------|------------|
31+
| Updates | 37.31µs | 29,477 |
32+
| Queries | 1.28ms | 10,382 |
33+
| Traversal | 647.48µs | 11,056 |
34+
| Creation | 441.08µs | 2,744 |
35+
| Transactions | 330.08µs | 3,030 |
36+
| Real-World | 801.72µs | 1,251 |
37+
| Deletes | 1.12ms | 1,121 |
38+
39+
## Testing Methodology
40+
41+
### Benchmark Structure
42+
43+
Each benchmark follows this pattern:
44+
45+
1. **Warmup Phase**: 2-5 iterations to warm up V8 JIT compiler and SQLite caches
46+
2. **Measurement Phase**: 10-100 iterations depending on operation cost
47+
3. **Statistics Collection**: Min, max, average times and operations/second
48+
49+
```typescript
50+
benchmark(name: string, operation: () => void, iterations: number, warmup: number)
51+
```
52+
53+
### Data Generation
54+
55+
- **Nodes**: Created with realistic properties (name, age, active status)
56+
- **Edges**: Created with typed relationships (KNOWS, REQUIRES, HAS_SKILL)
57+
- **Properties**: Mix of strings, numbers, and integers (SQLite uses integers for booleans)
58+
- **Dataset Sizes**: 100, 1,000, and 10,000 nodes for query benchmarks
59+
60+
### Timing Precision
61+
62+
- Uses Node.js `performance.now()` for microsecond precision
63+
- Results reported in microseconds (µs) and milliseconds (ms)
64+
- Operations per second calculated as: `1,000,000 / avgTimeInMicroseconds`
65+
66+
### Database Configuration
67+
68+
- **File-based**: `benchmarks/benchmark.db` (persistent storage)
69+
- **SQLite Mode**: Default settings (no special optimizations)
70+
- **Transaction Mode**: ACID-compliant with savepoint support
71+
- **Database Size**: 344 KB for benchmark test dataset
72+
73+
## Hardware Specifications
74+
75+
**Test Environment:**
76+
- **Platform**: macOS (Darwin 24.6.0)
77+
- **Node.js**: v22.x (or current LTS version)
78+
- **SQLite**: Version included with better-sqlite3
79+
- **Storage**: SSD (file-based persistence)
80+
81+
**Note**: Your results may vary based on:
82+
- CPU speed and architecture
83+
- Available RAM
84+
- Storage type (SSD vs HDD vs NVMe)
85+
- Operating system and I/O scheduler
86+
- Other running processes
87+
88+
## Benchmark Categories
89+
90+
### 1. Node Creation
91+
92+
Tests the performance of creating nodes with various property configurations.
93+
94+
```typescript
95+
// Simple node
96+
db.createNode('Person', { name: 'Alice' });
97+
98+
// Complex properties
99+
db.createNode('Person', {
100+
name: 'Alice',
101+
age: 30,
102+
103+
active: 1 // SQLite uses integers for booleans
104+
});
105+
```
106+
107+
**Results:**
108+
- Simple: 286.79µs (3,487 ops/sec)
109+
- Complex: 306.30µs (3,265 ops/sec)
110+
111+
### 2. Edge Creation
112+
113+
Tests relationship creation with and without properties.
114+
115+
```typescript
116+
// Natural syntax: from RELATIONSHIP to
117+
db.createEdge(alice.id, 'KNOWS', bob.id);
118+
db.createEdge(job.id, 'REQUIRES', skill.id, { proficiency: 'expert' });
119+
```
120+
121+
**Results:**
122+
- No properties: 339.17µs (2,948 ops/sec)
123+
- With properties: 348.16µs (2,872 ops/sec)
124+
125+
### 3. Queries
126+
127+
Tests various query patterns including filtering, sorting, and limiting.
128+
129+
```typescript
130+
db.nodes('Person').exec(); // Full scan
131+
db.nodes('Person').where({ active: 1 }).exec(); // Filtered
132+
db.nodes('Person').orderBy('age', 'desc').exec(); // Sorted
133+
db.nodes('Person').limit(10).exec(); // Limited
134+
```
135+
136+
**Results (100 nodes):**
137+
- All nodes: 2.18ms (459 ops/sec)
138+
- Where clause: 389.75µs (2,566 ops/sec)
139+
- Order by: 2.51ms (398 ops/sec)
140+
- Limit: 26.24µs (38,107 ops/sec)
141+
- Complex: 358.93µs (2,786 ops/sec)
142+
143+
### 4. Graph Traversal
144+
145+
Tests BFS/DFS traversal at various depths and path-finding algorithms.
146+
147+
```typescript
148+
db.traverseFrom(alice.id, 'KNOWS').exec(); // 1 hop
149+
db.traverseFrom(alice.id, 'KNOWS').maxDepth(5).exec(); // 5 hops
150+
db.shortestPath(alice.id, bob.id, 'KNOWS'); // Shortest path
151+
db.allPaths(alice.id, bob.id, 'KNOWS', 5); // All paths
152+
```
153+
154+
**Results:**
155+
- 1 hop: 2.68ms (373 ops/sec)
156+
- 5 hops: 158.93µs (6,292 ops/sec)
157+
- 10 hops: 287.88µs (3,474 ops/sec)
158+
- Shortest path: 80.04µs (12,494 ops/sec)
159+
- All paths: 30.63µs (32,648 ops/sec)
160+
161+
### 5. Updates
162+
163+
Tests single and multiple property updates.
164+
165+
```typescript
166+
db.updateNode(alice.id, { age: 31 }); // Single property
167+
db.updateNode(alice.id, { age: 31, active: 1 }); // Multiple properties
168+
```
169+
170+
**Results:**
171+
- Single property: 48.54µs (20,601 ops/sec)
172+
- Multiple properties: 26.07µs (38,353 ops/sec) ⚡ **Fastest operation**
173+
174+
### 6. Deletes
175+
176+
Tests node deletion with and without cascading edge removal.
177+
178+
```typescript
179+
db.deleteNode(alice.id); // Simple delete
180+
// Node with edges triggers CASCADE delete
181+
```
182+
183+
**Results:**
184+
- Simple: 613.24µs (1,631 ops/sec)
185+
- With edges: 1.63ms (612 ops/sec)
186+
187+
### 7. Transactions
188+
189+
Tests transactional operations including savepoint rollback.
190+
191+
```typescript
192+
db.transaction(() => {
193+
// Create 10 or 100 nodes
194+
for (let i = 0; i < count; i++) {
195+
db.createNode('Person', { name: `Person ${i}` });
196+
}
197+
});
198+
199+
// With savepoint rollback
200+
db.transaction((ctx) => {
201+
db.createNode('Person', { name: 'Test' });
202+
ctx.savepoint('sp1');
203+
db.createNode('Person', { name: 'Test2' });
204+
ctx.rollbackTo('sp1'); // Only first node persists
205+
ctx.commit();
206+
});
207+
```
208+
209+
**Results:**
210+
- 10 nodes: 343.19µs (2,914 ops/sec)
211+
- 100 nodes: 1.02ms (978 ops/sec)
212+
- With savepoint: 330.08µs (3,030 ops/sec)
213+
214+
### 8. Real-World Scenarios
215+
216+
Tests realistic application patterns combining multiple operations.
217+
218+
**Job Search Scenario:**
219+
```typescript
220+
// Create job, company, skills, requirements, and query matches
221+
```
222+
- **Result**: 759.28µs (1,317 ops/sec)
223+
224+
**Social Network Scenario:**
225+
```typescript
226+
// Create users, friendships, and query friends-of-friends
227+
```
228+
- **Result**: 844.17µs (1,185 ops/sec)
229+
230+
## Performance Characteristics
231+
232+
### What's Fast
233+
234+
- **Updates**: Extremely fast (38K ops/sec) - SQLite UPDATE operations are optimized
235+
- **Queries with LIMIT**: Very fast (38K ops/sec) - SQLite can skip scanning all rows
236+
- **Path finding**: Fast (12-32K ops/sec) - Efficient graph algorithms
237+
- **Simple operations**: Sub-millisecond for most single-node operations
238+
239+
### What's Slower
240+
241+
- **Full table scans**: Query all nodes without WHERE clause (459 ops/sec)
242+
- **Sorting**: ORDER BY requires full scan and sort (398 ops/sec)
243+
- **Cascading deletes**: Deleting nodes with many edges (612 ops/sec)
244+
- **Large transactions**: Linear scaling with operation count
245+
246+
### Scaling Considerations
247+
248+
1. **Node count**: Query performance degrades linearly with dataset size
249+
2. **Edge count**: Traversal performance depends on graph density
250+
3. **Transaction size**: Larger transactions are more efficient per-operation but have higher latency
251+
4. **Index usage**: WHERE clauses benefit from SQLite indexes on node properties
252+
253+
## Running Benchmarks
254+
255+
### Prerequisites
256+
257+
```bash
258+
npm install
259+
npm run build
260+
```
261+
262+
### Run Full Suite
263+
264+
```bash
265+
npx ts-node benchmarks/comprehensive-benchmark.ts
266+
```
267+
268+
### Output Format
269+
270+
```
271+
📝 Node Creation Benchmarks
272+
────────────────────────────────────────────────────────────────────────────────
273+
Create single node
274+
Avg: 286.79µs | Ops/sec: 3487
275+
Min: 228.83µs | Max: 501.96µs
276+
```
277+
278+
### Interpreting Results
279+
280+
- **Avg**: Average time per operation (lower is better)
281+
- **Ops/sec**: Operations per second (higher is better)
282+
- **Min/Max**: Best and worst case times (shows variance)
283+
- **Variance**: High variance (max >> avg) suggests:
284+
- JIT compilation effects (first few iterations)
285+
- OS scheduling interference
286+
- SQLite cache effects
287+
288+
## Comparison to Other Graph Databases
289+
290+
### sqlite-graph vs Neo4j
291+
292+
| Feature | sqlite-graph | Neo4j |
293+
|---------|--------------|-------|
294+
| Deployment | Single file, embedded | Server process |
295+
| Query syntax | TypeScript fluent API | Cypher query language |
296+
| Node creation | ~3,500 ops/sec | ~10,000 ops/sec (depends on config) |
297+
| Traversal | Microseconds for shallow | Optimized for deep traversals |
298+
| ACID | Yes (SQLite) | Yes (configurable) |
299+
300+
### sqlite-graph vs Property Graphs in Memory
301+
302+
| Feature | sqlite-graph | In-Memory (e.g., graphology) |
303+
|---------|--------------|------------------------------|
304+
| Persistence | File-based (automatic) | Manual serialization required |
305+
| Memory usage | Constant (disk-backed) | All data in RAM |
306+
| Query speed | Microseconds-milliseconds | Nanoseconds-microseconds |
307+
| Dataset size | Limited by disk | Limited by RAM |
308+
309+
## Future Optimization Opportunities
310+
311+
### Potential Improvements
312+
313+
1. **Index optimization**: Add indexes on frequently queried properties
314+
2. **Prepared statements**: Cache compiled SQL for repeated queries
315+
3. **Batch operations**: Bulk insert/update APIs
316+
4. **Connection pooling**: For concurrent access patterns
317+
5. **WAL mode**: Write-Ahead Logging for better concurrent reads
318+
6. **Graph-specific indexes**: Adjacency list optimizations
319+
320+
### Expected Impact
321+
322+
- Indexes: 10-100x speedup for filtered queries
323+
- Prepared statements: 2-5x speedup for repeated queries
324+
- WAL mode: Better concurrent read performance
325+
- Bulk operations: Linear scaling improvement
326+
327+
## Contributing Benchmarks
328+
329+
To add new benchmarks:
330+
331+
1. Add method to `BenchmarkSuite` class in [comprehensive-benchmark.ts](../benchmarks/comprehensive-benchmark.ts)
332+
2. Follow existing pattern: warmup + measurement + statistics
333+
3. Include realistic data and query patterns
334+
4. Update this documentation with results
335+
336+
### Benchmark Checklist
337+
338+
- [ ] Warmup iterations (2-5)
339+
- [ ] Sufficient measurement iterations (10-100)
340+
- [ ] Realistic data patterns
341+
- [ ] Clean database state between runs
342+
- [ ] Document expected performance characteristics
343+
- [ ] Update hardware specs if significantly different
344+
345+
## References
346+
347+
- [SQLite Performance Tuning](https://www.sqlite.org/speed.html)
348+
- [better-sqlite3 Documentation](https://github.com/WiseLibs/better-sqlite3)
349+
- Node.js [performance.now()](https://nodejs.org/api/perf_hooks.html#perf_hooksperformancenow)
350+
351+
---
352+
353+
**Last Updated**: 2025-10-29
354+
**Benchmark Version**: 1.0.0
355+
**Test Dataset**: 344 KB (100-10,000 nodes)
356+
**Total Benchmarks**: 23
357+
**Total Operations Tested**: 1,320

0 commit comments

Comments
 (0)