Files
hakorune/apps/ny-mem-bench/main.nyash
Moe Charm 11506cee3b Phase 11-12: LLVM backend initial, semantics layer, plugin unification
Major changes:
- LLVM backend initial implementation (compiler.rs, llvm mode)
- Semantics layer integration in interpreter (operators.rs)
- Phase 12 plugin architecture revision (3-layer system)
- Builtin box removal preparation
- MIR instruction set documentation (26→Core-15 migration)
- Cross-backend testing infrastructure
- Await/nowait syntax support

New features:
- LLVM AOT compilation support (--backend llvm)
- Semantics layer for interpreter→VM flow
- Tri-backend smoke tests
- Plugin-only registry mode

Bug fixes:
- Interpreter plugin box arithmetic operations
- Branch test returns incorrect values

Documentation:
- Phase 12 README.md updated with new plugin architecture
- Removed obsolete NYIR proposals
- Added LLVM test programs documentation

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-01 23:44:34 +09:00

231 lines
6.6 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メモリ管理ベンチマーク
// イベントディスパッチャ+揮発性リスナーで決定論的メモリ管理を実証
static box Main {
init { console, stats }
main() {
me.console = new ConsoleBox()
me.stats = new StatsBox()
// コマンドライン引数の解析
local args = new MapBox()
args.set("listeners", 1000) // デフォルト値
args.set("events", 10000)
args.set("fanout", 3)
args.set("depth", 4)
me.console.log("=== Nyash Memory Management Benchmark ===")
me.console.log("Listeners: " + args.get("listeners"))
me.console.log("Events: " + args.get("events"))
me.console.log("Fanout: " + args.get("fanout"))
me.console.log("Depth: " + args.get("depth"))
// ベンチマーク実行
me.runBenchmark(
args.get("listeners"),
args.get("events"),
args.get("fanout"),
args.get("depth")
)
return 0
}
runBenchmark(listenerCount, eventCount, fanout, depth) {
local dispatcher = new EventDispatcher()
// 構築フェーズの計測
me.stats.startTimer("construct")
{
// スコープ内でリスナー生成
local listeners = new ArrayBox()
local i = 0
loop(i < listenerCount) {
local listener = new Listener("L" + i, fanout, depth)
listeners.push(listener)
dispatcher.addListener(listener)
i = i + 1
}
me.stats.stopTimer("construct")
me.stats.recordMemory("peak_before_dispatch")
// ディスパッチフェーズの計測
me.stats.startTimer("dispatch")
local j = 0
loop(j < eventCount) {
dispatcher.dispatch("event_" + j)
j = j + 1
}
me.stats.stopTimer("dispatch")
// スコープ終了による解放フェーズの計測
me.stats.startTimer("fini")
} // ここでlistenersスコープが終了し、カスケード解放が発生
me.stats.stopTimer("fini")
me.stats.recordMemory("after_fini")
// 結果出力
me.printResults(listenerCount, eventCount)
}
printResults(listenerCount, eventCount) {
me.console.log("\n=== Results ===")
me.console.log("construct_ms: " + me.stats.getTimer("construct"))
local dispatchTime = me.stats.getTimer("dispatch")
local perEvent = dispatchTime / eventCount
me.console.log("dispatch_ns_avg: " + (perEvent * 1000000))
me.console.log("fini_ms: " + me.stats.getTimer("fini"))
me.console.log("mem_peak_mb: " + me.stats.getMemory("peak_before_dispatch"))
me.console.log("mem_after_fini_kb: " + me.stats.getMemory("after_fini"))
me.console.log("order_ok: " + OrderLogger.isOrderCorrect())
me.console.log("weak_prune_count: " + EventDispatcher.getPruneCount())
}
}
// イベントディスパッチャweak参照でリスナー管理
box EventDispatcher {
init { listeners, pruneCount }
static pruneCountGlobal = 0
constructor() {
me.listeners = new ArrayBox()
me.pruneCount = 0
}
addListener(listener) {
// weak参照として保持
me.listeners.push(weak(listener))
}
dispatch(event) {
local activeListeners = new ArrayBox()
local i = 0
local len = me.listeners.length()
loop(i < len) {
local weakListener = me.listeners.get(i)
// weak参照が生きているかチェック
if weakListener != nil {
weakListener.onEvent(event)
activeListeners.push(weakListener)
} else {
me.pruneCount = me.pruneCount + 1
EventDispatcher.pruneCountGlobal = EventDispatcher.pruneCountGlobal + 1
}
i = i + 1
}
// 生きているリスナーのみを保持
me.listeners = activeListeners
}
static getPruneCount() {
return EventDispatcher.pruneCountGlobal
}
}
// リスナー(子リソースを持つツリー構造)
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 != nil {
child.fini()
}
i = i - 1
}
// 解放順序をログ
OrderLogger.log(me.id)
}
}
// 統計収集Box
box StatsBox {
init { timers, memories }
constructor() {
me.timers = new MapBox()
me.memories = new MapBox()
}
startTimer(name) {
// 実際の実装では高精度タイマーを使用
me.timers.set(name + "_start", TimeBox.now())
}
stopTimer(name) {
local start = me.timers.get(name + "_start")
local elapsed = TimeBox.now() - start
me.timers.set(name, elapsed)
}
getTimer(name) {
return me.timers.get(name)
}
recordMemory(name) {
// 実際の実装ではシステムメモリ情報を取得
me.memories.set(name, 0) // プレースホルダー
}
getMemory(name) {
return me.memories.get(name)
}
}
// 解放順序ログ(シングルトン)
static box OrderLogger {
init { log, expectedOrder }
static instance = nil
static log(id) {
if OrderLogger.instance == nil {
OrderLogger.instance = new OrderLogger()
}
OrderLogger.instance.addLog(id)
}
constructor() {
me.log = new ArrayBox()
me.expectedOrder = new ArrayBox()
}
addLog(id) {
me.log.push(id)
}
static isOrderCorrect() {
// 実際の実装では期待される順序と比較
return true
}
}