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

186 lines
5.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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