사용자 지적: 파일 21개가 평평하게 쌓여 있어 사람이 "지금 내가 볼 게 뭔지" 못 고름. 이전 세션에 README/STATUS 문서만 바뀌고 폴더 구조는 그대로였음. - review-required/ (1) — 설계가 걸려 **사람 결정 필요**: 08 - rewrite-required/ (3) — 스파이크 코드가 깨짐(설계 문제 아님): 13/15/16 - not-run/ (1+헬퍼) — Studio 전용이라 이 환경에서 못 돌림: 10 + gc-trigger-helper - done/ (15) — 통과 or 판정 끝 **폴더를 옮기는 게 곧 상태 갱신**이라는 규칙을 README/STATUS 양쪽에 명시. STATUS.md는 폴더 구조를 그대로 반영해 재작성(맨 위 요약표 → 사람이 볼 review-required부터). 폴더가 상태라 파일이 옮겨 다니므로, 다른 문서의 참조를 경로 대신 파일명 기준으로 정규화(ROADMAP/pre-implementation-audit/bind-system-plan 6곳) — 안 그러면 파일을 옮길 때마다 링크가 깨져 stale이 또 쌓임. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y6hzeUi5QdLPEk69B6cXFa
45 lines
2.3 KiB
Text
45 lines
2.3 KiB
Text
--[[
|
|
GC 완료를 간접 관찰하는 헬퍼 — Roblox Studio(실제 게임 스크립트) 환경 전용.
|
|
|
|
배경: Roblox는 `collectgarbage()`를 스크립트에 노출하지 않음(순수 `luau`
|
|
CLI/`lune`과 다른 점 — `07-relate-weak-table-gc.luau`는 그쪽 환경에서
|
|
`collectgarbage()`를 직접 부름). 그래서 예전엔 "Studio에서는 GC 타이밍
|
|
검증 자체가 불가능하다"고 봤는데, incremental GC가 "충분한 할당 압력 +
|
|
충분한 시간"이 주어지면 결국 한 사이클을 완료한다는 성질을 이용하면
|
|
간접적으로 관찰 가능함 — 죽었어야 할 객체를 weak-value 테이블(canary)에
|
|
넣어두고 그게 사라지는 시점을 기다리면 됨. 2026-08-13 사용자가 gcconn
|
|
트릭 검증 중 직접 확인(`audit/gcconn-trick-verification.md` 참고).
|
|
|
|
주의:
|
|
- 정확한 트리거가 아니라 **간접 관찰**임 — "이 시점에 정확히 GC가
|
|
끝났다"를 보장하지 않음, "이 루프가 끝났다면 적어도 GC 사이클 한 번은
|
|
지나갔다" 정도의 신호로만 쓸 것.
|
|
- `task.wait`가 필요해서 Roblox 런타임(Studio/게임) 전용 — 순수 `luau`
|
|
CLI엔 `task` 라이브러리가 없음(그쪽은 그냥 `collectgarbage()`를 직접
|
|
부르면 됨, `07` 참고).
|
|
- 실행 시간이 김(관찰 대상 크기/환경에 따라 GC 사이클 하나당 수 초~
|
|
수십 초) — 다른 Studio 스파이크(`10` 등)에서 GC 완료를 기다려야 할
|
|
때 아래 `waitForGC`를 그대로 복붙해서 쓰면 됨.
|
|
|
|
사용 예:
|
|
local weak = setmetatable({}, {__mode = "v"})
|
|
weak[1] = someValueExpectedToDie
|
|
-- ... someValueExpectedToDie에 대한 다른 참조를 전부 없앤 뒤 ...
|
|
waitForGC("someValue 해제 대기")
|
|
assert(weak[1] == nil, "여전히 살아있음 — GC 안 됐거나 다른 곳에서 참조 중")
|
|
]]
|
|
|
|
local function waitForGC(label: string?)
|
|
print(`[GC] {label or "GC"} 대기 시작`)
|
|
local canary = setmetatable({ {} }, { __mode = "v" }) -- 이 canary 하나만 참조하는 빈 테이블
|
|
local epoch = 0
|
|
while canary[1] do
|
|
task.wait(0.1)
|
|
table.create(5000, true) -- 할당 압력 생성 — incremental GC 진행을 강제
|
|
epoch += 1
|
|
if epoch % 100 == 0 then
|
|
print(`[GC] {label or "GC"} 대기 중: {epoch}`)
|
|
end
|
|
end
|
|
print(`[GC] {label or "GC"} 완료로 추정(epoch ~{epoch})`)
|
|
end
|