문제

여러 스레드에서 액세스를 단순화하기 위해 Java로 불변 DOM 트리를 작성 중입니다.*

그러나 가능한 한 빨리 삽입 및 업데이트를 지원해야 합니다.그리고 이는 불변이기 때문에 트리의 N번째 수준에 있는 노드를 변경하는 경우 새 트리를 반환하려면 최소한 N개의 새 노드를 할당해야 합니다.

내 질문은 트리가 수정될 때마다 새 노드를 생성하는 것보다 노드를 사전 할당하는 것이 훨씬 더 빠를 것이라는 것입니다.사용하지 않는 수백 개의 노드 풀을 유지하고 수정 작업이 필요할 때마다 풀에서 하나를 생성하는 대신 풀에서 하나를 꺼내면 매우 쉽습니다.다른 일이 없을 때 노드 풀을 보충할 수 있습니다.(명확하지 않은 경우 이 애플리케이션에서는 실행 시간이 힙 공간보다 훨씬 더 중요할 것입니다.)

이것을 할 가치가 있습니까?속도를 높이는 다른 팁은 없나요?

또는 불변 DOM 라이브러리가 이미 있는지 아는 사람이 있습니까?검색했지만 아무것도 찾을 수 없었습니다.

*메모:불변성 개념에 익숙하지 않은 분들을 위해 설명하자면, 이는 기본적으로 객체를 변경하는 객체에 대한 모든 작업에서 메서드가 변경된 객체가 아닌 변경 사항이 적용된 객체의 복사본을 반환한다는 의미입니다.따라서, 다른 스레드가 여전히 객체를 읽고 있는 경우, 끔찍한 충돌이 발생하는 대신 변경 사항을 인식하지 못한 채 "이전" 버전에서 계속 원활하게 작동합니다.보다 http://www.javapractices.com/topic/TopicAction.do?Id=29

도움이 되었습니까?

해결책

요즘에는 개체 생성 속도가 매우 빠르며 개체 풀링의 개념은 다소 쓸모가 없습니다(적어도 일반적으로;물론 연결 풀링은 여전히 ​​유효합니다.)

조기 최적화를 피하세요.복사할 때 필요할 때 노드를 생성한 다음 엄청나게 느려지는지 확인하세요.그렇다면 속도를 높이는 몇 가지 기술을 살펴보십시오.그러나 당신이 가지고 있는 것이 충분히 빠르지 않다는 것을 이미 알고 있지 않다면 풀링을 진행하는 데 필요한 모든 복잡성을 소개하지 않을 것입니다.

다른 팁

나는 대답을 하기 싫지만 이와 같은 성능 질문에 대답하는 유일한 확실한 방법은 두 가지 접근 방식을 모두 코딩하고 두 가지를 벤치마킹하고 결과를 비교하는 것일 수 있다고 생각합니다.

모든 것이 스레드로부터 안전한지 확인하기 위해 특정 메서드를 명시적으로 동기화하는 것을 피할 수 있는지 잘 모르겠습니다.

한 가지 특정한 경우에는 새로 생성된 노드를 다른 스레드에서 사용할 수 있도록 한쪽 또는 다른 쪽을 동기화해야 합니다. 그렇지 않으면 VM/CPU가 공유 노드에 대한 참조 쓰기를 지나 필드 쓰기 순서를 다시 지정하여 노출될 위험이 있습니다. 파티가 만든 물건.

더 높은 수준에서 생각해보세요.IMMUTABLE 트리(기본적으로 자식을 가리키는 노드 집합)가 있습니다.노드를 삽입하려고 합니다.그렇다면 탈출구가 없습니다.새로운 전체 트리를 만들어야 합니다.

트리를 자식을 가리키는 노드 집합으로 구현하기로 선택한 경우 변경된 노드의 루트 경로를 따라 새 노드를 만들어야 합니다.나머지는 이전과 동일한 값을 가지며 일반적으로 공유됩니다.따라서 일반적으로 상위 노드(편집된 노드의 깊이)를 의미하는 부분적인 새 트리를 만들어야 합니다.

덜 직접적인 구현에 대처할 수 있다면 에 설명된 것과 유사한 기술을 사용하여 노드의 일부만 생성하는 것만으로도 충분합니다. 순전히 기능적인 데이터 구조 평균 생성 비용을 줄이거나 반기능적 접근 방식을 사용하여 이를 우회할 수 있습니다(예: 기존 반복자를 래핑하지만 복구 메커니즘과 함께 이전 노드 대신 새 노드를 반환하는 반복자 생성) 시간이 지남에 따라 구조에 이러한 패치가 발생합니다.이 경우 XPath 스타일 API가 DOM API보다 나을 수 있습니다. 트리에서 노드를 좀 더 분리하고 변형된 트리를 더 지능적으로 처리할 수 있습니다.

처음에 무엇을 하려는지 조금 혼란스럽습니다.모든 노드를 불변으로 만들고 풀링하고 싶습니까?이 두 가지 아이디어는 상호 배타적이지 않나요?풀에서 객체를 꺼낼 때 자식을 연결하기 위해 setter를 호출해야 하지 않나요?

불변 노드를 사용한다고 해서 애초에 필요한 스레드 안전성을 얻을 수 없을 수도 있다고 생각합니다.한 스레드가 노드(검색 등)를 반복하는 동안 다른 스레드가 노드를 추가/제거하는 경우 어떻게 되나요?검색 결과가 무효가 되는 것은 아닌가요?모든 것이 스레드로부터 안전한지 확인하기 위해 특정 메서드를 명시적으로 동기화하는 것을 피할 수 있는지 잘 모르겠습니다.

@무법자 프로그래머

수영장에서 물체를 꺼낼 때 아이들을 연결하기 위해 세터를 호출 할 필요가 없습니까?

각 노드는 패키지 내부적으로는 변경할 수 없으며 외부 인터페이스에서만 변경할 수 있습니다. node.addChild() 공개적으로 표시되고 문서를 반환하는 불변 함수입니다. node.addChildInternal() 패키지 가시성을 갖춘 정상적이고 변경 가능한 함수입니다.그러나 패키지 내부에 있으므로 다음의 하위 항목으로만 호출할 수 있습니다. addChild() 그리고 구조 전체가 스레드 안전이 보장됩니다(객체 풀에 대한 액세스를 동기화하는 경우).이것에 흠집이 보이시나요...?그렇다면 알려주세요!

불변 노드를 사용한다고 해서 애초에 필요한 스레드 안전성을 얻을 수 없을 수도 있다고 생각합니다.한 스레드가 노드(검색 등)를 반복하는 동안 다른 스레드가 노드를 추가/제거하는 경우 어떻게 되나요?

트리 전체는 불변입니다.Thread1과 Thread2, 그리고 트리 dom1이 있다고 가정해 보겠습니다.Thread1은 dom1에서 읽기 작업을 시작하는 동시에 Thread2는 dom1에서 쓰기 작업을 시작합니다.그러나 Thread2의 모든 변경 사항은 실제로 새 개체인 dom2에 적용되며 dom1은 변경할 수 없습니다.Thread1이 읽은 값이 (몇 마이크로초) 오래된 것은 사실이지만 IndexOutOfBounds 또는 NullPointer 예외나 기록 중인 변경 가능한 개체를 읽는 경우와 유사한 경우에는 충돌이 발생하지 않습니다.그런 다음 Thread2는 dom2가 포함된 이벤트를 Thread1에 발생시켜 필요한 경우 다시 읽고 결과를 업데이트할 수 있습니다.

편집하다:명확히하다

@Outlaw에는 일리가 있다고 생각합니다.DOM 트리의 구조는 노드 자체에 상주하며 노드가 자식을 가리킵니다.트리 구조를 수정하려면 노드를 수정해야 하므로 노드를 풀링할 수 없으므로 새 노드를 만들어야 합니다.

더 높은 수준에서 생각해보세요.IMMUTABLE 트리(기본적으로 자식을 가리키는 노드 집합)가 있습니다.노드를 삽입하려고 합니다.그렇다면 탈출구가 없습니다.새로운 전체 트리를 만들어야 합니다.

예, 불변 트리는 스레드로부터 안전하지만 성능에 영향을 미칩니다.객체 생성은 빠를 수 있지만 객체 생성이 없는 것보다 빠르지는 않습니다.:)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top