diff options
| author | eunhhu <[email protected]> | 2026-09-24 17:14:54 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-09-24 17:14:54 +0100 |
| commit | b1ce1927022d374198441afafeb27199fc8a052a (patch) | |
| tree | 6021f175f4c67ed03b44240eaa2f90d846f12f6f /docs/design/007-execution-domains.md | |
| parent | d34f9426d5317a1948f12f229439946728bc342a (diff) | |
| download | pure-b1ce1927022d374198441afafeb27199fc8a052a.tar.gz pure-b1ce1927022d374198441afafeb27199fc8a052a.zip | |
Establish native micro runtime checkpoint
Diffstat (limited to 'docs/design/007-execution-domains.md')
| -rw-r--r-- | docs/design/007-execution-domains.md | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/docs/design/007-execution-domains.md b/docs/design/007-execution-domains.md new file mode 100644 index 0000000..01edb88 --- /dev/null +++ b/docs/design/007-execution-domains.md @@ -0,0 +1,222 @@ +# 작은 OS로 설계하는 마이크로 런타임과 실행 영역 + +작성일: 2026-09-23. 상태: 설계 방향. [022](../research/022-execution-core.md)에서 저장 프로필의 +영역별 작업 접수·완료·대여·회수를 구현했다. 작은 OS의 통합 코어·범용 실행·샌드박스는 아직 미완료다. + +## 마이크로 런타임의 크기 제약 + +**작은 OS라는 책임 범위와 마이크로 런타임이라는 크기 제약을 함께 지킨다.** +아래 기능 목록을 항상 포함되는 커널·서비스 목록으로 해석하지 않는다. + +- 공통 코어는 실제 작업에 필요한 실행 진행, 소유권·자원 한도, 접근 권한과 완료·회수 규칙에 + 한정한다. 사용하지 않는 기능을 위한 범용 객체·관리 계층을 미리 만들지 않는다. +- 네트워크 프로토콜·저장 구현·UI·미디어·호환 기능은 앱에 필요한 구성을 선택해 결합한다. + 초기 방식은 빌드 시 선택이며 동적 로더·플러그인 레지스트리를 기본 의존성으로 추가하지 않는다. + 기능 지원을 그 코드·상태·백그라운드 작업의 상시 포함으로 구현하지 않는다. +- 영역마다 전용 스레드·스택·소켓·큰 큐를 예약하지 않는다. 공유 가능한 준비 코드·연결은 공유하고 + 상태·대기 공간은 실제 수요와 명시적인 한도에 맞춘다. 유휴 풀의 보유 공간도 비용이다. +- 파서·컴파일러·작성 도구를 실행 전용 구성의 필수 의존성으로 만들지 않는다. 준비된 실행에 + 필요 없는 소스·AST·필드 이름표를 계속 보관하지 않는다. 특수화에 따른 코드 증가도 비용에 넣는다. + +코어의 코드·정적 데이터, 선택한 의존성을 포함한 배포 구성, 유휴 메모리, 영역·진행 작업별 +추가 비용을 구분한다. 실제 앱의 전체 피크와 외부 버퍼도 확인한다. 작은 코어 옆의 라이브러리나 +호스트로 비용을 옮긴 것으로 축소를 주장하지 않는다. 모듈을 분리했다는 사실만으로 미사용 +코드·상태가 빠졌다고 보지 않고 선택한 빌드와 실행에서 확인한다. + +새 코어 기능에는 현재 작업이 요구하는 이유와 더 작은 구현 가능성을 제시한다. 다음 구현의 +전후 크기·메모리 차이를 확인하고 설명되지 않는 증가가 있으면 범위를 줄인다. 수치 상한은 +실행 전용 코어·선택 구성·대상 기기별로 근거를 갖고 정하며 임의의 KiB 숫자를 달성치로 쓰지 않는다. +필수 권한·정확성·보안 계약을 제거해 작게 만들지 않는다. + +현재 저장 프로필은 `make core`로 파서·저장·HTTP 없는 아카이브만 빌드한다. release의 +`make check-core`가 코드 섹션·구조체 상한, 아카이브 구성과 외부 의존성을 검사한다. +상한 변경은 필요한 기능·더 작은 배치·전체 비용의 검토를 함께 기록한다. 현재 수치와 +선택 실행물의 비용 범위는 [023](../research/023-document-edits.md)에 있다. 이 제한된 코어의 +크기를 전체 앱·모든 플랫폼의 메모리 크기로 인용하지 않는다. + +## Pure가 소유하는 운영 모델 + +**Pure 런타임 자체를 하나의 작은 OS로 설계한다.** 실행·메모리·보호·자원 수명·저장·통신의 +의미와 정책을 Pure가 소유하고, 앱은 그 모델 위에서 동작한다. UI는 이 기반의 한 하위 체계다. +OS 프로세스는 현재 호스트에서 구동할 때 받는 실행·보호·자원 제약이며 Pure의 기본 개념이 아니다. +앞선 설명처럼 프로세스 배치 관리에서 설계를 시작하지 않는다. + +현재 호스트는 CPU 실행 기회, 메모리, 시계, 저장·통신·장치 접근을 제공한다. +Pure는 제공받은 범위 안에서 어떤 작업을 실행하고, 누구에게 자원을 할당하며, 어떤 연결과 +효과를 허용하고, 언제 회수할지 결정한다. 호스트의 PID·스레드·파일 디스크립터·소켓을 +앱의 정체성이나 공통 실행 계약으로 노출하지 않는다. 기존 네이티브 도구의 FFI는 별도 경계다. + +| Pure가 정의할 정책·의미 | 플랫폼 연결부가 제공할 수단·제약 | +|---|---| +| 실행 가능한 작업과 스케줄링, 기한·중단 계약 | 실행 기회, 깨우기·대기·시계, 사용 가능한 중단 수단 | +| 메모리 배치·소유권·대여·할당·회수와 예산 | 메모리 확보·반환·매핑·보호의 가용 기능과 실패 | +| 앱·자원 식별, 접근 권한과 실행 보호 | 해당 환경이 집행할 수 있는 보호 기능과 한계 | +| 내부 연결, 원격 호출과 완료·실패 의미 | 바이트·패킷 전달 수단과 실제 입출력 완료 | +| 저장 배치·공개·내구성·복구 계약 | 파일·블록 등 저장 수단, 동기화 결과와 장애 | +| UI 입력·배치·표시의 일관된 의미 | 창·입력·접근성·그래픽 등 환경 기능 | + +이 표는 새 중간 객체를 매번 만드는 API를 요구하지 않는다. 준비된 연결에서 계약을 보존하며 +불필요한 경계를 제거한다. 플랫폼이 어떤 계약을 집행하지 못하면 지원 범위로 명시한다. +호스트 밖의 메모리·CPU를 통제하거나 호스트 종료를 막는다고 주장하지 않는다. + +개발은 기존 OS에서 구동하는 형태로 시작한다. 직접 하드웨어를 구동하는 경로에서도 +Pure의 앱·실행 모델을 유지할 수 있도록 경계를 정하되, 드라이버·부팅 구현을 지금 완료한 +것으로 취급하지 않는다. 작은 OS라는 목표를 단순한 이름 변경이나 향후 부가 기능으로 미루지 않는다. + +## 외부 통신은 핵심 기능이다 + +Pure 외부와의 연결도 운영 모델의 일부다. Pure를 사용하지 않는 서비스·런타임·프로그램과 +요청을 보내고 받을 수 있어야 한다. 작은 OS라는 설계 방향을 폐쇄된 통신 환경으로 해석하지 않는다. + +- Pure 내부 연결은 준비된 연산·데이터 관계를 사용한다. +- Pure 간 원격 연결은 자체 형식과 보안 전송을 사용할 수 있다. +- 외부 서비스와의 연결은 상대가 사용하는 프로토콜·형식·인증·완료 의미를 지원한다. + HTTP(S), 기존 RPC, TCP/UDP 기반 프로토콜과 로컬 IPC 등 필요한 접점을 양방향으로 제공한다. + +이는 지원 목표이며 위 프로토콜들을 모두 구현했다는 목록이 아니다. 자체 형식도 상대가 +그 계약을 구현하면 Pure 외부에서 사용할 수 있어야 한다. 외부 프로그램의 내부 구조까지 +Pure 실행 영역으로 옮기거나 모든 상대에게 Pure 전용 프로토콜을 강제하지 않는다. + +외부 형식은 필요에 따라 검증·변환하되, 내부 데이터를 항상 외부 형식으로 보관하지 않는다. +그대로 소비할 수 있는 데이터에 불필요한 변환을 추가하지 않는다. 변환·암호화·대기·복사 비용은 +전체 경로에 포함하고, 해당 프로토콜의 주소·메서드·오류 등 앱에 필요한 의미는 접점에서 제공한다. +호환성을 이유로 그 개념을 모든 Pure 내부 연결의 필수 모델로 올리지는 않는다. + +## 기본 단위 + +**실행 영역**은 Pure 내부에서 상태·권한·수명을 귀속시키는 단위다. +기존 [메모리 계약](002-memory-lifetime.md)의 영역을 작은 OS의 운영 모델 안에서 구체화한다. +영역을 OS 프로세스의 대체 이름이나 컨테이너의 포장으로 정의하지 않는다. +VM 명령 집합의 채택 여부는 이 관리 단위를 정의하는 결정과 별개다. + +영역은 앱이 독립적으로 관리해야 하는 상태·권한·수명의 경계에 만든다. +함수·그래프 노드·요청마다 영역이나 메일박스를 하나씩 만들지 않는다. +첫 후보는 영역의 관리 상태를 한 제어 흐름이 변경하고, 독립 작업의 완료를 그 흐름에서 회수하는 방식이다. +영역마다 전용 OS 스레드·스택·소켓·이벤트 루프를 예약할 필요는 없다. +변경하지 않는 준비 프로그램은 공유하고, 인스턴스 상태와 사용 중인 작업만 개별 보유한다. + +| 영역이 관리할 것 | 의미 | +|---|---| +| 실행 식별자와 세대 | 재시작한 인스턴스에 이전 요청·완료가 섞이지 않음 | +| 프로그램과 상태 | 준비된 연산·연결, 영역이 소유한 변경 가능한 상태 | +| 자원 예산 | 보유 메모리, 진행·대기·완료 요청과 외부 자원의 귀속·한도 | +| 허용된 연결과 효과 | 호출 가능한 입력, 저장·파일·네트워크 등 접근 범위 | +| 실행·종료 상태 | 새 작업 접수, 진행 작업 배출, 취소 요청, 실제 접근 종료와 회수 | + +pod·VM은 사용자가 설명한 관리 경험의 비유이며 Pure의 내부 구조를 고정하는 명칭이 아니다. +묶음 수명과 보호 강도는 Pure의 요구에서 정한다. 영역마다 별도의 OS 이미지나 가상 장치를 +필수로 넣지 않는다. + +## 연결은 자원의 접근·공유 조건에서 준비한다 + +앱은 허용된 입력과 출력의 관계를 작성한다. 연결을 준비할 때 대상의 형식·권한·수명과 +배치를 확인하고 실행 경로를 정한다. 모든 호출을 범용 객체·직렬화·소켓으로 보내지 않는다. +경로를 선택해도 격리 정책과 관찰 가능한 실행 순서를 우회하지 않는다. + +| 가용 자원과 보호 조건 | 가능한 경로 | 남는 책임 | +|---|---|---| +| 데이터를 함께 접근할 수 있고 실행 순서를 바로 연결 가능 | 준비된 직접 호출·읽기 대여·소유권 이전 | 권한, 원본 수명, 접수 예산, 재진입·효과 순서 | +| 데이터를 공유할 수 있으나 실행 흐름이 독립적 | 제한된 작업 큐와 데이터 참조 전달 | 동기화·공개 순서, 대여 유지, 완료 회수 | +| 보호 경계가 직접 접근을 제한 | 허용된 공유 매핑 또는 바이트 전달 | 공유 영역의 권한·수명·동기화·검증, 종료 후 회수 | +| 메모리를 공유할 수 없는 원격 상대 | 자체 경계 형식과 보안 전송 | 인코딩, 흐름 제어, 기한, 응답 유실과 결과 불명 | + +현재 호스트 연결부에서는 위 조건을 스레드·메모리 매핑·IPC·소켓 등으로 구현할 수 있다. +이 구현 분류를 Pure 코어의 필수 프로세스·소켓 계층으로 올리지 않는다. + +같은 프로세스라도 격리된 샌드박스 사이에서는 임의 포인터 대여를 허용하지 않는다. +같은 기기라도 공유 메모리를 항상 사용하는 것으로 확정하지 않는다. 공유·매핑의 관리 비용과 +격리 요구에 따라 복사나 IPC가 더 적절할 수 있다. 서로 다른 프로세스에는 포인터를 전송하지 않는다. + +버퍼 핸들은 기존 계약처럼 발급 영역 안에서 유효하다. 영역 간 대여는 수신 영역에서 +검사할 수 있는 접근 권한과 대여 기록으로 연결하며, 발급 영역의 핸들 숫자만 복사하지 않는다. +물리 버퍼는 한 번만 계상하되, 각 소비자가 얼마나 오래 회수를 막는지도 기록한다. + +## 같은 호출 계약과 다른 실패 조건 + +접수, 결과, 완료, 취소, 기한의 의미는 [연산 계약](001-operation-semantics.md)과 +[모듈 계약](003-module-contract.md)을 따른다. 로컬 호출이 즉시 끝나더라도 제출 도중 앱에 +예상치 못한 재진입을 만들지 않는다. 관찰 가능한 순서·권한·예산을 보존할 수 있을 때 +내부 호출이나 완료 처리를 합칠 수 있으며 모든 경계마다 큐를 강제하지 않는다. + +원격 호출을 로컬 함수와 똑같이 성공·실패한다고 보이게 만들지는 않는다. +요청이 접수되기 전 거절과, 효과 실행 후 응답을 받지 못한 결과 불명은 구분한다. +취소는 이미 발생한 저장 효과를 되돌리지 않는다. 재연결 시 자동 재실행도 기본으로 가정하지 않는다. +같은 입력을 로컬·원격에 배치하려면 앱이 요구하는 순서·내구성·오류·공유 조건을 양쪽에서 +충족해야 한다. 충족하지 못하는 배치는 거절하거나 명시적으로 다른 계약을 선택한다. + +준비된 연결은 대상의 실행 세대와 결부한다. 대상이 재시작하면 이전 연결을 무효화하고 +형식·권한을 다시 확인한다. 늦은 완료로 새 인스턴스의 상태·버퍼를 변경하지 않는다. +이전 작업이 이미 실행됐을 가능성이 있으면 새 인스턴스에 조용히 재전달하지 않는다. +네트워크의 인증된 상대 식별과 영역 내부의 슬롯·세대는 별개이며 세대 번호 자체는 인증 수단이 아니다. + +## 자원 관리와 강제 격리 + +첫 단계의 신뢰하는 네이티브 코드 사이에서 가능한 것은 관리 계약에 따른 상태·자원 분리다. +현재 C 코드에 영역 구조체를 추가하는 것으로 임의 메모리 접근이나 프로세스 크래시를 +격리했다고 주장할 수 없다. 프로세스를 공유하면 OS 수준의 종료·주소 공간 장애도 공유한다. + +불신 코드에 필요한 격리 강도는 배치의 입력 조건으로 둔다. 후보는 제한된 실행 형식의 +검증·메모리 접근 제어, Wasm 같은 샌드박스, 별도 OS 프로세스 또는 VM 경계다. +메모리 안전한 실행 형식도 네이티브 확장·호스트 호출의 권한과 안전성을 자동 보장하지 않는다. +예를 들어 Wasmtime은 인스턴스 메모리 격리를 제공하고 호스트 API의 안전성도 별도로 다룬다. +이 문서는 Wasmtime 도입 결정이 아니다. [Wasmtime 보안 모델](https://docs.wasmtime.dev/security.html) + +메모리 예산에는 진행 작업뿐 아니라 완료 슬롯, 큐, 암호·재전송·외부 라이브러리의 보유 공간도 +포함하거나 미계측으로 명시한다. 같은 물리 공간의 중복 합산과 외부로 비용을 숨기는 일을 피한다. +공유 코드·스케줄러·유휴 풀은 런타임 공통 비용으로 따로 보고한다. + +CPU 시간의 강제 제한에는 중단 가능한 실행이나 OS의 집행 수단이 필요하다. +협력적 스케줄러의 실행 예산만으로 멈추지 않는 네이티브 함수나 동기 파일 호출을 제어할 수는 없다. +현재 서버의 동기 저장 호출은 이벤트 루프를 막을 수 있다. 영역을 나누는 것만으로 해결됐다고 세지 않는다. + +종료 요청은 새 접수를 막고 진행 작업·대여를 배출하는 단계다. 시간 초과만으로 참조 중인 +메모리를 재사용하지 않는다. 영역을 관리 목록에서 제외하더라도 남은 자원은 접근이 끝날 때까지 +명시적인 회수 책임과 예산 아래 둔다. 강제 종료·무중단 이동·복제는 별도 구현과 복구 계약이 필요하다. + +## BSD socket·Kitex 수준의 목표를 평가하는 방법 + +BSD socket은 통신 API이므로 단일 성능 수치를 뜻하지 않는다. 요구를 **같은 일을 하는 직접 +소켓 구현에 비해 런타임의 추가 비용을 작게 유지하고, 실제 RPC에서는 Kitex와 경쟁하는 것**으로 둔다. +그 수준에 도달했다는 결과는 아직 없다. + +Kitex는 Netpoll을 기본 전송 구현으로 사용하지만 다른 전송 구현도 연결할 수 있다. +연결 풀·프로토콜·실행 경로를 포함해 비교해야 한다. +[Kitex 전송 확장](https://www.cloudwego.io/docs/kitex/tutorials/framework-exten/transport/) + +현재 공식 문서는 긴 연결 풀을 기본으로 설명한다. `netpollmux`에 의존하는 +`WithMuxConnection` / `WithMuxTransport`는 유지보수 중단으로 deprecated 상태다. +이는 QUIC이나 gRPC를 포함한 모든 다중화가 불필요하다는 뜻이 아니다. +과거 벤치마크 숫자나 설정을 그대로 합격선으로 삼지 않는다. +[Kitex 연결 유형](https://www.cloudwego.io/docs/kitex/tutorials/basic-feature/connection_type/) + +비교는 실제 선택에 필요할 때만 수행한다. + +- 같은 주소 공간의 연결: 같은 작업·권한·수명·완료 조건을 가진 직접 구현에 비해 추가된 + 할당·큐·복사·스케줄링을 확인한다. 소켓을 생략한 결과를 네트워크 전송 성능으로 발표하지 않는다. +- 프로세스·기기 간 RPC: 성공 결과·형식·인증/암호화·연결 재사용·동시성·배치·내구성과 + 타임아웃·재시도 조건을 맞춘 직접 소켓 구현 및 유지보수되는 Kitex 구성과 비교한다. +- 기존 변경·저장 작업에서 지연 분포와 성공 처리량, 클라이언트·서버 CPU·전체 메모리, + 연결별 보유량을 확인한다. 큰 전달·느린 수신자·과부하가 작은 작업에 주는 영향도 포함한다. + +영역·핸들·바이너리 형식을 만들었다는 사실은 신규성이나 성능의 증명이 아니다. +연구 가설은 작성된 연결의 의미를 보존하면서 **배치에 불필요한 전송·복사·중간 보관을 +준비 단계에서 제거하고, 필요한 격리와 자원 관리는 유지할 수 있는가**다. + +## 다음 구현의 구체적 범위 + +[006](006-native-protocol.md)의 진입점 분리를 **Pure가 운영 정책을 소유하는 코어와 호스트 +수단의 분리**로 진행한다. 기존 선택·조건부 저장·응답 작업을 재사용해 실제 효과까지 연결한다. +기존 구현에서 필요한 책임만 분리하며, 사용처 없는 서비스 관리자·범용 모듈 체계를 먼저 만들지 않는다. +이번 경로에 필요한 코어 크기와 실행 비용을 기준으로 유지하고, 추가 기능의 비용은 선택 구성에 귀속시킨다. + +1. Pure가 요청 접수·진행 작업·완료·자원 회수를 소유하고, 호스트 연결부는 저장·전송·시계 등 + 실제 수단과 결과를 제공하도록 책임을 분리한다. PID·파일 디스크립터를 앱의 식별자로 삼지 않는다. +2. 영역별 프로그램·상태·예산·접근 권한을 이 코어에 귀속시킨다. 두 영역의 기존 작업을 + 내부 연결로 실행하고 외부 요청도 같은 앱 의미로 접수한다. 사용자에게 수명 관리를 떠넘기지 않는다. +3. 한 영역의 포화·정상 종료·재생성과 이전 완료 처리에서 다른 영역의 관리 상태를 보존하고, + 호스트의 자원 부족·입출력 실패가 Pure 결과로 정확히 전달되는지 확인한다. +4. 호스트에서 집행할 수 있는 격리와 보안 원격 경로를 확장한다. 각 기능의 검증 범위와 + 호스트 제약을 기록하며 관리 상태 분리를 네이티브 크래시 격리로 해석하지 않는다. + +첫 구현에 클러스터 스케줄러, 게스트 OS, 범용 바이트코드 VM, 자동 복제·라이브 이동을 추가하지 않는다. +고정 바이트 예산과 처리량 목표는 대상 작업·기기·보장을 확정한 뒤 결정한다. |
