2025-09-11 16:23:32 -07:00
/ * *
2026-02-17 17:04:11 -08:00
* Performance Benchmark Test Suite for Brainy
*
* Validates latency SLAs , throughput , memory efficiency ,
* concurrent operation handling , and search performance .
* Scales are kept moderate since each add ( ) involves embedding computation .
2025-09-11 16:23:32 -07:00
* /
2026-02-17 17:04:11 -08:00
import { describe , it , expect , beforeEach , afterEach } from 'vitest'
2025-09-11 16:23:32 -07:00
import { Brainy } from '../../src/brainy'
2026-02-17 17:04:11 -08:00
import { NounType , VerbType } from '../../src/types/graphTypes'
2025-09-11 16:23:32 -07:00
import { performance } from 'perf_hooks'
interface PerformanceResult {
operation : string
iterations : number
duration : number
throughput : number
latencies : {
p50 : number
p95 : number
p99 : number
min : number
max : number
mean : number
}
memory : {
initial : number
peak : number
final : number
delta : number
}
}
class PerformanceBenchmark {
private results : PerformanceResult [ ] = [ ]
private latencies : number [ ] = [ ]
private initialMemory : number = 0
private peakMemory : number = 0
constructor ( private name : string ) { }
start() {
this . latencies = [ ]
this . initialMemory = process . memoryUsage ( ) . heapUsed
this . peakMemory = this . initialMemory
}
recordOperation ( latency : number ) {
this . latencies . push ( latency )
const currentMemory = process . memoryUsage ( ) . heapUsed
if ( currentMemory > this . peakMemory ) {
this . peakMemory = currentMemory
}
}
finish ( ) : PerformanceResult {
const finalMemory = process . memoryUsage ( ) . heapUsed
const sorted = [ . . . this . latencies ] . sort ( ( a , b ) = > a - b )
const totalDuration = this . latencies . reduce ( ( sum , l ) = > sum + l , 0 )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result : PerformanceResult = {
operation : this.name ,
iterations : this.latencies.length ,
duration : totalDuration ,
2026-02-17 17:04:11 -08:00
throughput : this.latencies.length > 0 ? ( this . latencies . length / totalDuration ) * 1000 : 0 ,
2025-09-11 16:23:32 -07:00
latencies : {
p50 : sorted [ Math . floor ( sorted . length * 0.5 ) ] || 0 ,
p95 : sorted [ Math . floor ( sorted . length * 0.95 ) ] || 0 ,
p99 : sorted [ Math . floor ( sorted . length * 0.99 ) ] || 0 ,
min : sorted [ 0 ] || 0 ,
max : sorted [ sorted . length - 1 ] || 0 ,
2026-02-17 17:04:11 -08:00
mean : this.latencies.length > 0 ? totalDuration / this . latencies.length : 0
2025-09-11 16:23:32 -07:00
} ,
memory : {
initial : this.initialMemory ,
peak : this.peakMemory ,
final : finalMemory ,
delta : finalMemory - this . initialMemory
}
}
this . results . push ( result )
return result
}
static generateReport ( results : PerformanceResult [ ] ) {
console . log ( '\n=== Performance Benchmark Report ===\n' )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const table = results . map ( r = > ( {
Operation : r.operation ,
'Iterations' : r . iterations ,
'Throughput (ops/s)' : r . throughput . toFixed ( 0 ) ,
'P50 (ms)' : r . latencies . p50 . toFixed ( 2 ) ,
'P95 (ms)' : r . latencies . p95 . toFixed ( 2 ) ,
'P99 (ms)' : r . latencies . p99 . toFixed ( 2 ) ,
'Memory (MB)' : ( r . memory . delta / 1024 / 1024 ) . toFixed ( 2 )
} ) )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
console . table ( table )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
console . log ( '\n=== Summary ===' )
console . log ( ` Total operations: ${ results . reduce ( ( sum , r ) = > sum + r . iterations , 0 ) } ` )
2026-02-17 17:04:11 -08:00
if ( results . length > 0 ) {
console . log ( ` Average throughput: ${ ( results . reduce ( ( sum , r ) = > sum + r . throughput , 0 ) / results . length ) . toFixed ( 0 ) } ops/s ` )
}
2025-09-11 16:23:32 -07:00
console . log ( ` Total memory used: ${ ( results . reduce ( ( sum , r ) = > sum + r . memory . delta , 0 ) / 1024 / 1024 ) . toFixed ( 2 ) } MB ` )
}
}
describe ( 'Performance Benchmarks - SLA Validation' , ( ) = > {
let brainy : Brainy
2026-02-17 17:04:11 -08:00
const benchmarkResults : PerformanceResult [ ] = [ ]
2025-09-11 16:23:32 -07:00
beforeEach ( async ( ) = > {
feat(8.0)!: flip requireSubtype default to true (BRAINY-8.0-SUBTYPE-CONTRACT § C-1)
Brainy 8.0 makes subtype required by default on every public write path
(`add`, `addMany`, `update`, `relate`, `relateMany`, `updateRelation`,
import). Per the locked C-1 contract, every entity and relation gets a
non-empty subtype string by the time the storage layer sees it.
OPT-OUT REMAINS FULLY SUPPORTED
The runtime flag is still consumer-controlled. Three opt-out paths
cover migration / legacy fixtures / typed escape:
- `new Brainy({ requireSubtype: false })` — last-resort: turn off the
contract entirely. Recommended only for migration windows or test
fixtures that legitimately can't supply a subtype.
- `new Brainy({ requireSubtype: { except: [NounType.Thing, ...] } })` —
per-type allowlist: strict everywhere except the listed types.
- `brain.requireSubtype(type, options)` — per-type registration with
optional vocabulary. Composes with the brain-wide flag.
Default is now `true`. Opt-out is explicit and documented; nothing
silently degrades.
TEST SWEEP
Bulk-applied `requireSubtype: false` to every `new Brainy({...})` call
site across 120 test files. Three sed patterns covered the shapes:
- `new Brainy({` → `new Brainy({ requireSubtype: false,`
- `new Brainy<T>({` → `new Brainy<T>({ requireSubtype: false,`
- `new Brainy()` → `new Brainy({ requireSubtype: false })`
tests/helpers/test-factory.ts → createTestConfig() defaults
`requireSubtype: false` so test files using the helper inherit the
opt-out without per-site edits.
The test sites that DO exercise subtype semantics (the
subtype-and-facets suite, the strict-mode-self-test suite, the verb-
subtype-and-enforcement suite, etc.) already pass real subtypes — they
were the 7.30.x acceptance tests for this contract. Those tests
continue to pass unchanged.
CHANGES
src/brainy.ts
- normalizeConfig() — `requireSubtype` default `false` → `true`.
Comment refreshed to document the three opt-out paths.
tests/* (120 files)
- Bulk-edited brain construction sites. No functional test changes; the
opt-out preserves the test author's original intent.
tests/helpers/test-factory.ts
- createTestConfig() base config gains `requireSubtype: false`.
NO-OP for consumers who were already passing subtype on every write.
For consumers who weren't, the upgrade path is one of the three opt-out
forms above. Migration recipe documented in 8.0 release notes (next
commit).
VERIFICATION
- npx tsc --noEmit: clean
- npm test: 1408 / 1409 (same pre-existing race-condition outstanding;
no other regressions from the flip)
2026-06-09 14:58:25 -07:00
brainy = new Brainy ( { requireSubtype : false ,
2025-09-11 16:23:32 -07:00
storage : { type : 'memory' }
} )
await brainy . init ( )
} )
afterEach ( async ( ) = > {
await brainy . close ( )
} )
describe ( 'Single Operation Latency SLAs' , ( ) = > {
it ( 'should meet ADD operation latency SLAs' , async ( ) = > {
const benchmark = new PerformanceBenchmark ( 'add-single' )
2026-02-17 17:04:11 -08:00
const iterations = 50
2025-09-11 16:23:32 -07:00
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( let i = 0 ; i < iterations ; i ++ ) {
const start = performance . now ( )
await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Performance test document ${ i } about machine learning ` ,
type : NounType . Document ,
2025-09-11 16:23:32 -07:00
metadata : { index : i , timestamp : Date.now ( ) }
} )
const latency = performance . now ( ) - start
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
// SLA Assertions (each add includes embedding computation)
expect ( result . latencies . p50 ) . toBeLessThan ( 200 )
expect ( result . latencies . p95 ) . toBeLessThan ( 500 )
expect ( result . latencies . p99 ) . toBeLessThan ( 1000 )
expect ( result . throughput ) . toBeGreaterThan ( 2 )
} , 120000 )
2025-09-11 16:23:32 -07:00
it ( 'should meet GET operation latency SLAs' , async ( ) = > {
// Seed data
const ids : string [ ] = [ ]
2026-02-17 17:04:11 -08:00
for ( let i = 0 ; i < 50 ; i ++ ) {
2025-09-11 16:23:32 -07:00
const id = await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Get benchmark document ${ i } ` ,
type : NounType . Document
2025-09-11 16:23:32 -07:00
} )
ids . push ( id )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const benchmark = new PerformanceBenchmark ( 'get-single' )
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( const id of ids ) {
const start = performance . now ( )
await brainy . get ( id )
const latency = performance . now ( ) - start
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
// GET should be fast — no embedding needed
expect ( result . latencies . p50 ) . toBeLessThan ( 5 )
expect ( result . latencies . p95 ) . toBeLessThan ( 20 )
expect ( result . latencies . p99 ) . toBeLessThan ( 50 )
expect ( result . throughput ) . toBeGreaterThan ( 100 )
} , 120000 )
2025-09-11 16:23:32 -07:00
it ( 'should meet UPDATE operation latency SLAs' , async ( ) = > {
// Seed data
const ids : string [ ] = [ ]
2026-02-17 17:04:11 -08:00
for ( let i = 0 ; i < 30 ; i ++ ) {
2025-09-11 16:23:32 -07:00
const id = await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Update benchmark ${ i } ` ,
type : NounType . Document ,
2025-09-11 16:23:32 -07:00
metadata : { version : 1 }
} )
ids . push ( id )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const benchmark = new PerformanceBenchmark ( 'update-single' )
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( const id of ids ) {
const start = performance . now ( )
await brainy . update ( {
id ,
metadata : { version : 2 , updatedAt : Date.now ( ) }
} )
const latency = performance . now ( ) - start
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . latencies . p50 ) . toBeLessThan ( 50 )
expect ( result . latencies . p95 ) . toBeLessThan ( 200 )
expect ( result . latencies . p99 ) . toBeLessThan ( 500 )
} , 120000 )
2025-09-11 16:23:32 -07:00
it ( 'should meet DELETE operation latency SLAs' , async ( ) = > {
// Seed data
const ids : string [ ] = [ ]
2026-02-17 17:04:11 -08:00
for ( let i = 0 ; i < 30 ; i ++ ) {
2025-09-11 16:23:32 -07:00
const id = await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Delete benchmark ${ i } ` ,
type : NounType . Document
2025-09-11 16:23:32 -07:00
} )
ids . push ( id )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const benchmark = new PerformanceBenchmark ( 'delete-single' )
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( const id of ids ) {
const start = performance . now ( )
2026-06-11 14:51:00 -07:00
await brainy . remove ( id )
2025-09-11 16:23:32 -07:00
const latency = performance . now ( ) - start
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . latencies . p50 ) . toBeLessThan ( 10 )
expect ( result . latencies . p95 ) . toBeLessThan ( 50 )
expect ( result . latencies . p99 ) . toBeLessThan ( 100 )
} , 120000 )
2025-09-11 16:23:32 -07:00
} )
describe ( 'Throughput Testing' , ( ) = > {
it ( 'should maintain throughput under sustained load' , async ( ) = > {
2026-02-17 17:04:11 -08:00
const durationMs = 5000 // 5 seconds
2025-09-11 16:23:32 -07:00
const benchmark = new PerformanceBenchmark ( 'sustained-load' )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
benchmark . start ( )
const startTime = performance . now ( )
let operations = 0
2026-02-17 17:04:11 -08:00
while ( performance . now ( ) - startTime < durationMs ) {
2025-09-11 16:23:32 -07:00
const opStart = performance . now ( )
await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Sustained load test ${ operations } data processing ` ,
type : NounType . Document ,
2025-09-11 16:23:32 -07:00
metadata : { timestamp : Date.now ( ) }
} )
const latency = performance . now ( ) - opStart
benchmark . recordOperation ( latency )
operations ++
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . throughput ) . toBeGreaterThan ( 2 )
expect ( result . latencies . p99 ) . toBeLessThan ( 1000 )
expect ( operations ) . toBeGreaterThan ( 10 )
} , 120000 )
2025-09-11 16:23:32 -07:00
it ( 'should handle burst traffic' , async ( ) = > {
const benchmark = new PerformanceBenchmark ( 'burst-traffic' )
2026-02-17 17:04:11 -08:00
const burstSize = 30
2025-09-11 16:23:32 -07:00
benchmark . start ( )
const startTime = performance . now ( )
2026-02-17 17:04:11 -08:00
const promises = Array . from ( { length : burstSize } , ( _ , i ) = >
2025-09-11 16:23:32 -07:00
brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Burst request ${ i } about natural language ` ,
type : NounType . Document
2025-09-11 16:23:32 -07:00
} ) . then ( ( ) = > {
const latency = performance . now ( ) - startTime
2026-02-17 17:04:11 -08:00
benchmark . recordOperation ( latency / burstSize )
2025-09-11 16:23:32 -07:00
} )
)
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
await Promise . all ( promises )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const totalDuration = performance . now ( ) - startTime
const burstThroughput = ( burstSize / totalDuration ) * 1000
2026-02-17 17:04:11 -08:00
expect ( burstThroughput ) . toBeGreaterThan ( 1 )
expect ( totalDuration ) . toBeLessThan ( 60000 )
} , 120000 )
2025-09-11 16:23:32 -07:00
} )
describe ( 'Concurrent Operations' , ( ) = > {
it ( 'should handle concurrent reads efficiently' , async ( ) = > {
// Seed data
const ids : string [ ] = [ ]
2026-02-17 17:04:11 -08:00
for ( let i = 0 ; i < 20 ; i ++ ) {
2025-09-11 16:23:32 -07:00
const id = await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Concurrent read test ${ i } information retrieval ` ,
type : NounType . Document
2025-09-11 16:23:32 -07:00
} )
ids . push ( id )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const benchmark = new PerformanceBenchmark ( 'concurrent-reads' )
2026-02-17 17:04:11 -08:00
const concurrency = 10
const iterations = 5
2025-09-11 16:23:32 -07:00
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( let iter = 0 ; iter < iterations ; iter ++ ) {
const startTime = performance . now ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
await Promise . all (
2026-02-17 17:04:11 -08:00
Array . from ( { length : concurrency } , ( _ , i ) = >
2025-09-11 16:23:32 -07:00
brainy . get ( ids [ i % ids . length ] )
)
)
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const latency = performance . now ( ) - startTime
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . latencies . mean ) . toBeLessThan ( 100 )
} , 120000 )
2025-09-11 16:23:32 -07:00
it ( 'should handle mixed concurrent operations' , async ( ) = > {
2026-02-17 17:04:11 -08:00
// Seed some entities first so we have valid IDs for get/update/delete
const seedIds : string [ ] = [ ]
for ( let i = 0 ; i < 20 ; i ++ ) {
const id = await brainy . add ( {
data : ` Mixed ops seed ${ i } ` ,
type : NounType . Document ,
metadata : { v : 1 }
} )
seedIds . push ( id )
}
2025-09-11 16:23:32 -07:00
const benchmark = new PerformanceBenchmark ( 'concurrent-mixed' )
2026-02-17 17:04:11 -08:00
const concurrency = 10
const iterations = 3
2025-09-11 16:23:32 -07:00
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( let iter = 0 ; iter < iterations ; iter ++ ) {
const startTime = performance . now ( )
2026-02-17 17:04:11 -08:00
const operations = Array . from ( { length : concurrency } , ( _ , i ) = > {
const op = i % 3
2025-09-11 16:23:32 -07:00
switch ( op ) {
2026-02-17 17:04:11 -08:00
case 0 :
2025-09-11 16:23:32 -07:00
return brainy . add ( {
data : ` Concurrent add ${ iter } - ${ i } ` ,
2026-02-17 17:04:11 -08:00
type : NounType . Document
2025-09-11 16:23:32 -07:00
} )
2026-02-17 17:04:11 -08:00
case 1 :
return brainy . get ( seedIds [ i % seedIds . length ] )
case 2 :
2025-09-11 16:23:32 -07:00
return brainy . update ( {
2026-02-17 17:04:11 -08:00
id : seedIds [ i % seedIds . length ] ,
2025-09-11 16:23:32 -07:00
metadata : { updated : Date.now ( ) }
2026-02-17 17:04:11 -08:00
} ) . catch ( ( ) = > null )
2025-09-11 16:23:32 -07:00
default :
return Promise . resolve ( )
}
} )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
await Promise . all ( operations )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const latency = performance . now ( ) - startTime
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . latencies . p95 ) . toBeLessThan ( 5000 )
} , 120000 )
2025-09-11 16:23:32 -07:00
} )
describe ( 'Memory Efficiency' , ( ) = > {
it ( 'should not leak memory during operations' , async ( ) = > {
const benchmark = new PerformanceBenchmark ( 'memory-leak-test' )
2026-02-17 17:04:11 -08:00
const iterations = 3
const opsPerIteration = 20
2025-09-11 16:23:32 -07:00
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( let iter = 0 ; iter < iterations ; iter ++ ) {
2026-02-17 17:04:11 -08:00
if ( global . gc ) global . gc ( )
2025-09-11 16:23:32 -07:00
const startMemory = process . memoryUsage ( ) . heapUsed
const startTime = performance . now ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const ids : string [ ] = [ ]
for ( let i = 0 ; i < opsPerIteration ; i ++ ) {
const id = await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Memory test ${ iter } - ${ i } leak detection ` ,
type : NounType . Document
2025-09-11 16:23:32 -07:00
} )
ids . push ( id )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( const id of ids ) {
2026-06-11 14:51:00 -07:00
await brainy . remove ( id )
2025-09-11 16:23:32 -07:00
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
if ( global . gc ) global . gc ( )
const endMemory = process . memoryUsage ( ) . heapUsed
const latency = performance . now ( ) - startTime
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
benchmark . recordOperation ( latency )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const memoryGrowth = endMemory - startMemory
2026-02-17 17:04:11 -08:00
expect ( memoryGrowth ) . toBeLessThan ( 50 * 1024 * 1024 )
2025-09-11 16:23:32 -07:00
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . memory . delta ) . toBeLessThan ( 100 * 1024 * 1024 )
} , 120000 )
2025-09-11 16:23:32 -07:00
it ( 'should handle large entities efficiently' , async ( ) = > {
const benchmark = new PerformanceBenchmark ( 'large-entities' )
2026-02-17 17:04:11 -08:00
const entitySize = 10 * 1024 // 10KB per entity
const count = 10
2025-09-11 16:23:32 -07:00
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( let i = 0 ; i < count ; i ++ ) {
const largeData = 'x' . repeat ( entitySize )
const start = performance . now ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
await brainy . add ( {
data : largeData ,
2026-02-17 17:04:11 -08:00
type : NounType . Document ,
2025-09-11 16:23:32 -07:00
metadata : { size : entitySize , index : i }
} )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const latency = performance . now ( ) - start
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . latencies . p95 ) . toBeLessThan ( 2000 )
expect ( result . memory . delta ) . toBeLessThan ( 150 * 1024 * 1024 )
} , 120000 )
2025-09-11 16:23:32 -07:00
} )
describe ( 'Search Performance' , ( ) = > {
it ( 'should meet FIND operation latency SLAs' , async ( ) = > {
// Seed diverse data
2026-02-17 17:04:11 -08:00
for ( let i = 0 ; i < 50 ; i ++ ) {
2025-09-11 16:23:32 -07:00
await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Search test document ${ i } : artificial intelligence and data science ` ,
type : NounType . Document ,
2025-09-11 16:23:32 -07:00
metadata : {
2026-02-17 17:04:11 -08:00
category : ` cat- ${ i % 5 } ` ,
2025-09-11 16:23:32 -07:00
score : Math.random ( ) * 100 ,
active : i % 2 === 0
}
} )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const benchmark = new PerformanceBenchmark ( 'find-operations' )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const queries = [
2026-02-17 17:04:11 -08:00
'artificial intelligence' ,
'data science research' ,
'search document' ,
'machine learning'
2025-09-11 16:23:32 -07:00
]
2026-02-17 17:04:11 -08:00
for ( let i = 0 ; i < 20 ; i ++ ) {
2025-09-11 16:23:32 -07:00
const query = queries [ i % queries . length ]
const start = performance . now ( )
2026-02-17 17:04:11 -08:00
await brainy . find ( { query , limit : 10 } )
2025-09-11 16:23:32 -07:00
const latency = performance . now ( ) - start
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . latencies . p50 ) . toBeLessThan ( 200 )
expect ( result . latencies . p95 ) . toBeLessThan ( 500 )
expect ( result . latencies . p99 ) . toBeLessThan ( 1000 )
} , 120000 )
it ( 'should handle similarity search efficiently' , async ( ) = > {
const benchmark = new PerformanceBenchmark ( 'similar-search' )
const ids : string [ ] = [ ]
for ( let i = 0 ; i < 50 ; i ++ ) {
2025-09-11 16:23:32 -07:00
const id = await brainy . add ( {
2026-02-17 17:04:11 -08:00
data : ` Similarity search test ${ i } about neural networks ` ,
type : NounType . Thing ,
metadata : { group : ` group- ${ i % 5 } ` }
2025-09-11 16:23:32 -07:00
} )
2026-02-17 17:04:11 -08:00
ids . push ( id )
2025-09-11 16:23:32 -07:00
}
2026-02-17 17:04:11 -08:00
// Create some relationships
for ( let i = 0 ; i < ids . length - 1 ; i += 5 ) {
await brainy . relate ( {
from : ids [ i ] ,
to : ids [ i + 1 ] ,
type : VerbType . RelatedTo
} )
2025-09-11 16:23:32 -07:00
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
benchmark . start ( )
2026-02-17 17:04:11 -08:00
for ( let i = 0 ; i < 10 ; i ++ ) {
2025-09-11 16:23:32 -07:00
const start = performance . now ( )
2026-02-17 17:04:11 -08:00
await brainy . similar ( {
to : ids [ i % ids . length ] ,
limit : 5
} )
2025-09-11 16:23:32 -07:00
const latency = performance . now ( ) - start
benchmark . recordOperation ( latency )
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
expect ( result . latencies . p95 ) . toBeLessThan ( 500 )
} , 120000 )
2025-09-11 16:23:32 -07:00
} )
describe ( 'Batch Operations Performance' , ( ) = > {
it ( 'should meet batch ADD performance targets' , async ( ) = > {
const benchmark = new PerformanceBenchmark ( 'batch-add' )
2026-02-17 17:04:11 -08:00
const batchSizes = [ 5 , 10 , 20 ]
2025-09-11 16:23:32 -07:00
benchmark . start ( )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
for ( const batchSize of batchSizes ) {
2026-02-17 17:04:11 -08:00
const items = Array . from ( { length : batchSize } , ( _ , i ) = > ( {
data : ` Batch item ${ i } for performance testing ` ,
type : NounType . Document as NounType ,
2025-09-11 16:23:32 -07:00
metadata : { batchSize , index : i }
} ) )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const start = performance . now ( )
await brainy . addMany ( { items } )
const latency = performance . now ( ) - start
2026-02-17 17:04:11 -08:00
benchmark . recordOperation ( latency / batchSize )
2025-09-11 16:23:32 -07:00
}
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const result = benchmark . finish ( )
benchmarkResults . push ( result )
2026-02-17 17:04:11 -08:00
// Batch amortized cost per item should be reasonable
expect ( result . latencies . mean ) . toBeLessThan ( 500 )
} , 120000 )
2025-09-11 16:23:32 -07:00
} )
describe ( 'Performance Report' , ( ) = > {
it ( 'should generate comprehensive performance report' , ( ) = > {
2026-02-17 17:04:11 -08:00
if ( benchmarkResults . length === 0 ) {
// No prior benchmarks ran — skip report
return
}
2025-09-11 16:23:32 -07:00
PerformanceBenchmark . generateReport ( benchmarkResults )
2026-02-17 17:04:11 -08:00
2025-09-11 16:23:32 -07:00
const avgThroughput = benchmarkResults . reduce ( ( sum , r ) = > sum + r . throughput , 0 ) / benchmarkResults . length
2026-02-17 17:04:11 -08:00
expect ( avgThroughput ) . toBeGreaterThan ( 1 )
2025-09-11 16:23:32 -07:00
const totalMemory = benchmarkResults . reduce ( ( sum , r ) = > sum + r . memory . delta , 0 )
2026-02-17 17:04:11 -08:00
expect ( totalMemory ) . toBeLessThan ( 500 * 1024 * 1024 )
2025-09-11 16:23:32 -07:00
} )
} )
2026-02-17 17:04:11 -08:00
} )