✅ Phase 9.75実装計画追加: - copilot_issues.txtにPhase 9.75追加(Phase 9.7と9.8の間) - Arc<Mutex>二重化問題の根本解決計画 - 段階的実装戦略(Phase A-D)定義 📚 Box設計ドキュメント完全体系化: - docs/説明書/reference/box-design/ 新設 - everything-is-box.md: 核心哲学の完全解説 - memory-management.md: Arc<Mutex>設計・fini/weak参照 - delegation-system.md: 完全明示デリゲーション仕様 - box-types-catalog.md: 全Box型の完全カタログ - ffi-abi-specification.md: FFI/ABI仕様(移動済み) 🔧 実装ノート完備: - current-issues.md: 現在進行中の設計課題 - socket-box-problem.md: Arc<Mutex>二重化問題詳細分析 - phase-9-75-redesign.md: 実装計画詳細 👥 Copilot実装ガイド作成: - phase9_75_socketbox_arc_mutex_redesign.md - SocketBox優先対応の具体的実装手順 - 完全テストスイート設計 - 段階的実装戦略(Step 1-5) 📋 CURRENT_TASK.md更新: - Box設計ドキュメント完成記録 - Phase 9.75準備完了状況 🎯 効果: - Everything is Box哲学の体系的文書化 - SocketBox問題解決の明確な道筋 - Copilot協調実装の準備完了 - 新規開発者オンボーディング改善 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
6.9 KiB
6.9 KiB
🧠 Nyash メモリ管理設計
📋 概要
Nyashは「Everything is Box」哲学のもと、すべての値をBoxとして統一的に管理します。 メモリ安全性を保証しながら、シンプルで直感的なメモリ管理を実現しています。
🏗️ 基本アーキテクチャ
Arc一元管理
// インタープリターレベルでの統一管理
type NyashObject = Arc<Mutex<dyn NyashBox>>;
すべてのBoxは、インタープリターレベルでArc<Mutex>によって管理されます。
これにより:
- スレッドセーフティ: 自動的に保証
- 参照カウント: 自動的なメモリ解放
- 統一的アクセス: すべて同じ方法で操作
❌ アンチパターン(Phase 9.75で修正中)
// 現在の問題: Box内部での二重ロック
pub struct BadBox {
data: Arc<Mutex<String>>, // ❌ Box内部でロック管理
}
// 正しい設計
pub struct GoodBox {
data: String, // ✅ シンプルなフィールド
}
🔄 fini()システム
概要
Nyashは決定論的なリソース解放のためにfini()システムを提供します。
box FileHandler {
init { file }
fini() {
// オブジェクト削除時に自動呼び出し
if me.file != null {
me.file.close()
console.log("File closed automatically")
}
}
}
fini()の特徴
- 自動呼び出し: オブジェクトの参照がゼロになると自動実行
- 決定論的: GCのタイミングに依存しない
- 伝播: 親オブジェクトのfini()が子オブジェクトに伝播
実装例
box DatabaseConnection {
init { connection, transactions }
fini() {
// トランザクションをすべてロールバック
for tx in me.transactions {
tx.rollback()
}
// 接続を閉じる
me.connection.close()
}
}
// 使用例
{
local db = new DatabaseConnection()
db.connect("localhost:5432")
// ... データベース操作 ...
} // スコープを抜けると自動的にfini()が呼ばれる
💭 weak参照システム
循環参照の問題と解決
// 循環参照の例
box Parent {
init { children }
pack() {
me.children = new ArrayBox()
}
addChild(child) {
me.children.push(child)
child.parent = me // 循環参照!
}
}
box Child {
init { parent }
}
weak参照による解決
box Parent {
init { children }
pack() {
me.children = new ArrayBox()
}
addChild(child) {
me.children.push(child)
child.parent = weak me // weak参照で循環を防ぐ
}
}
box Child {
init { parent } // weak参照として保持
getParent() {
// weak参照から通常参照を取得
local p = strong me.parent
if p == null {
console.log("Parent has been deleted")
return null
}
return p
}
}
weak参照の特徴
- 自動null化: 参照先が削除されるとnullになる
- メモリリーク防止: 循環参照を断ち切る
- 明示的変換:
strongで通常参照に変換
📊 メモリ管理パターン
1. 所有権パターン
box Container {
init { items } // Containerがitemsを所有
pack() {
me.items = new ArrayBox()
}
fini() {
// itemsも自動的に解放される
console.log("Container and all items released")
}
}
2. 共有参照パターン
// 複数のオブジェクトで共有
local sharedData = new DataBox()
local viewer1 = new DataViewer(sharedData)
local viewer2 = new DataViewer(sharedData)
// sharedDataは両方のviewerから参照されている間は生存
3. 観察者パターン
box Subject {
init { observers }
pack() {
me.observers = new ArrayBox()
}
attach(observer) {
// weak参照で観察者を保持
me.observers.push(weak observer)
}
notify() {
// weak参照をチェックしながら通知
local aliveObservers = new ArrayBox()
for weakObs in me.observers {
local obs = strong weakObs
if obs != null {
obs.update(me)
aliveObservers.push(weakObs)
}
}
// 死んだ参照を削除
me.observers = aliveObservers
}
}
🛡️ メモリ安全性保証
1. 二重解放防止
Arcにより、同じオブジェクトの二重解放は不可能。
2. Use-After-Free防止
参照カウントにより、使用中のオブジェクトは解放されない。
3. データ競合防止
Mutexにより、同時アクセスは自動的に同期される。
4. メモリリーク検出
// デバッグモードでメモリリーク検出
DEBUG = new DebugBox()
DEBUG.startTracking()
// ... プログラム実行 ...
print(DEBUG.memoryReport())
// 出力: 未解放オブジェクト一覧
🚀 ベストプラクティス
1. fini()の正しい使い方
box ResourceManager {
init { resources }
fini() {
// 1. 子リソースから順に解放
for resource in me.resources {
resource.release()
}
// 2. 自身のリソースを解放
me.cleanup()
// 3. ログを残す(デバッグ用)
console.log("ResourceManager cleaned up")
}
}
2. weak参照の使い時
- 親子関係: 子→親はweak参照
- イベントリスナー: Subject→Observerはweak参照
- キャッシュ: 一時的な参照はweak
3. メモリ効率的なコード
// ❌ 非効率
loop(i < 1000000) {
local temp = new StringBox("temp")
// tempが毎回作られる
}
// ✅ 効率的
local temp = new StringBox("")
loop(i < 1000000) {
temp.set("temp")
// 既存オブジェクトを再利用
}
📈 パフォーマンス考慮事項
1. 参照カウントのオーバーヘッド
- 小さいが無視できない
- ホットパスでは最小限に
2. Mutexロックの競合
- Phase 9.75で一元化により改善予定
- 細粒度ロックを避ける
3. fini()の実行コスト
- 複雑なfini()は避ける
- 非同期処理は避ける
🔮 将来の拡張
1. 世代別GC
参照カウントと世代別GCのハイブリッド検討
2. メモリプール
頻繁に生成・破棄されるBoxのプール化
3. コンパクション
メモリ断片化対策
関連ドキュメント: