Files
core/benchmarks/memory-profile.js
T

135 lines
3.8 KiB
JavaScript
Raw Normal View History

import { Arbiter } from '../src/core/Arbiter.js';
function parseArgs(argv) {
const args = new Map();
for (let i = 2; i < argv.length; i++) {
const value = argv[i];
if (!value.startsWith('--')) continue;
const [key, inline] = value.slice(2).split('=');
if (inline !== undefined) {
args.set(key, inline);
continue;
}
const next = argv[i + 1];
if (next && !next.startsWith('--')) {
args.set(key, next);
i++;
} else {
args.set(key, true);
}
}
return args;
}
function parseSizes(value) {
if (!value) return null;
return value.split(',').map(item => Number(item.trim())).filter(Number.isFinite);
}
function formatBytes(bytes) {
const units = ['B', 'KB', 'MB', 'GB'];
let idx = 0;
let val = bytes;
while (val >= 1024 && idx < units.length - 1) {
val /= 1024;
idx++;
}
return `${val.toFixed(2)}${units[idx]}`;
}
function gc() {
if (global.gc) {
global.gc();
global.gc();
}
}
function measureMemory(label) {
const mem = process.memoryUsage();
return {
label,
rss: mem.rss,
heapUsed: mem.heapUsed,
heapTotal: mem.heapTotal,
external: mem.external
};
}
function buildNodes(arbiter, size) {
for (let i = 0; i < size; i++) {
arbiter.addNode(`user:${i}`, 'user');
arbiter.addNode(`resource:${i}`, 'resource');
}
}
function addEdges(arbiter, size, relation, perNode, srcPrefix = 'user', dstPrefix = 'resource') {
for (let i = 0; i < size; i++) {
for (let j = 0; j < perNode; j++) {
const dstId = (i + j) % size;
arbiter.addRelation(`${srcPrefix}:${i}`, relation, `${dstPrefix}:${dstId}`);
}
}
}
function buildGraph(arbiter, size) {
buildNodes(arbiter, size);
addEdges(arbiter, size, 'owner', 1);
addEdges(arbiter, size, 'viewer', 1);
addEdges(arbiter, size, 'group_tuple_to_userset', 1);
addEdges(arbiter, size, 'plan_chain', 1);
addEdges(arbiter, size, 'account_admin_chain', 1);
addEdges(arbiter, size, 'blocked_unless', 1);
addEdges(arbiter, size, 'age_abac', 2);
addEdges(arbiter, size, 'risk_limit', 2);
addEdges(arbiter, size, 'feature_flag', 1);
addEdges(arbiter, size, 'owa_union', 1);
addEdges(arbiter, size, 'owa_comparator_nested', 5);
arbiter.setRelationConfig('owner', { type: 'direct' });
arbiter.setRelationConfig('viewer', { type: 'direct' });
arbiter.setRelationConfig('group_tuple_to_userset', { type: 'direct' });
arbiter.setRelationConfig('plan_chain', { type: 'direct' });
arbiter.setRelationConfig('account_admin_chain', { type: 'direct' });
arbiter.setRelationConfig('blocked_unless', { type: 'direct' });
arbiter.setRelationConfig('age_abac', { type: 'direct' });
arbiter.setRelationConfig('risk_limit', { type: 'direct' });
arbiter.setRelationConfig('feature_flag', { type: 'direct' });
arbiter.setRelationConfig('owa_union', { type: 'direct' });
arbiter.setRelationConfig('owa_comparator_nested', { type: 'direct' });
}
const args = parseArgs(process.argv);
const sizes = parseSizes(args.get('sizes')) || [10000, 50000, 100000];
console.log('memory_profile');
console.log('size,nodes,edges,rss,heap_used,heap_total,external');
for (const size of sizes) {
const arbiter = new Arbiter();
gc();
const before = measureMemory('before');
buildGraph(arbiter, size);
gc();
const after = measureMemory('after');
const nodes = size * 2;
const edges = size * (1 + 1 + 1 + 1 + 1 + 1 + 2 + 2 + 1 + 1 + 5);
const delta = {
rss: after.rss - before.rss,
heapUsed: after.heapUsed - before.heapUsed,
heapTotal: after.heapTotal - before.heapTotal,
external: after.external - before.external
};
console.log([
size,
nodes,
edges,
formatBytes(delta.rss),
formatBytes(delta.heapUsed),
formatBytes(delta.heapTotal),
formatBytes(delta.external)
].join(','));
}