segview — 조각 뷰의 커서 · 총길이 · 펴기
언어가 든 조각 뷰 연산은 셋뿐이다 — view_segments(짓기), segs(조각 수), seg(i 번째 조각). 이 모듈은 그 위에 커서 · 총길이 · 펴기(coalesce) 를 얹는다. 셋 다 앞의 셋으로 쓰이므로 내장 연산이 될 이유가 없다.
왜 segments 가 언어에 있나. 조각 여럿을 한 값으로 들지 못하면 밖으로 내보낼 때 조각마다 한 번씩 나가야 한다. 64 KiB 를 64 조각으로 내보낼 때 그 차이가 개발 저장소의 측정에서 28 배였다(writev 한 번 대 write 64 번). 조각은 곧 iovec 이다 — 방출 C 의 슬라이스가 struct iovec 과 크기도 두 오프셋도 같아서, extern 경계에서 조각 배열을 넘기는 값은 캐스트이지 복사가 아니다(시험이 매번 대조한다).
rem 서술자는 평평한 slice u64 에 (at, n) 쌍 --- 새 구조체 타입은 없다
set (index d 0) 0 . set (index d 1) 4 .
set (index d 2) 8 . set (index d 3) 4 .
let ss be view_segments back d .
let n u64 be segview.total_len ss .
let w option u64 . be segview.coalesce ss out .| 부르는 것 | 무엇을 만지나 | 값 |
|---|---|---|
segs · seg(내장) | 서술자만 | 조각당 수 ns 이하, 복사 0 |
segview.total_len | 서술자만 | O(조각 수) |
segview.cursor · seek · byte_at | 서술자만 | O(조각 수) — 조각을 훑어 자리를 찾는다 |
segview.coalesce | 바이트 전부 | O(n) — 여기서만 복사가 일어난다 |
표 50.1 — 비용이 op 이름에 적혀 있다
그것이 설계의 요점이다 — 순회는 조각을 빌리기만 하고, 한 덩어리로 펴는 값은 부를 때만 치른다. 비용이 부르는 자리에 보인다.
알아 둘 것. 저장은 호출자 것이다 — coalesce 는 받은 버퍼에 쓰고 쓴 길이를 답하며, 버퍼가 모자라면 잘라 쓰지 않고 none 이다. 없는 자리를 가리키는 커서를 만들지 않는다 — seek 이 끝을 넘으면 none 이다.
이름 하나가 남의 모듈을 아프게 했다. 처음에 total_len 의 이름은 total 이었다. 그러자 라이브러리 짝 시험이 segview 와 tls13 · tlssrv 를 함께 쓸 때 깨지는 것을 잡았다 — tls13 안의 지역 변수 total 과 부딪혀 엉뚱한 진단(E-GUARD-FALLTHROUGH)이 났다. 흔한 낱말을 export 하지 않는다. (진단이 이름 충돌을 이름 충돌로 말하지 않은 것은 따로 남은 결함이다.)
짓지 않은 것 — 가변 원소 폭(segments T 의 T 는 오늘 스칼라 슬라이스다), coalesce 의 무복사 최적화, 읽기 쪽(readv) 짝.