Files
core/tests/engine/memory-usage.test.js
T

163 lines
5.2 KiB
JavaScript
Raw Normal View History

import assert from 'node:assert/strict';
import { describe, test } from 'node:test';
import { Arbiter } from '../../src/core/Arbiter.js';
const runPerf = process.env.RUN_PERF_TESTS === '1';
const perfTest = runPerf ? test : test.skip;
describe('Memory Usage and Performance', () => {
perfTest('memory usage grows linearly with node count', () => {
const arbiter = new Arbiter();
const numNodes = 10000;
for (let i = 0; i < numNodes; i++) {
arbiter.addNode(`node:${i}`, 'node');
}
const memoryUsage = process.memoryUsage();
const memoryMB = memoryUsage.heapUsed / (1024 * 1024);
console.log(`Memory for ${numNodes} nodes: ${memoryMB.toFixed(2)} MB`);
assert.ok(memoryMB < 100, `Memory usage (${memoryMB.toFixed(2)} MB) should be reasonable`);
});
perfTest('memory usage for graph with edges', () => {
const arbiter = new Arbiter();
const numNodes = 5000;
const edgesPerNode = 3;
for (let i = 0; i < numNodes; i++) {
arbiter.addNode(`node:${i}`, 'node');
}
arbiter.setRelationConfig('connect', { type: 'direct' });
for (let i = 0; i < numNodes; i++) {
for (let j = 1; j <= edgesPerNode && i + j < numNodes; j++) {
arbiter.addRelation(`node:${i}`, 'connect', `node:${i + j}`, 1.0);
}
}
const memoryUsage = process.memoryUsage();
const memoryMB = memoryUsage.heapUsed / (1024 * 1024);
console.log(`Memory for ${numNodes} nodes with ${numNodes * edgesPerNode} edges: ${memoryMB.toFixed(2)} MB`);
assert.ok(memoryMB < 200, `Memory usage (${memoryMB.toFixed(2)} MB) should be reasonable`);
});
perfTest('large graph stays within 128MB limit', () => {
const arbiter = new Arbiter();
const numNodes = 30000;
const edgesPerNode = 3;
arbiter.setRelationConfig('connect', { type: 'direct' });
for (let i = 0; i < numNodes; i++) {
arbiter.addNode(`node:${i}`, 'node');
}
for (let i = 0; i < numNodes; i++) {
for (let j = 1; j <= edgesPerNode && i + j < numNodes; j++) {
arbiter.addRelation(`node:${i}`, 'connect', `node:${i + j}`, 1.0);
}
}
const memoryUsage = process.memoryUsage();
const memoryMB = memoryUsage.heapUsed / (1024 * 1024);
console.log(`Memory for ${numNodes} nodes: ${memoryMB.toFixed(2)} MB`);
assert.ok(memoryMB < 250, `Memory usage (${memoryMB.toFixed(2)} MB) must be reasonable`);
});
perfTest('direct check cache improves performance', () => {
const arbiter = new Arbiter();
for (let i = 0; i < 1000; i++) {
arbiter.addNode(`user:${i}`, 'user');
arbiter.addNode(`resource:${i}`, 'resource');
}
arbiter.setRelationConfig('member', { type: 'direct' });
for (let i = 0; i < 1000; i++) {
arbiter.addRelation(`user:${i}`, 'member', `resource:${i}`, 1.0);
}
for (let i = 0; i < 200; i++) {
arbiter.check(`user:${i % 100}`, 'member', `resource:${i % 100}`);
}
const runBatch = () => {
const start = performance.now();
for (let i = 0; i < 500; i++) {
arbiter.check(`user:${i % 100}`, 'member', `resource:${i % 100}`);
}
return performance.now() - start;
};
const time1 = runBatch();
const time2 = runBatch();
const time3 = runBatch();
const time4 = runBatch();
const time5 = runBatch();
console.log(`First batch: ${time1}ms, Second batch: ${time2}ms, Third batch: ${time3}ms, Fourth batch: ${time4}ms, Fifth batch: ${time5}ms`);
if (arbiter.directCheckCache) {
const warmTimes = [time2, time3, time4, time5].sort((a, b) => a - b);
const medianWarm = (warmTimes[1] + warmTimes[2]) / 2;
assert.ok(medianWarm <= time1 * 1.5, `Cached queries should be at least as fast (${medianWarm}ms <= ${time1}ms)`);
} else {
console.log('Direct check cache is disabled');
}
});
perfTest('query performance scales linearly with graph size', () => {
const arbiter = new Arbiter();
const numNodes = 5000;
for (let i = 0; i < numNodes; i++) {
arbiter.addNode(`node:${i}`, 'node');
}
arbiter.setRelationConfig('connect', { type: 'direct' });
for (let i = 0; i < numNodes - 1; i++) {
arbiter.addRelation(`node:${i}`, 'connect', `node:${i + 1}`, 1.0);
}
const start = Date.now();
const result = arbiter.check('node:0', 'connect', 'node:1');
const duration = Date.now() - start;
console.log(`Query time: ${duration}ms`);
assert.strictEqual(result.possibility, 1.0);
assert.ok(duration < 1000, `Query should be fast, took ${duration}ms`);
});
perfTest('batch relation addition is efficient', () => {
const arbiter = new Arbiter();
const numNodes = 20000;
arbiter.setRelationConfig('connect', { type: 'direct' });
for (let i = 0; i < numNodes; i++) {
arbiter.addNode(`node:${i}`, 'node');
}
const start = Date.now();
for (let i = 0; i < numNodes - 1; i++) {
arbiter.addRelation(`node:${i}`, 'connect', `node:${i + 1}`, 1.0);
}
const duration = Date.now() - start;
console.log(`Batch addition time: ${duration}ms for ${numNodes - 1} relations`);
assert.ok(duration < 5000, `Batch addition should be fast, took ${duration}ms`);
});
});