docs(plugin-arch): 归档插件架构迁移评估 + plan 第11节整改计划

- docs/zh/架构迁移评估.md: C ABI→子进程+共享内存完整迁移论证(1621行)
- docs/zh/experiments/: 18项可复跑可行性实验(架构评估的所有数字来源)
- plan.md §11: 11.1~11.9 插件架构缺陷修复清单(唯一权威编号)
- main 保持干净,本批次为 update 特性分支的整改起点
This commit is contained in:
dev
2026-08-31 11:45:52 +08:00
parent c4219767d4
commit 40a3efa955
34 changed files with 3552 additions and 0 deletions

View File

@ -0,0 +1,84 @@
//go:build ignore
package main
import (
"bufio"
"encoding/binary"
"encoding/json"
"fmt"
"os"
"os/exec"
"strings"
"sync"
"time"
"golang.org/x/sys/unix"
)
func main() {
fmt.Println("=== 实验 8:跨进程并发扇出改写同一 StageContext(最高风险点 3.4)===")
mfd, _ := unix.MemfdCreate("stagectx", 0)
unix.Ftruncate(mfd, 65536)
shmFile := os.NewFile(uintptr(mfd), "shm")
data, _ := unix.Mmap(mfd, 0, 65536, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
// 初始 final_text = "" @1024, arena 游标 = 1024
binary.LittleEndian.PutUint32(data[0:4], 1024)
binary.LittleEndian.PutUint32(data[4:8], 0)
binary.LittleEndian.PutUint32(data[8:12], 1024)
tags := []string{"A", "B", "C", "D", "E"} // 5 个并发插件
var mu sync.Mutex // 内核侧锁仲裁
var wg sync.WaitGroup
var rpcCount int64
var cntMu sync.Mutex
t0 := time.Now()
for _, tag := range tags {
cmd := exec.Command("go", "run", "exp8_worker.go", tag)
cmd.ExtraFiles = []*os.File{shmFile}
sin, _ := cmd.StdinPipe()
sout, _ := cmd.StdoutPipe()
cmd.Stderr = os.Stderr
cmd.Start()
wg.Add(1)
go func() {
defer wg.Done()
dec := json.NewDecoder(bufio.NewReader(sout))
w := bufio.NewWriter(sin)
enc := json.NewEncoder(w)
held := false
for {
var q map[string]string
if err := dec.Decode(&q); err != nil { break }
switch q["method"] {
case "stage.lock": mu.Lock(); held = true
case "stage.unlock": if held { mu.Unlock(); held = false }
}
cntMu.Lock(); rpcCount++; cntMu.Unlock()
enc.Encode(map[string]bool{"ok": true}); w.Flush()
}
if held { mu.Unlock() }
cmd.Wait()
}()
}
wg.Wait()
dur := time.Since(t0)
off := binary.LittleEndian.Uint32(data[0:4])
ln := binary.LittleEndian.Uint32(data[4:8])
final := string(data[off : off+ln])
fmt.Printf("\n--- 结果 ---\n")
fmt.Printf("最终 final_text 长度 = %d\n", len(final))
counts := map[string]int{}
for _, t := range tags { counts[t] = strings.Count(final, t) }
fmt.Printf("各插件写入次数: %v\n", counts)
total := 0
for _, c := range counts { total += c }
fmt.Printf("总字符 = %d, 长度 = %d → %s\n", total, len(final),
map[bool]string{true:"一致 ✅ 无丢失/无撕裂", false:"不一致 ❌"}[total == len(final)])
fmt.Printf("RPC 锁操作 = %d 次, 总耗时 %v\n", rpcCount, dur)
fmt.Printf("\n注:写入次数少于 5×300 是 arena 64KB 上限所致(append-only 未压实),符合设计\n")
}