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/021-field-connections.md | 89 ++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/research/021-field-connections.md (limited to 'docs/research/021-field-connections.md') diff --git a/docs/research/021-field-connections.md b/docs/research/021-field-connections.md new file mode 100644 index 0000000..ad1e98e --- /dev/null +++ b/docs/research/021-field-connections.md @@ -0,0 +1,89 @@ +# 021 — 필드와 입력 값으로 정하는 저장·응답 + +2026-09-23. **바이트 위치를 연산마다 직접 쓰지 않고, 필드 이름과 실제 입력 값으로 저장할 +내용을 정할 수 있게 했다.** 문서·선택 시작·길이를 받아 선택한 내용만 저장하고 응답하는 +네이티브 경로를 구현했다. 한글·이모지가 있는 UTF-8 파일을 예제 클라이언트에서 선택하고 +다시 조회해 같은 바이트가 남는 것을 확인했다. + +이 단계는 작성 표현과 실제 계산·저장·소비를 연결한 기능 결과다. 범용 타입 시스템이나 +새 직렬화 표준을 확정한 것이 아니며 성능 우위도 주장하지 않는다. + +## 사용자가 작성하는 관계 + +[selection.pure](../../prototypes/connections/examples/selection.pure)는 경계의 필드를 선언한다. + +```text +layout Selection { + start: u32le; + count: u32le; + document: bytes; +} + +on put { + let input = view(Selection, request.body); + let selected = range(input.document, input.start, input.count); + let saved = store.write(request.key, request.revision, selected); + reply(saved, selected); +} +``` + +`layout`은 이 입력 경계의 배치다. 선언 순서와 타입 폭으로 접근 위치를 정하며, RAM 전체나 +저장소를 같은 레코드로 강제하지 않는다. 이 예제의 저장 본문은 선택한 원본 문서 바이트이고 +입력의 start·count 필드는 저장되지 않는다. 기존 전체 바이트 저장 경로에는 layout도 필요 없다. + +이름·타입·별칭은 서버 시작 때 해소한다. 요청에서는 두 u32 값을 정렬되지 않은 위치에서도 +little-endian으로 읽고, 범위를 검사한 뒤 원본의 해당 구간을 참조한다. 레코드 객체·필드 사전· +선택 본문 사본을 추가하지 않는다. 저장과 응답은 같은 계산 결과를 쓰며 응답 완료까지 원본을 유지한다. + +실제 사용은 [Python 예제 클라이언트](../../prototypes/connections/examples/select-text.py)가 +UTF-8 텍스트 파일과 문자 위치를 받아 요청한다. 클라이언트는 Unicode 코드 포인트 위치를 +바이트 위치로 바꾼다. 서버의 bytes 연산 자체는 UTF-8이나 사용자에게 보이는 글자 덩어리를 +검증하지 않는다. [실행 방법](../../prototypes/connections/README.md). + +## 준비할 수 있는 것과 실행해야 하는 것 + +상수 구간은 기존처럼 합친다. 필드의 실제 값에 의존하는 구간만 준비된 범위 연산 목록에 +남긴다. 예제는 한 단계이며 그 결과에 별칭을 더 붙여도 단계 수는 늘지 않는다. +동적 구간의 하위 구간도 표현할 수 있다. 사용하지 않는 동적 구간의 실패도 관찰 가능한 +동작으로 유지하고, 모든 입력 검사가 성공한 뒤에만 쓰기를 호출한다. + +GET에서는 이름 기반 고정 필드와 가변 꼬리 구간을 선택한다. 꼬리의 길이는 같은 파일 버전의 +전체 크기에서 구하므로 본문 전체를 별도 배열로 읽지 않는다. GET의 숫자 필드 값에 의존하는 +범위는 현재 거절한다. 필요한 숫자와 선택 본문을 같은 버전에서 읽는 계획을 구현하지 않고 +전체 매핑으로 대체하지 않았다. + +지원 타입은 u32le·고정 bytes[N]·마지막 가변 bytes다. 선언은 최대 4개, 필드는 선언당 16개, +입력 값에 의존하는 범위는 8단계다. 버전 식별·마이그레이션·일반 산술·중첩 배치·여러 가변 +필드를 지원하는 최종 애플리케이션 데이터 모델은 아직 아니다. 송수신자가 배치에 합의해야 한다. + +## 비용과 검증 + +Linux AArch64에서 일반 빌드와 ASan·UBSan 빌드가 통과했다. + +- 기존 22개 통합 시나리오에 실제 문서 선택, 잘린 입력·동적 범위, 필드 순서·정렬 변경, + 사용되지 않은 계산의 오류, 저장된 가변 꼬리 조회, 부분 전송 수명을 추가해 28개를 확인했다. +- 선언 순서를 바꾸면 실제 숫자 접근 위치도 달라진다. 고정된 헤더 위치를 서버에 숨겨 넣은 것이 아니다. +- 정렬되지 않은 u32, 여러 바이트에 걸친 수, 최대 u32, 빈 구간·끝 위치·범위 초과를 검사했다. +- 오류가 나면 기존 내용·revision을 유지한다. 느린 응답에서는 선택 본문 길이만 계상하는 대신 + 보유 중인 원본 수신 할당 전체를 계상하고, 완료 뒤 반납한다. + +이 기능에는 비용이 추가됐다. 준비 구조체는 프로그램당 **112 B에서 648 B로 증가**했다. +최대 8개의 동적 범위 계획도 고정 예약하는 현재 구현의 크기이며 전체 RSS·컴파일러 크기가 아니다. +요청 계산에는 고정된 임시 span 배열을 쓰고 이 기능 때문에 힙 객체를 만들지는 않는다. +기존 수신 할당·파일 쓰기·페이지 매핑·커널 복사·클라이언트 인코딩 비용은 남는다. +따라서 이번 결과를 전체 메모리 절감이나 처리량 개선으로 해석하지 않는다. + +[원자료·소스 사본](../../prototypes/connections/results/2026-09-23-field-connections/README.md), +[필드와 범위 준비·계산](../../prototypes/connections/program.c), +[계약](../design/005-field-connections.md). + +macOS 실행, 전원 장애, 대규모 서비스, 네이티브 UI, 현재 숫자/화면 DSL과의 언어 통합은 +검증 범위 밖이다. 저장 효과는 여전히 요청당 하나이고 파일 작업은 동기식이다. + +## 다음 결정 + +현재 입력 값과 소비자를 연결했지만, 저장된 값의 조회·변경·다시 저장은 한 요청에서 작성할 +수 없다. 다음은 **실제 앱의 읽기·변경·저장 경로에서 연산과 버전 관계를 연결하는 것**이다. +읽은 버전과 조건부 쓰기의 관계, 서로 다른 생산자가 제공하는 값의 수명을 먼저 정한다. +숫자 타입·문법을 늘리기보다 기존 실행 코어에서 재사용할 연산과 필요한 외부 효과 경계를 +구체적인 작업에서 결정한다. 이번 문서 선택 데모의 크기를 키운 반복 측정은 하지 않는다. -- cgit v1.2.3