Files
hakorune/apps/ny-mem-bench/main.hako

186 lines
5.3 KiB
Plaintext
Raw Normal View History

// 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
}
}