From b1ce1927022d374198441afafeb27199fc8a052a Mon Sep 17 00:00:00 2001 From: eunhhu Date: Thu, 24 Sep 2026 17:14:54 +0100 Subject: Establish native micro runtime checkpoint --- docs/research/024-native-app-instances.md | 109 ++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 docs/research/024-native-app-instances.md (limited to 'docs/research/024-native-app-instances.md') diff --git a/docs/research/024-native-app-instances.md b/docs/research/024-native-app-instances.md new file mode 100644 index 0000000..fee556d --- /dev/null +++ b/docs/research/024-native-app-instances.md @@ -0,0 +1,109 @@ +# 024 — 기존 작성물을 네이티브 앱 상태·저장 경로에 연결 + +2026-09-23. Linux AArch64, Zig 0.15.2 / GCC 14.2.0. +첫 공개 체크포인트 진행 중이다. 이번 실행 호스트는 터미널이며 네이티브 창은 아직 없다. + +## 바뀐 경계 + +기존 Workbench의 계산 실행기는 전역 `engine` 하나를 사용했다. Wasm 인스턴스마다 메모리가 +분리되는 브라우저에서는 여러 작성물을 실행할 수 있었지만, 같은 코드를 네이티브 라이브러리로 +붙이면 앱마다 독립된 상태를 제공하지 못했다. + +실제 계산을 `engine.zig`의 명시적인 `Engine` 인스턴스로 옮겼다. 기존 `core.zig`는 브라우저 +ABI와 회귀 검사를 유지하는 얇은 연결부다. 네이티브 `native.zig`는 호출자가 제공한 정렬된 +메모리에 인스턴스를 초기화하고 C 함수로 접근한다. 네이티브 모듈에는 기본 VM 인스턴스, +할당기, 파일·소켓·스레드가 없다. 실행 정의의 준비·실패·복원·평가 기록도 해당 인스턴스에 속한다. + +이 계산 모듈은 **앱이 선택하는 기존의 제한된 scalar 실행기**다. 모든 Pure 실행 영역에 +자동으로 포함하는 새 공통 VM이 아니다. 작업 접수·수명·대여·예산을 맡는 C 코어는 변경하지 않았다. + +## 작성에서 네이티브 실행까지 + +새 문법이나 별도 파서를 만들지 않았다. `native/prepare.mjs`가 기존 `compiler.mjs`로 `.pure`를 +준비하고 읽기 전용 C 데이터로 출력한다. 상태·입력 이름, 공유 규칙의 바인딩, 대상 라우팅, +표시 식이 그대로 들어간다. 문자열은 UTF-8 바이트의 C escape로 출력해 소스 문자열이 C 코드가 +되지 않게 한다. 이 데이터와 실행 모듈·호스트를 링크해 독립 실행 파일을 만든다. + +Node·Zig·C 컴파일러는 **빌드 도구**다. 만들어진 실행물은 Node·브라우저·Wasm 없이 구동한다. +실행 시 소스 파서나 AST를 보관하지 않는다. 다만 연산은 기존 준비 명령을 해석하며, 앱의 각 +연산을 기계어로 직접 생성하는 AOT 최적화 컴파일러를 구현한 것은 아니다. 현재 작성 변경은 +다시 빌드해서 반영한다. 실시간 소스 편집·교체는 아직 네이티브 호스트에 연결하지 않았다. + +## 하나의 실행 코어를 통과하는 앱 경로 + +`native/app.c`는 준비된 앱의 입력과 상태를 기존 C 실행 코어에 연결한다. + +```text +입력 → 코어의 접수·예산·작업 슬롯 → 선택한 계산 인스턴스 → 상태/표시 값 +상태 스냅샷 → 코어의 내부 결과 대여 → 조건부 바이트 저장 +저장된 바이트의 매핑 → 코어의 내부 결과 대여 → 검증 후 상태 복원 +``` + +저장과 복원은 기존 `pure_runtime_forward`를 사용한다. 전달을 위한 두 번째 본문 버퍼나 +소켓 직렬화를 추가하지 않는다. 단, **현재 상태를 스냅샷으로 만들 때는 복사한다.** 이후 입력이 +상태를 바꾸어도 저장할 내용이 달라지지 않도록 44 B의 헤더와 상태당 8 B를 별도 소유한다. +같은 데이터의 두 작업이 유지되는 동안 각 작업의 크레딧을 계산하므로 이를 물리 메모리로 합산하지 않는다. + +예제의 상태 25개는 스냅샷 244 B다. 버전 충돌은 상대 값을 덮어쓰지 않고 현재 앱 상태도 +바꾸지 않는다. 복원은 정의 식별자·상태 수·길이·유한한 값을 검사한 뒤 전체 정의와 값을 함께 +설치한다. 실패하면 기존 앱 상태와 채택한 저장 버전은 유지한다. 초기값과 현재 값은 별개라 +복원 후 `reset`은 작성된 초기값으로 돌아간다. + +정의 식별자는 빌드 도구가 만든 SHA-256이다. 의미만 같은 다른 소스나 위치 정보가 달라진 +정의를 자동으로 호환 처리하지 않으며, 정의가 다르면 복원을 거절한다. 이는 인증이나 서명이 +아니다. 현재 스냅샷은 브라우저 Workbench의 JSON 프로젝트 형식과 별개이며 변환기는 미구현이다. +수치 표현도 현재 IEEE binary64 경계에 한정한다. 모든 Pure 데이터를 이 배치로 강제하지 않는다. + +포인터는 입력 그룹이 아닌 실제 대상마다 소유자를 가진다. 같은 라우팅 입력의 두 대상을 +동시에 조작하고 하나만 취소할 수 있다. 다른 소유자의 이동·해제는 거절한다. 키 입력은 여러 +출처가 눌러도 첫 down과 마지막 up만 작성 규칙에 전달한다. 진행 중인 입력이 있으면 저장· +복원을 거절한다. 이벤트의 계산 실패는 상태 쓰기를 원자적으로 되돌리며 실제 입력 해제와 구분한다. +네이티브 명령 인터페이스의 오류 표현·무시 정책 전체가 브라우저 UI와 같다는 주장은 아니다. + +## micro 비용 + +일반 네이티브 라이브러리 설정은 기본 panic 보고·심볼 해석과 compiler-rt 아카이브를 포함했다. +이 선택 모듈에는 그 전체 기능이 필요하지 않았다. `ReleaseSafe`의 범위·오버플로 검사를 유지하고 +예상하지 못한 내부 불변식 위반은 trap으로 중단하도록 바꿨다. 정상적인 작성 오류는 기존 상태 +코드로 반환한다. 실패를 무시하거나 안전 검사를 꺼서 줄인 것은 아니다. 내부 버그 발생 시 +이 모듈이 자체 스택 추적을 출력하지 않는 비용 절충은 남으며, 네이티브 크래시 격리도 아니다. + +필요하지 않은 compiler-rt 전체를 포함하지 않은 뒤 실제 외부 심볼은 `memcpy`, `memset`뿐이다. +초기 아카이브 수치는 동결 자료에 보관했다. 링크 전 아카이브 합을 최종 실행물 크기 감소율로 +해석하지 않는다. + +| 범위 | 확인한 비용 | +|---|---:| +| 공통 C 실행 코어의 GNU `size text` | 5,932 B, 이전과 동일 | +| 선택한 scalar 라이브러리의 `size text` | 33,020 B | +| scalar 라이브러리의 data/BSS | 0 B / 0 B | +| 앱별 scalar 인스턴스 | 20,064 B, 정렬 8 B | +| 앱 컨트롤러 | 928 B, 실행 코어와 작업 슬롯 2개 포함 | +| 앱 입력 값 | 32 B | +| 상태 25개의 저장 스냅샷 | 244 B | +| 라우팅 예제 전체 CLI의 text/data/BSS 합 | 64,883 B | +| 같은 실행물의 심볼 제거 후 ELF 파일 | 68,000 B | + +계산 인스턴스의 20,064 B에는 최대 용량의 준비 정의·교체 작업 공간·상태·평가 기록이 들어간다. +읽기 전용 C 준비 데이터도 실행물에 존재한다. 현재 배열의 고정 예약과 정의 복사 비용을 +없앴다고 하지 않는다. 입력·스냅샷의 호스트 할당, 스택, libc·로더·커널·페이지·유휴/피크 RSS는 +위 구조체 수치와 별개다. 현재 ELF의 직접 동적 의존성은 `libc.so.6`이며 전체 의존 메모리 +비용을 측정한 결과가 아니다. 코어 크기 검사는 그대로 통과한다. + +## 실제로 확인한 범위 + +[동결된 근거](../../prototypes/workbench/results/2026-09-23-native-instances/)에 다음을 보관했다. + +- 기존 Zig 의미 검사 37개, 브라우저/Wasm 및 Node CLI 회귀 검사 87개 통과. +- 기존 카운터·토글·프레임 계산·드래그·공유 대상·숫자 입력과 빈 정의·계산 실패·문자열 경계 등 + 작성물 9개의 입력 156단계에서 네이티브와 Wasm의 상태·표시 값 일치. +- 각 네이티브 작성물을 저장한 뒤 새 프로세스에서 같은 정의로 복원해 값과 표시 식을 확인. +- 같은 프로세스의 인스턴스 3개에서 상태·준비 실패·평가 설정·입력 소유권·예산이 섞이지 않음을 확인. +- 실제 저장소의 버전 충돌, 다른 정의, 비유한 상태 복원 거절과 모든 작업·크레딧 회수 확인. +- 일반 C 호스트와 ASan/UBSan C 호스트에서 위 네이티브 경로 통과. Zig 오브젝트는 둘 다 + `ReleaseSafe`이며 ASan으로 계측된 Zig 빌드라고 주장하지 않는다. + +동시 소유 스레드 간 실행, 네이티브 창·IME·접근성·크기 변경, macOS 실사용은 이번 검증 범위에 없다. +기존 scalar 한도(상태 32, 입력 8, 표시 24, 명령 512)도 유지된다. 대규모 앱 전체를 이 한도에 +맞추라는 뜻이 아니라 이전 작성 모델을 실제 네이티브·저장 경로로 연결한 중간 구현이다. +전체 체크포인트의 일반 앱 표현·비동기 효과·보안 RPC·실제 화면·규모 검증은 계속 남아 있다. -- cgit v1.2.3