Spaces:
Paused
Paused
opencode commited on
Commit ·
2554817
1
Parent(s): 7ead267
memguard: 總上限 96->80 GiB, 單一行程 80->64 GiB
Browse files
AGENTS.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
| 1 |
# 記憶體上限規則(必遵守)
|
| 2 |
|
| 3 |
本機有一支記憶體守衛 `/root/memkill.py`,每 2 秒掃一次。
|
| 4 |
-
**規則:我(opencode)啟動的任何程式,記憶體一律不得超過
|
| 5 |
|
| 6 |
## 守衛行為
|
| 7 |
|
| 8 |
-
- 觸發條件:`opencode 本體 + 我啟動的所有子行程` 合計 RSS > **
|
| 9 |
- 處置:對記憶體最肥的那個子行程樹送 `SIGKILL`(連同它的子行程)。
|
| 10 |
- **opencode 本體永遠不會被砍**,只砍我開出去的程式。
|
| 11 |
- 我在 CLI 看到的現象:該指令 exit code 137 / 顯示 `Killed` / 沒有任何輸出。
|
|
@@ -20,7 +20,7 @@ cat /tmp/memkill.last.json # 被砍的是哪條指令、峰值多少 GiB
|
|
| 20 |
1. **絕對不要用同一種做法重跑一次。** 那是確定會再被砍一次。
|
| 21 |
2. 先讀 `/tmp/memkill.last.json` 確認峰值用量與被砍的指令。
|
| 22 |
3. 改用低記憶體做法(見下表),先向用戶說明「原本那條路已因記憶體超標被放棄,改用 O」,再執行。
|
| 23 |
-
4. 改完仍需要 >
|
| 24 |
|
| 25 |
## 低記憶體替代做法
|
| 26 |
|
|
@@ -37,4 +37,4 @@ cat /tmp/memkill.last.json # 被砍的是哪條指令、峰值多少 GiB
|
|
| 37 |
|
| 38 |
- 跑任何吃記憶體的指令前先估量:`du -sh <path>`、`wc -l <file>`。
|
| 39 |
- 預估會超過 2 GiB 記憶體時,直接改用分批/串流版本,不要先跑再說。
|
| 40 |
-
- 需要 `prlimit` 硬上限時用 `prlimit --data=
|
|
|
|
| 1 |
# 記憶體上限規則(必遵守)
|
| 2 |
|
| 3 |
本機有一支記憶體守衛 `/root/memkill.py`,每 2 秒掃一次。
|
| 4 |
+
**規則:我(opencode)啟動的任何程式,記憶體一律不得超過 80 GiB。**
|
| 5 |
|
| 6 |
## 守衛行為
|
| 7 |
|
| 8 |
+
- 觸發條件:`opencode 本體 + 我啟動的所有子行程` 合計 RSS > **80 GiB**(單一子行程 > 64 GiB 也直接砍)。
|
| 9 |
- 處置:對記憶體最肥的那個子行程樹送 `SIGKILL`(連同它的子行程)。
|
| 10 |
- **opencode 本體永遠不會被砍**,只砍我開出去的程式。
|
| 11 |
- 我在 CLI 看到的現象:該指令 exit code 137 / 顯示 `Killed` / 沒有任何輸出。
|
|
|
|
| 20 |
1. **絕對不要用同一種做法重跑一次。** 那是確定會再被砍一次。
|
| 21 |
2. 先讀 `/tmp/memkill.last.json` 確認峰值用量與被砍的指令。
|
| 22 |
3. 改用低記憶體做法(見下表),先向用戶說明「原本那條路已因記憶體超標被放棄,改用 O」,再執行。
|
| 23 |
+
4. 改完仍需要 > 80 GiB 的話:**停下來問用戶**,不要硬跑、不要偷偷繞過守衛。
|
| 24 |
|
| 25 |
## 低記憶體替代做法
|
| 26 |
|
|
|
|
| 37 |
|
| 38 |
- 跑任何吃記憶體的指令前先估量:`du -sh <path>`、`wc -l <file>`。
|
| 39 |
- 預估會超過 2 GiB 記憶體時,直接改用分批/串流版本,不要先跑再說。
|
| 40 |
+
- 需要 `prlimit` 硬上限時用 `prlimit --data=80G -- <cmd>`(**不要用 `--as`**,bun/node 類程式會秒死)。
|
README.md
CHANGED
|
@@ -30,7 +30,7 @@ OpenCode 在啟動時安裝,並重設使用者層級設定為預設值。
|
|
| 30 |
每次 Space 啟動時,`app.py` 的 `install_memguard()` 會自動:
|
| 31 |
|
| 32 |
- 把 repo 的 `memguard.py` 複製到 `~/memkill.py` 並啟動它
|
| 33 |
-
- `opencode` 本體 + 它啟動的所有子行程合計 RSS > **
|
| 34 |
- **只砍子行程,opencode 本體永不砍**
|
| 35 |
- 被砍的指令與峰值寫入 `/tmp/memkill.last.json`、歷史 `/tmp/memkill.jsonl`、log `/var/log/memkill.log`
|
| 36 |
- 把 repo 的 `AGENTS.md` 複製到 `~/.config/opencode/AGENTS.md`
|
|
|
|
| 30 |
每次 Space 啟動時,`app.py` 的 `install_memguard()` 會自動:
|
| 31 |
|
| 32 |
- 把 repo 的 `memguard.py` 複製到 `~/memkill.py` 並啟動它
|
| 33 |
+
- `opencode` 本體 + 它啟動的所有子行程合計 RSS > **80 GiB**(單一行程 > **64 GiB**)→ 對記憶體最肥的那個子行程樹送 `SIGKILL`
|
| 34 |
- **只砍子行程,opencode 本體永不砍**
|
| 35 |
- 被砍的指令與峰值寫入 `/tmp/memkill.last.json`、歷史 `/tmp/memkill.jsonl`、log `/var/log/memkill.log`
|
| 36 |
- 把 repo 的 `AGENTS.md` 複製到 `~/.config/opencode/AGENTS.md`
|
app.py
CHANGED
|
@@ -670,8 +670,8 @@ def reset_opencode_config():
|
|
| 670 |
# 規則:opencode 及其啟動的子行程合計不得超過 MEMGUARD_TOTAL_GIB,單一行程不得超過
|
| 671 |
# MEMGUARD_PER_PROC_GIB;超過只砍子行程,opencode 本體永不砍。
|
| 672 |
# 規則文字放在 Space repo 的 AGENTS.md,啟動時複製到 ~/.config/opencode/AGENTS.md。
|
| 673 |
-
MEMGUARD_TOTAL_GIB = int(os.environ.get("MEMGUARD_TOTAL_GIB", "
|
| 674 |
-
MEMGUARD_PER_PROC_GIB = int(os.environ.get("MEMGUARD_PER_PROC_GIB", "
|
| 675 |
MEMGUARD_PIDFILE = "/tmp/.memguard.pid"
|
| 676 |
MEMGUARD_LOG = "/var/log/memkill.log"
|
| 677 |
|
|
|
|
| 670 |
# 規則:opencode 及其啟動的子行程合計不得超過 MEMGUARD_TOTAL_GIB,單一行程不得超過
|
| 671 |
# MEMGUARD_PER_PROC_GIB;超過只砍子行程,opencode 本體永不砍。
|
| 672 |
# 規則文字放在 Space repo 的 AGENTS.md,啟動時複製到 ~/.config/opencode/AGENTS.md。
|
| 673 |
+
MEMGUARD_TOTAL_GIB = int(os.environ.get("MEMGUARD_TOTAL_GIB", "80"))
|
| 674 |
+
MEMGUARD_PER_PROC_GIB = int(os.environ.get("MEMGUARD_PER_PROC_GIB", "64"))
|
| 675 |
MEMGUARD_PIDFILE = "/tmp/.memguard.pid"
|
| 676 |
MEMGUARD_LOG = "/var/log/memkill.log"
|
| 677 |
|
memguard.py
CHANGED
|
@@ -15,9 +15,9 @@ import signal
|
|
| 15 |
import sys
|
| 16 |
import time
|
| 17 |
|
| 18 |
-
LIMIT = float(sys.argv[1] if len(sys.argv) > 1 else
|
| 19 |
INTERVAL = float(sys.argv[2] if len(sys.argv) > 2 else 2)
|
| 20 |
-
PER_PROC = float(sys.argv[3] if len(sys.argv) > 3 else
|
| 21 |
MARK = "/tmp/memkill.last.json"
|
| 22 |
HIST = "/tmp/memkill.jsonl"
|
| 23 |
PAGE = os.sysconf("SC_PAGE_SIZE")
|
|
|
|
| 15 |
import sys
|
| 16 |
import time
|
| 17 |
|
| 18 |
+
LIMIT = float(sys.argv[1] if len(sys.argv) > 1 else 80) * 1024 ** 3
|
| 19 |
INTERVAL = float(sys.argv[2] if len(sys.argv) > 2 else 2)
|
| 20 |
+
PER_PROC = float(sys.argv[3] if len(sys.argv) > 3 else 64) * 1024 ** 3
|
| 21 |
MARK = "/tmp/memkill.last.json"
|
| 22 |
HIST = "/tmp/memkill.jsonl"
|
| 23 |
PAGE = os.sysconf("SC_PAGE_SIZE")
|