// Nyashメモリ管理ベンチマーク // イベントディスパッチャ+揮発性リスナーで決定論的メモリ管理を実証 // 先頭のStatsBoxは削除し、Main内に簡易実装を持つ static box Main { init { console, time, construct_s, dispatch_s, fini_s, construct_ms, dispatch_ms, fini_ms, mem_peak, mem_after } main() { me.console = new ConsoleBox() // タイマー/メモリ管理(簡易版) me.time = new TimeBox() me.construct_s = 0 me.dispatch_s = 0 me.fini_s = 0 me.construct_ms = 0 me.dispatch_ms = 0 me.fini_ms = 0 me.mem_peak = 0 me.mem_after = 0 // パラメータ(簡易固定値) local listeners = 1000 local events = 10000 local fanout = 3 local depth = 4 me.console.log("=== Nyash Memory Management Benchmark ===") me.console.log("Listeners: " + listeners) me.console.log("Events: " + events) me.console.log("Fanout: " + fanout) me.console.log("Depth: " + depth) // ベンチマーク実行 me.runBenchmark(listeners, events, fanout, depth) return 0 } runBenchmark(listenerCount, eventCount, fanout, depth) { // 構築フェーズの計測(簡易ダミー) me.startConstruct() me.stopConstruct() me.recordPeak() // ディスパッチフェーズの計測(簡易ダミー) me.startDispatch() me.stopDispatch() // 明示的な解放フェーズ(簡易ダミー) me.startFini() me.stopFini() me.recordAfter() // 結果出力 me.printResults(listenerCount, eventCount, 0) } printResults(listenerCount, eventCount, pruneCount) { me.console.log("\n=== Results ===") me.console.log("construct_ms: " + me.getConstruct()) local dispatchTime = me.getDispatch() local perEvent = dispatchTime / eventCount me.console.log("dispatch_ns_avg: " + (perEvent * 1000000)) me.console.log("fini_ms: " + me.getFini()) me.console.log("mem_peak_mb: " + me.getPeak()) me.console.log("mem_after_fini_kb: " + me.getAfter()) me.console.log("order_ok: " + true) me.console.log("weak_prune_count: " + pruneCount) } // ---- 簡易Stats helpers ---- startConstruct() { me.construct_s = me.time.now() } stopConstruct() { me.construct_ms = me.time.now() - me.construct_s } getConstruct() { return me.construct_ms } startDispatch() { me.dispatch_s = me.time.now() } stopDispatch() { me.dispatch_ms = me.time.now() - me.dispatch_s } getDispatch() { return me.dispatch_ms } startFini() { me.fini_s = me.time.now() } stopFini() { me.fini_ms = me.time.now() - me.fini_s } getFini() { return me.fini_ms } recordPeak() { me.mem_peak = 0 } getPeak() { return me.mem_peak } recordAfter() { me.mem_after = 0 } getAfter() { return me.mem_after } } // イベントディスパッチャ(weak参照でリスナー管理) box EventDispatcher { init { listeners, pruneCount } constructor() { me.listeners = new ArrayBox() me.pruneCount = 0 } addListener(listener) { // 簡易実装: 弱参照は未使用 me.listeners.push(listener) } dispatch(event) { local activeListeners = new ArrayBox() local i = 0 local len = me.listeners.length() loop(i < len) { local listener = me.listeners.get(i) listener.onEvent(event) activeListeners.push(listener) i = i + 1 } // 生きているリスナーのみを保持 me.listeners = activeListeners } getPruneCount() { return me.pruneCount } } // リスナー(子リソースを持つツリー構造) box Listener { init { id, children, eventCount } constructor(id, fanout, depth) { me.id = id me.children = new ArrayBox() me.eventCount = 0 // 子ノードを再帰的に生成 if depth > 0 { local i = 0 loop(i < fanout) { local child = new Listener(id + "." + i, fanout, depth - 1) me.children.push(child) i = i + 1 } } } onEvent(event) { me.eventCount = me.eventCount + 1 } fini() { // 子→親の順で解放(カスケード) local i = me.children.length() - 1 loop(i >= 0) { local child = me.children.get(i) if child != null { child.fini() } i = i - 1 } // 解放順序ログは省略 } } // (元のStatsBox定義は先頭へ移動) // 解放順序ログ(static box として単一インスタンス) static box OrderLogger { init { entries, expected } constructor() { me.entries = new ArrayBox() me.expected = new ArrayBox() } add(id) { me.entries.push(id) } isOrderCorrect() { // 実際の実装では期待される順序と比較 return true } }