186 lines
5.3 KiB
Plaintext
186 lines
5.3 KiB
Plaintext
// 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
|
||
}
|
||
}
|