@soulcraft/brainy 3.40.0 → 3.40.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/utils/unifiedCache.d.ts +6 -0
- package/dist/utils/unifiedCache.js +36 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [3.40.2](https://github.com/soulcraftlabs/brainy/compare/v3.40.1...v3.40.2) (2025-10-13)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ⚡ Performance Improvements
|
|
9
|
+
|
|
10
|
+
* more aggressive cache fairness to prevent thrashing ([829a8a6](https://github.com/soulcraftlabs/brainy/commit/829a8a61a23688aae1384b2844f1e75b1fd773d9))
|
|
11
|
+
|
|
12
|
+
### [3.40.1](https://github.com/soulcraftlabs/brainy/compare/v3.40.0...v3.40.1) (2025-10-13)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug Fixes
|
|
16
|
+
|
|
17
|
+
* correct cache eviction formula to prioritize high-value items ([8e7b52b](https://github.com/soulcraftlabs/brainy/commit/8e7b52bda98e637164e2fb321251c254d03cdf70))
|
|
18
|
+
|
|
5
19
|
## [3.40.0](https://github.com/soulcraftlabs/brainy/compare/v3.39.0...v3.40.0) (2025-10-13)
|
|
6
20
|
|
|
7
21
|
|
|
@@ -78,6 +78,12 @@ export declare class UnifiedCache {
|
|
|
78
78
|
*/
|
|
79
79
|
private startFairnessMonitor;
|
|
80
80
|
private checkFairness;
|
|
81
|
+
/**
|
|
82
|
+
* Proactive fairness check (v3.40.2)
|
|
83
|
+
* Called immediately when adding items to prevent imbalance formation
|
|
84
|
+
* Uses same thresholds as periodic check but runs on-demand
|
|
85
|
+
*/
|
|
86
|
+
private checkProactiveFairness;
|
|
81
87
|
/**
|
|
82
88
|
* Force evict items of a specific type
|
|
83
89
|
*/
|
|
@@ -50,7 +50,7 @@ export class UnifiedCache {
|
|
|
50
50
|
this.config = {
|
|
51
51
|
enableRequestCoalescing: true,
|
|
52
52
|
enableFairnessCheck: true,
|
|
53
|
-
fairnessCheckInterval:
|
|
53
|
+
fairnessCheckInterval: 30000, // Check fairness every 30 seconds (v3.40.2: was 60s)
|
|
54
54
|
persistPatterns: true,
|
|
55
55
|
enableMemoryMonitoring: true,
|
|
56
56
|
memoryCheckInterval: 30000, // Check memory every 30s
|
|
@@ -149,6 +149,11 @@ export class UnifiedCache {
|
|
|
149
149
|
this.currentSize += size;
|
|
150
150
|
this.typeAccessCounts[type]++;
|
|
151
151
|
this.totalAccessCount++;
|
|
152
|
+
// Proactive fairness check (v3.40.2): Check immediately if adding to a dominant type
|
|
153
|
+
// This prevents imbalance formation instead of reacting to it
|
|
154
|
+
if (this.config.enableFairnessCheck && this.cache.size > 10) {
|
|
155
|
+
this.checkProactiveFairness(type);
|
|
156
|
+
}
|
|
152
157
|
}
|
|
153
158
|
/**
|
|
154
159
|
* Evict item with lowest value (access count / rebuild cost)
|
|
@@ -157,9 +162,9 @@ export class UnifiedCache {
|
|
|
157
162
|
let victim = null;
|
|
158
163
|
let lowestScore = Infinity;
|
|
159
164
|
for (const [key, item] of this.cache) {
|
|
160
|
-
// Calculate value score: access frequency
|
|
165
|
+
// Calculate value score: access frequency * rebuild cost (higher is better)
|
|
161
166
|
const accessScore = (this.access.get(key) || 1);
|
|
162
|
-
const score = accessScore
|
|
167
|
+
const score = accessScore * item.rebuildCost;
|
|
163
168
|
if (score < lowestScore) {
|
|
164
169
|
lowestScore = score;
|
|
165
170
|
victim = key;
|
|
@@ -180,7 +185,7 @@ export class UnifiedCache {
|
|
|
180
185
|
evictForSize(bytesNeeded) {
|
|
181
186
|
const candidates = [];
|
|
182
187
|
for (const [key, item] of this.cache) {
|
|
183
|
-
const score = (this.access.get(key) || 1)
|
|
188
|
+
const score = (this.access.get(key) || 1) * item.rebuildCost;
|
|
184
189
|
candidates.push([key, score, item]);
|
|
185
190
|
}
|
|
186
191
|
// Sort by score (lower is worse)
|
|
@@ -235,14 +240,36 @@ export class UnifiedCache {
|
|
|
235
240
|
embedding: typeSizes.embedding / totalSize,
|
|
236
241
|
other: typeSizes.other / totalSize
|
|
237
242
|
};
|
|
238
|
-
// Check for starvation (
|
|
243
|
+
// Check for starvation (v3.40.2: more aggressive - 70% cache with <15% accesses)
|
|
244
|
+
// Previous: 90% cache, <10% access (too lenient, caused thrashing)
|
|
239
245
|
for (const type of ['hnsw', 'metadata', 'embedding', 'other']) {
|
|
240
|
-
if (sizeRatios[type] > 0.
|
|
246
|
+
if (sizeRatios[type] > 0.7 && accessRatios[type] < 0.15) {
|
|
241
247
|
prodLog.warn(`Type ${type} is hogging cache (${(sizeRatios[type] * 100).toFixed(1)}% size, ${(accessRatios[type] * 100).toFixed(1)}% access)`);
|
|
242
248
|
this.evictType(type);
|
|
243
249
|
}
|
|
244
250
|
}
|
|
245
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Proactive fairness check (v3.40.2)
|
|
254
|
+
* Called immediately when adding items to prevent imbalance formation
|
|
255
|
+
* Uses same thresholds as periodic check but runs on-demand
|
|
256
|
+
*/
|
|
257
|
+
checkProactiveFairness(addedType) {
|
|
258
|
+
// Quick check: only evaluate the type being added
|
|
259
|
+
let typeSize = 0;
|
|
260
|
+
for (const item of this.cache.values()) {
|
|
261
|
+
if (item.type === addedType) {
|
|
262
|
+
typeSize += item.size;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const sizeRatio = typeSize / (this.currentSize || 1);
|
|
266
|
+
const accessRatio = this.typeAccessCounts[addedType] / (this.totalAccessCount || 1);
|
|
267
|
+
// Same threshold as periodic check: 70% size, <15% access
|
|
268
|
+
if (sizeRatio > 0.7 && accessRatio < 0.15) {
|
|
269
|
+
prodLog.debug(`Proactive fairness: ${addedType} reaching dominance (${(sizeRatio * 100).toFixed(1)}% size, ${(accessRatio * 100).toFixed(1)}% access)`);
|
|
270
|
+
this.evictType(addedType);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
246
273
|
/**
|
|
247
274
|
* Force evict items of a specific type
|
|
248
275
|
*/
|
|
@@ -250,14 +277,14 @@ export class UnifiedCache {
|
|
|
250
277
|
const candidates = [];
|
|
251
278
|
for (const [key, item] of this.cache) {
|
|
252
279
|
if (item.type === type) {
|
|
253
|
-
const score = (this.access.get(key) || 1)
|
|
280
|
+
const score = (this.access.get(key) || 1) * item.rebuildCost;
|
|
254
281
|
candidates.push([key, score, item]);
|
|
255
282
|
}
|
|
256
283
|
}
|
|
257
284
|
// Sort by score (lower is worse)
|
|
258
285
|
candidates.sort((a, b) => a[1] - b[1]);
|
|
259
|
-
// Evict bottom
|
|
260
|
-
const evictCount = Math.max(1, Math.floor(candidates.length * 0.
|
|
286
|
+
// Evict bottom 50% of this type (v3.40.2: was 20%, too slow to prevent thrashing)
|
|
287
|
+
const evictCount = Math.max(1, Math.floor(candidates.length * 0.5));
|
|
261
288
|
for (let i = 0; i < evictCount && i < candidates.length; i++) {
|
|
262
289
|
const [key, , item] = candidates[i];
|
|
263
290
|
this.currentSize -= item.size;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@soulcraft/brainy",
|
|
3
|
-
"version": "3.40.
|
|
3
|
+
"version": "3.40.2",
|
|
4
4
|
"description": "Universal Knowledge Protocol™ - World's first Triple Intelligence database unifying vector, graph, and document search in one API. 31 nouns × 40 verbs for infinite expressiveness.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.js",
|