공유 소유권은 거의 감지되지 않습니다
이 답변은 약간 접하지 않을 수도 있지만 소유권 을 공유 하기 위해 사용자 엔드 관점에서 얼마나 많은 경우가 합리적 입니까? 적어도 내가 일한 도메인에는 실제로 아무것도 없었습니다 . 그렇지 않으면 사용자가 한 곳에서 한 번만 무언가를 제거 할 필요는 없지만 리소스가 실제로되기 전에 모든 관련 소유자로부터 명시 적으로 제거해야 함을 의미합니다 시스템에서 제거되었습니다.
다른 스레드처럼 다른 리소스가 여전히 리소스에 액세스하는 동안 리소스가 손상되는 것을 방지하기 위해 종종 저수준 엔지니어링 아이디어입니다. 종종 사용자가 소프트웨어에서 무언가를 닫거나 제거 / 삭제하도록 요청하는 경우 가능한 빨리 제거해야합니다 (제거하기에 안전 할 때마다). 응용 프로그램이 실행 중입니다.
예를 들어, 비디오 게임의 게임 자산은 재료 라이브러리의 재료를 참조 할 수 있습니다. 예를 들어, 한 스레드에서 재료 라이브러리에서 재료를 제거하고 다른 스레드가 여전히 게임 자산에서 참조하는 재료에 액세스하는 경우 매달려 포인터 충돌이 발생하지 않도록해야합니다. 그러나 이것이 게임 자산이 자신이 참조하는 재질의 소유권 을 재질 라이브러리와 공유 하는 것이 의미가있는 것은 아닙니다 . 우리는 사용자가 자산 및 재료 라이브러리에서 재료를 명시 적으로 제거하도록 강요하지 않습니다. 다른 스레드가 재료에 액세스 할 때까지 재료의 유일한 현명한 소유자 인 재료 라이브러리에서 재료를 제거하지 않기를 원합니다.
자원 유출
그러나 저는 소프트웨어의 모든 구성 요소에 대해 GC를 채택한 전 팀과 함께 작업했습니다. 다른 스레드가 여전히 리소스에 액세스하는 동안 리소스가 파괴되지 않도록하는 데 실제로 도움이되었지만 결국 리소스 누출에 대한 부분을 얻었습니다 .
그리고 이것은 1 시간 동안 세션을 수행 한 후 킬로바이트의 메모리 누수와 같이 개발자 만 화나게하는 사소한 리소스 누출이 아닙니다. 이것은 활동적인 세션에서 종종 기가 바이트의 메모리로 인해 서사시 유출이 발생하여 버그보고를 초래했습니다. 이제 자원의 소유권이 시스템의 8 개의 다른 부분들 사이에서 참조되고 따라서 소유권에서 공유 될 때, 자원의 제거를 요청하는 사용자에 대한 응답으로 자원을 제거하는 데 실패하는 데 단 하나의 시간이 소요되기 때문에 누출 될 가능성이 있으며 무한정 가능합니다.
그래서 나는 누설 소프트웨어를 만드는 것이 얼마나 쉬운 지에 따라 광범위한 규모로 적용되는 GC 또는 레퍼런스 카운팅의 열렬한 팬이 아니 었습니다. 이전에는 감지하기 쉬운 매달린 포인터 충돌이 있었지만 감지하기 어려운 리소스 누수가되어 테스트 레이더에서 쉽게 날 수 있습니다.
언어 / 라이브러리에서 이러한 참조를 제공하는 경우 약한 참조가이 문제를 완화 할 수 있지만 혼합 기술 집합의 개발자 팀이 필요할 때마다 약한 참조를 일관되게 사용할 수 없게 만드는 것이 어렵습니다. 이 어려움은 내부 팀뿐만 아니라 소프트웨어의 모든 단일 플러그인 개발자와 관련이있었습니다. 그것들은 또한 범인으로 플러그인을 추적하는 것을 어렵게하는 방식으로 객체에 대한 지속적인 참조를 저장함으로써 시스템이 쉽게 리소스를 유출하게 할 수 있습니다. 소스 코드가 우리의 통제 범위를 벗어난 플러그인이 고가의 리소스에 대한 참조를 공개하지 못했기 때문에 단순히 유출됩니다.
솔루션 : 지연된 주기적 제거
그래서 나중에 두 가지 세계에서 내가 찾은 최고를 제공하는 개인 프로젝트에 적용한 솔루션은 referencing=ownership
여전히 자원 파괴를 지연 시키는 개념을 제거하는 것이 었습니다 .
결과적으로, 이제 사용자가 자원을 제거해야하는 작업을 수행 할 때마다 API는 자원을 제거한다는 관점에서 표현됩니다.
ecs->remove(component);
... 사용자 엔드 로직을 매우 간단하게 모델링합니다. 그러나 처리 단계에 동일한 구성 요소에 동시에 액세스 할 수있는 다른 시스템 스레드가있는 경우 자원 (구성 요소)을 즉시 제거 할 수 없습니다.
따라서 이러한 처리 스레드는 여기저기서 시간을 생성하므로 가비지 수집기와 유사한 스레드가 깨어나 " 세계를 중지 "하고 해당 구성 요소 처리가 완료 될 때까지 스레드를 잠그는 동안 제거 요청 된 모든 리소스를 제거 할 수 있습니다. . 여기서 수행해야 할 작업의 양이 일반적으로 최소화되고 프레임 속도로 눈에 띄게 줄어들지 않도록 이것을 조정했습니다.
이제 이것이 시도되고 테스트되고 잘 문서화 된 방법이라고 말할 수는 없지만 두통이없고 리소스 누수가없는 몇 년 동안 내가 사용해온 것입니다. 아키텍처가 GC 또는 참조 횟수보다 훨씬 덜 무겁고 테스트 레이더에서 이러한 유형의 리소스 누수가 발생할 위험이 없으므로 이러한 종류의 동시성 모델에 적합 할 수있을 때 이와 같은 접근 방식을 탐색하는 것이 좋습니다.
Ref-Counting 또는 GC가 유용한 것으로 밝혀진 곳은 지속적인 데이터 구조입니다. 이 경우 데이터 구조 영역은 사용자와 관련된 문제와는 거리가 멀고 각 변경 불가능한 사본이 수정되지 않은 동일한 데이터의 소유권을 잠재적으로 공유하는 것이 실제로 의미가 있습니다.