Rust에서 Arc 다운캐스팅을 갈망하며

6 days ago 10

동시성 캐시의 큰 값을 매번 복제하는 대신 Arc 를 사용하면, 전체 데이터를 복제하지 않고 읽기 접근이 가능한 소유 값을 저렴하게 복제할 수 있음 하지만 Arc<JSON> 내부의 String 을 패턴 매칭으로 꺼내 Arc<String>으로 반환할 수는 없음. 원본 소유권을 유지하면서 내부 값에 접근하는 별도 타입이 필요함 소유 값과 내부 참조를 묶고 참조 수명을 강제로 늘리는 방식은 값 이동으로 주소가 바뀌는 문제가 있음. Deref로만 접근을 제한해도 이 문제는 해결되지 않음 PinRef<V, T> 는 Pin<Arc<MustPin<V>>>와 내부 포인터를 함께 보관하고, 참조 변환 함수를 이용해 원본 데이터를 복제하지 않는 투영(projection)을 구현함 구현에는 PhantomPinned와 고차 수명 제약이 중요하지만, 안전성이 확정된 것은 아님. 전체 코드는 공개됐으나 놓친 정의되지 않은 동작(UB) 이 남아 있을 가능성이 있음 동시성 캐시에서 전체 값 복제가 비싸지는 문제 빌드 드라이버를 개발하는 과정에서 캐시 값 복제 비용이 문제가 됨 초기 캐시 예제는 HTTP 클라이언트와 RWLock<HashMap<String, JSON>>을 사용함 JSON은 F64, String, Vec, Object 변형을 가진 열거형임 캐시 적중 시 읽기 잠금 안에서 값을 복제해 반환함 캐시 미적중 시 HTTP 요청 결과를 얻고, 쓰기 잠금 안에서 복제본을 캐시에 넣은 뒤 원래 값을 반환함 두 경로 모두 호출당 .clone() 한 번이 필요함. 값이 크거나 트리 형태여서 복제가 비싸면 이 비용이 캐시의 절감 효과를 압도할 수 있으며, 실제 개발 코드에서도 이런 문제가 발생함 예제에는 복제 외에도 과도한 문자열 기반 타입 사용, 오류 처리 부재, 동시 요청의 중복 작업 문제가 있음 동시 요청이 경쟁해 같은 작업을 반복하는 문제의 해결 코드는 데이터베이스 구현에서 확인할 수 있음 참조 반환 대신 Arc로 복제 비용 줄이기 읽기 전용 접근으로 충분하다면 공유 참조를 반환하고, 실제 소유권이 필요한 지점에서만 값을 복제하는 방식이 바람직함 하지만 get<'a, 'b>(&'a self, url: &'b str) -> &'a JSON 형태로 반환할 수는 없음 잠금으로 보호된 캐시의 내부 참조는 임시 잠금 가드를 ...

Read Entire Article