import v8 from 'node:v8'; 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 buildNodes(arbiter, count, prefix) { for (let i = 0; i < count; i++) { arbiter.addNode(`${prefix}:${i}`, prefix); } } 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, 'user'); buildNodes(arbiter, size, 'resource'); 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); const relationConfigs = ['owner', 'viewer', 'group_tuple_to_userset', 'plan_chain', 'account_admin_chain', 'blocked_unless', 'age_abac', 'risk_limit', 'feature_flag', 'owa_union', 'owa_comparator_nested']; for (const relation of relationConfigs) { arbiter.setRelationConfig(relation, { type: 'direct' }); } } const args = parseArgs(process.argv); const sizes = parseSizes(args.get('sizes')) || [10000, 50000]; console.log('memory_breakdown'); console.log('size,space,space_used,space_size,space_available,physical'); for (const size of sizes) { const arbiter = new Arbiter(); gc(); buildGraph(arbiter, size); gc(); const spaces = v8.getHeapSpaceStatistics(); for (const space of spaces) { console.log([ size, space.space_name, formatBytes(space.space_used_size), formatBytes(space.space_size), formatBytes(space.space_available_size), formatBytes(space.physical_space_size) ].join(',')); } }