CHECKPOINT: Session 4 - Complete Optimization Suite
✅ Unified Cache System - Created UnifiedCache with cost-aware eviction - Integrated with both MetadataIndex and HNSW - Request coalescing, fairness monitoring, access patterns ✅ Index Persistence - Sorted indices for range queries saved/loaded - Integrated with UnifiedCache (100x rebuild cost) ✅ TripleIntelligence Fixed - Native Brain Pattern support - Direct metadata filtering without string conversion ✅ Competitive Analysis - Created comprehensive docs/COMPETITIVE-ANALYSIS.md - Shows Brainy advantages vs all competitors ✅ All Infrastructure Complete - TypeScript: 0 errors - Memory: Optimized with unified cache - Models: Cached locally - Ready for comprehensive testing
This commit is contained in:
parent
88abcddf84
commit
f0ee5f44ec
16 changed files with 2081 additions and 582 deletions
212
COORDINATED_INDEX_OPTIMIZATION.md
Normal file
212
COORDINATED_INDEX_OPTIMIZATION.md
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
# Coordinated Index Optimization Strategy
|
||||
|
||||
## The Problem
|
||||
Two independent index systems competing for resources:
|
||||
- **HNSW Index**: Wants to cache hot vectors in RAM
|
||||
- **MetadataIndex**: Wants to cache hot field values in RAM
|
||||
- **Conflict**: Both trying to use same memory/disk without coordination!
|
||||
|
||||
## The Solution: Unified Resource Manager
|
||||
|
||||
### 1. Shared Resource Pool
|
||||
```typescript
|
||||
class UnifiedIndexManager {
|
||||
private totalMemoryBudget: number = 2 * 1024 * 1024 * 1024 // 2GB total
|
||||
private hnswMemoryUsage: number = 0
|
||||
private metadataMemoryUsage: number = 0
|
||||
|
||||
// Intelligent allocation based on usage patterns
|
||||
allocateMemory(requester: 'hnsw' | 'metadata', size: number): boolean {
|
||||
const available = this.totalMemoryBudget - this.hnswMemoryUsage - this.metadataMemoryUsage
|
||||
|
||||
if (size <= available) {
|
||||
if (requester === 'hnsw') {
|
||||
this.hnswMemoryUsage += size
|
||||
} else {
|
||||
this.metadataMemoryUsage += size
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Try to steal from other index if one is underutilized
|
||||
return this.rebalance(requester, size)
|
||||
}
|
||||
|
||||
private rebalance(requester: string, needed: number): boolean {
|
||||
// If HNSW is using 80% and metadata only 20%, rebalance
|
||||
const hnswRatio = this.hnswMemoryUsage / this.totalMemoryBudget
|
||||
const metadataRatio = this.metadataMemoryUsage / this.totalMemoryBudget
|
||||
|
||||
// Intelligent rebalancing logic
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Coordinated LRU Eviction
|
||||
```typescript
|
||||
class CoordinatedLRUCache {
|
||||
private hnswLRU: LRUCache
|
||||
private metadataLRU: LRUCache
|
||||
private accessPatterns: AccessTracker
|
||||
|
||||
// When memory pressure, evict from the index with lowest utility
|
||||
async evict(bytesNeeded: number): Promise<void> {
|
||||
const hnswUtility = this.calculateUtility(this.hnswLRU)
|
||||
const metadataUtility = this.calculateUtility(this.metadataLRU)
|
||||
|
||||
if (hnswUtility < metadataUtility) {
|
||||
// HNSW items are less frequently accessed
|
||||
await this.hnswLRU.evict(bytesNeeded)
|
||||
} else {
|
||||
// Metadata items are less frequently accessed
|
||||
await this.metadataLRU.evict(bytesNeeded)
|
||||
}
|
||||
}
|
||||
|
||||
private calculateUtility(cache: LRUCache): number {
|
||||
// Factors:
|
||||
// - Access frequency
|
||||
// - Recency
|
||||
// - Cost to rebuild (HNSW is expensive, metadata is cheap)
|
||||
// - Current query patterns
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Query-Aware Optimization
|
||||
```typescript
|
||||
class QueryOptimizer {
|
||||
private queryHistory: QueryPattern[] = []
|
||||
|
||||
optimizeForQuery(query: TripleQuery) {
|
||||
// Analyze query type
|
||||
const usesVector = !!(query.like || query.similar)
|
||||
const usesMetadata = !!query.where
|
||||
|
||||
// Pre-warm appropriate caches
|
||||
if (usesVector && usesMetadata) {
|
||||
// Hybrid query - balance resources 50/50
|
||||
this.resourceManager.setRatio(0.5, 0.5)
|
||||
} else if (usesVector) {
|
||||
// Vector-heavy - give HNSW more memory
|
||||
this.resourceManager.setRatio(0.8, 0.2)
|
||||
} else {
|
||||
// Metadata-heavy - give MetadataIndex more memory
|
||||
this.resourceManager.setRatio(0.2, 0.8)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Unified Persistence Strategy
|
||||
```typescript
|
||||
class UnifiedPersistence {
|
||||
private writeBuffer: WriteBuffer
|
||||
private flushScheduler: FlushScheduler
|
||||
|
||||
async flush() {
|
||||
// Coordinate flushes to avoid disk contention
|
||||
const tasks = []
|
||||
|
||||
// Flush metadata first (smaller, faster)
|
||||
if (this.metadataIndex.isDirty) {
|
||||
tasks.push(this.flushMetadata())
|
||||
}
|
||||
|
||||
// Then flush HNSW (larger, slower)
|
||||
if (this.hnswIndex.isDirty) {
|
||||
tasks.push(this.flushHNSW())
|
||||
}
|
||||
|
||||
// Sequential to avoid disk thrashing
|
||||
for (const task of tasks) {
|
||||
await task
|
||||
}
|
||||
}
|
||||
|
||||
private async flushMetadata() {
|
||||
// Flush sorted indices
|
||||
await this.storage.save('metadata_sorted', this.metadataIndex.sortedIndices)
|
||||
// Flush hash indices
|
||||
await this.storage.save('metadata_hash', this.metadataIndex.hashIndices)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Shared Memory Manager (Quick Win)
|
||||
```typescript
|
||||
// In BrainyData constructor
|
||||
this.resourceManager = new UnifiedResourceManager({
|
||||
totalMemory: config.maxMemory || 2 * GB,
|
||||
hnswRatio: 0.6, // 60% for vectors by default
|
||||
metadataRatio: 0.4 // 40% for metadata by default
|
||||
})
|
||||
|
||||
// Pass to both indices
|
||||
this.hnswIndex = new HNSWIndexOptimized({
|
||||
resourceManager: this.resourceManager
|
||||
})
|
||||
|
||||
this.metadataIndex = new MetadataIndexOptimized({
|
||||
resourceManager: this.resourceManager
|
||||
})
|
||||
```
|
||||
|
||||
### Phase 2: Coordinated Eviction
|
||||
- Single LRU that tracks both index types
|
||||
- Utility-based eviction (not just recency)
|
||||
- Consider rebuild cost in eviction decisions
|
||||
|
||||
### Phase 3: Query-Driven Optimization
|
||||
- Track query patterns
|
||||
- Dynamically adjust memory allocation
|
||||
- Pre-warm caches based on query type
|
||||
|
||||
## Benefits of Coordination
|
||||
|
||||
1. **No Resource Conflicts**: Indices cooperate instead of compete
|
||||
2. **Better Memory Usage**: Allocate based on actual query patterns
|
||||
3. **Smarter Eviction**: Keep data that's actually needed
|
||||
4. **Unified Monitoring**: Single place to track all index performance
|
||||
5. **Auto-Optimization**: System learns and adapts to usage
|
||||
|
||||
## Configuration Example
|
||||
```typescript
|
||||
const brain = new BrainyData({
|
||||
indexOptimization: {
|
||||
mode: 'coordinated', // vs 'independent'
|
||||
totalMemory: 4 * GB, // Total for ALL indices
|
||||
autoBalance: true, // Dynamic rebalancing
|
||||
persistenceInterval: 60000, // Coordinated flush every minute
|
||||
monitoring: {
|
||||
trackQueryPatterns: true,
|
||||
optimizeForPatterns: true,
|
||||
rebalanceInterval: 300000 // Every 5 minutes
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Monitoring & Metrics
|
||||
```typescript
|
||||
const stats = brain.getIndexStats()
|
||||
// {
|
||||
// hnsw: {
|
||||
// memoryUsed: 1.2 * GB,
|
||||
// cacheHitRate: 0.89,
|
||||
// avgQueryTime: 12ms
|
||||
// },
|
||||
// metadata: {
|
||||
// memoryUsed: 0.8 * GB,
|
||||
// cacheHitRate: 0.95,
|
||||
// avgQueryTime: 2ms
|
||||
// },
|
||||
// coordination: {
|
||||
// rebalances: 5,
|
||||
// memoryUtilization: 0.95,
|
||||
// queryPatternDetected: 'hybrid-heavy'
|
||||
// }
|
||||
// }
|
||||
Loading…
Add table
Add a link
Reference in a new issue