Рост памяти на Windows
Некоторые пользователи Windows наблюдают, как процесс bun, на котором работает opencodex,
разрастается до многих гигабайт RSS во время долгих streaming-сессий (issue
#314). Эта страница честно объясняет, что
именно происходит и что вы можете сделать сейчас.
Корневая причина: проблемы в upstream-рантайме Bun
Заголовок раздела «Корневая причина: проблемы в upstream-рантайме Bun»opencodex поставляет рантайм Bun (сейчас это 1.3.14). Рост памяти вызван известными проблемами upstream Bun, а не JavaScript-утечками внутри прокси:
| Проблема Bun | Состояние (проверено 2026-07-23) |
|---|---|
#28035 — backpressure в fetch() receive не связан с потреблением на стороне JS |
Исправлено в PR #29831; в каком релизе это появилось, не подтверждено — мы исходим из того, что в комплектном 1.3.14 этого ещё нет |
| #32111 — crash при отмене async-pull stream клиентом | Исправление PR #32120 смёржено 2026-06-21; не предполагается, что оно уже есть в 1.3.14. Важно: этот crash не специфичен для Windows (он воспроизводился и на macOS/Linux) |
PR #31654 — утечка socket handle в node:net |
Всё ещё open в upstream |
На Windows opencodex вынужден оставлять streaming-ответы на более консервативном пути кода, чтобы избежать crash из #32111, а именно этот путь сильнее всего подвержен проблеме backpressure: медленный или зависший клиент может оставить рантайм буферизовать upstream-данные в нативной памяти, которую JavaScript уже не может ограничить.
Что opencodex делает сегодня
Заголовок раздела «Что opencodex делает сегодня»Есть ограниченные меры и наблюдаемость — не исправление. На комплектном рантайме 1.3.14 сама утечка остаётся проблемой upstream:
- Memory watchdog — прокси раз в минуту измеряет собственную память и пишет rate-limited
предупреждение, когда наблюдаемая память пересекает 4 GiB. Наблюдаемая память — это максимум из
RSS,
externalиarrayBuffers(а не их сумма), потому что счётчики working set/RSS на Windows могут занижать коммит удерживаемой external-памяти. ocx doctor— раздел “Memory / runtime” показывает версию Bun у service-процесса, RSS, счётчики external/ArrayBuffers, контекст JS-heap и выбранный stream mode. На комплектном Bun 1.3.14 одних толькоheapUsed/jscHeapнедостаточно, чтобы отличить утечку; сравнивайте наблюдаемую память сresponseStateи повторными сэмплами, прежде чем записывать это на app-level leak.GET /api/system/memory— те же данные через аутентифицированный management API для дашбордов и сценариев. Помимо счётчиков RSS/heap/external он возвращает скалярный блокresponseState(число записей, суммарный/максимальный сериализованный размер, возраст самой старой записи) для in-memory store продолженийprevious_response_idв прокси. Это помогает точнее отнести рост: если растут иresponseState.totalBytes, и наблюдаемая память, проблема может быть в удержании длинных цепочекstore:false; еслиresponseStateплоский, а память растёт, причину нужно искать вне этого store. Значения только скалярные — без тел запросов, токенов, путей и идентификаторов аккаунтов — и чтение не имеет побочных эффектов: ничего не prune’ится и не evict’ится. Карточка Memory observability в дашборде показывает те же поля и даёт confirm-gated действие Drain & restart: она показывает текущее число активных ходов, ждёт до 60 секунд, пока они закончатся (используя уже существующий drain через 503 +Retry-After), затем прерывает оставшиеся ходы, просит аттестованный живой процесс заменить себя и проверяет другой PID на том же порту, не снимая внедрение в Codex. Это более длинный и осознанный recycle, чем короткий drain уPOST /api/stop.- Альтернативный stream path под флагом — bounded single-reader relay, полностью убирающий
форму неограниченной буферизации. На Windows он станет значением по умолчанию автоматически,
когда в комплектный Bun подтверждённо войдёт исправление #32111; сегодня это только opt-in
(см. ниже). На macOS он останется opt-in даже после такого релиза — решение по
autoдля macOS будет приниматься отдельно.
Подтверждение реального снижения RSS от этих изменений ещё ждёт проверки пользователями Windows — мы не утверждаем, что утечка уже исправлена.
Пороговый auto-restart намеренно не поставляется. Если процесс всё же падает, его и так перезапускают service manager’ы (Task Scheduler/WinSW, launchd, systemd).
Что вы можете сделать
Заголовок раздела «Что вы можете сделать»-
Подождать обновления комплектного рантайма. Когда релиз Bun подтверждённо будет содержать эти исправления, opencodex обновит bundled runtime, и более безопасный stream path автоматически включится на Windows (на macOS он всё равно останется только явным opt-in).
-
Запустить Bun, которому вы доверяете, через
OPENCODEX_BUN_PATH. Это непроверенная территория — вы запускаете opencodex на рантайме, который мы не тестировали, на свой риск. Важно для service-установок: override считывается при генерации артефакта службы, а не при её старте. Задайте переменную окружения и заново выполнитеocx service repairиз той же оболочки, чтобы путь оказался зашит в долговременное определение службы. Одной только переменной для уже установленной службы недостаточно. -
Явно перейти на bounded relay через
streamMode: "eager-relay". Есть два пути: отредактироватьconfig.json(добавить"streamMode": "eager-relay") или вызвать management API —PUT /api/settingsс{"streamMode":"eager-relay"}применит изменение к новым ходам без перезапуска. Предупреждение о риске crash: на Bun 1.3.14 это использует форму streaming, затронутую #32111, и процесс может упасть прямо посреди потока (на любой ОС, не только на Windows). Service manager перезапустит его, но все запросы в полёте потерпят неудачу."legacy-tee"жёстко фиксирует текущий путь по умолчанию. На Windows"auto"(по умолчанию) позволяет рантайму выбрать путь самому. На macOS"auto"всегда остаётся на tee; явный"eager-relay"— это opt-in.
Если вы попробуете любой из этих вариантов на реальной Windows-нагрузке, пожалуйста, пришлите
разделы памяти из ocx doctor до и после в
#314 — именно такой верификации эта мера и
ждёт.

