문제
보통 XML 사용에 관해 이야기할 때 가장 문제가 되는 부분은 XML의 장황함과 XML의 구문 분석 속도입니다. 이 문제는 대용량 XML 파일을 처리해야 할 때 특히 심각해집니다. 여기서 언급하는 것은 XML 처리 속도를 최적화하는 방법에 대한 주제입니다.
XML 파일 처리를 선택할 때 일반적으로 두 가지 옵션이 있습니다.
W3C 표준 모델인 DOM, XML 구조 정보를 트리 모양으로 구축하는 인터페이스 및 메소드 제공 이 트리를 횡단하기 위해.
저수준 파서인 SAX는 요소별 정방향 읽기 전용 처리를 수행하며 구조적 정보를 포함하지 않습니다.
위의 두 옵션 모두 장단점이 있지만 특별히 좋은 해결책은 아닙니다. 장점과 단점은 다음과 같습니다.
DOM
장점: 사용 용이성, 모든 XML 구조 정보가 메모리에 존재하고 XPath를 지원하여 탐색이 간단하기 때문입니다.
단점: 파싱 속도가 너무 느리고, 메모리 사용량이 너무 높으며(원본 파일의 5배~10배), 대용량 파일에는 사용이 거의 불가능합니다.
SAX
장점: 구문 분석이 빠르고 메모리 사용량이 XML 크기와 관련이 없습니다(XML이 커짐에 따라 메모리를 늘리지 않고 수행 가능).
단점: 구조적 정보가 없고, 순회할 수 없으며, XPath를 지원하지 않아 사용성이 좋지 않습니다. 구조가 필요한 경우 조금만 읽고 조금만 구성하면 유지 관리성이 매우 떨어집니다.
DOM과 SAX는 기본적으로 서로 반대되는 두 극단이지만 어느 쪽도 대부분의 요구 사항을 잘 충족할 수 없다는 것을 알 수 있습니다. XML의 효율성 문제는 XML 자체의 문제가 아니라 XML을 처리하는 Parser의 문제입니다. 위에서 본 두 가지 방법이 서로 다른 효율성 균형을 가지고 있는 것처럼 말입니다.
생각
우리는 순회가 가능하기 때문에 DOM과 같은 방법을 사용하는 것을 좋아합니다. 이는 XPath를 지원할 수 있다는 것을 의미하며 이는 사용 편의성을 크게 향상시키지만 DOM의 효율성은 매우 낮습니다. . 우리가 이미 알고 있듯이 효율성 문제는 처리 메커니즘에 있습니다. 그렇다면 DOM의 어떤 측면이 효율성에 영향을 미칠까요? 포괄적으로 분석해 보겠습니다.
오늘날 가상 머신(호스팅 또는 유사한 메커니즘) 기술을 기반으로 하는 대부분의 플랫폼에서 객체 생성 및 삭제는 시간이 많이 걸리는 작업입니다. 가비지 수집에 시간이 많이 소요됨) DOM 메커니즘에 사용되는 수많은 개체 생성 및 삭제는 의심할 여지 없이 효율성에 영향을 미치는 이유 중 하나입니다(너무 많은 가비지 수집이 발생함).
각 개체에는 메모리 주소를 저장하기 위한 추가 32비트가 있습니다. DOM과 같은 개체 수가 많은 경우 이 추가 비용은 적지 않습니다.
위의 두 가지 문제를 일으키는 주요 효율성 문제는 DOM과 SAX가 모두 추출 구문 분석 모드라는 것입니다. 이 구문 분석 모드에는 DOM과 SAX 모두에 대해 많은 수의 생성(파괴) 개체가 필요하므로 효율성 문제가 발생합니다. 소위 추출 구문 분석은 XML, DOM 또는 SAX를 구문 분석할 때 원본 파일의 일부(일반적으로 문자열)를 추출한 다음 이를 메모리에서 구문 분석하고 구성하는 것을 의미합니다(출력은 자연적으로 하나 또는 일부 개체임). DOM을 예로 들면, DOM은 각 요소, 속성, 처리 명령, 주석 등을 객체로 구문 분석하여 구조를 제공합니다.
추출 문제로 인해 발생하는 또 다른 문제는 업데이트 효율성입니다. DOM(SAX는 업데이트를 지원하지 않으므로 전혀 언급하지 않음)에서는 변경이 필요할 때마다 해야 할 일은 다음과 같습니다. 객체 정보를 업데이트한 다음 XML 문자열을 다시 구문 분석합니다. 즉, 원본 파일은 사용되지 않지만 DOM 모델은 완전히 XML 문자열로 직접 다시 구문 분석됩니다. 즉, DOM은 Incremental Update(증분 업데이트)를 지원하지 않습니다.
눈에 띄지 않을 수 있는 또 다른 "작은" 문제는 XML 인코딩입니다. 어떤 구문 분석 방법을 사용하든 XML 인코딩, 즉 읽을 때 디코딩하고 쓸 때 디코딩을 처리할 수 있어야 합니다. 코딩할 때. DOM의 또 다른 효율성 문제는 대규모 XML을 약간 수정하려는 경우 먼저 전체 파일을 디코딩한 다음 구조를 빌드해야 한다는 것입니다. 눈에 보이지 않게 그것은 또 다른 비용이다.
문제를 간단히 요약하자면 DOM의 효율성 문제는 주로 추출 구문 분석 모드에 있습니다(동일한 문제가 있는 SAX의 경우에도 마찬가지입니다). 이로 인해 일련의 관련 문제가 발생했습니다. 효율성 병목 현상이 발생하면 XML 처리 효율성이 더욱 향상될 것으로 예상됩니다. XML의 사용 편의성과 처리 효율성이 크게 향상된다면 XML의 적용 범위와 적용 모델은 더욱 승화될 것이며 아마도 이전에 생각하지 못했던 XML 기반 제품이 많이 나올 것입니다.
탈출구
VTD-XML은 위의 문제에 대해 생각해 본 결과, 비추출적 XML 파서이며 뛰어난 메커니즘으로 인해 좋은 솔루션입니다. 피하기 위해)은 위에서 제기된 다양한 문제를 해결하고 "부수적으로" 빠른 구문 분석 및 탐색, XPath 지원, 증분 업데이트 등과 같은 기타 비추출적 이점을 제공합니다. 여기에 VTD-XML 공식 웹사이트에서 가져온 데이터 세트가 있습니다.
VTD-XML의 구문 분석 속도는 SAX(NULL 콘텐츠 핸들러 포함)의 구문 분석 속도보다 1.5x~2.0x입니다. NULL 콘텐츠 핸들러를 사용한다는 것은 SAX의 최대 속도인 SAX 구문 분석에 추가 처리 논리가 삽입되지 않음을 의미합니다.
VTD-XML의 메모리 사용량은 원본 XML의 1.3x~1.5x(1.0x 부분은 원본 XML이고 0.3x~0.5x 부분은 VTD-XML이 차지하는 부분)입니다. DOM의 메모리 사용량은 원래 XML의 5x~10x입니다. 예를 들어 XML 크기가 50MB인 경우 VTD-XML이 차지하는 메모리는 65MB~75MB이고 DOM이 차지하는 메모리는 250M~500MB입니다. DOM을 사용하여 이 데이터를 기반으로 하는 대규모 XML 파일을 처리하는 것은 거의 불가능한 옵션입니다.
놀랍게도 DOM보다 사용하기 쉽고 SAX보다 빠른 XML 파서를 만드는 것이 정말 가능할까요? 성급하게 결론을 내리지 말고 VTD-XML의 원리를 살펴보겠습니다!
기본 원리
대부분의 좋은 제품이 그렇듯이 VTD-XML의 원리는 복잡하지 않고 매우 기발합니다. 비추출의 목적을 달성하기 위해 원본 XML 파일을 디코딩하지 않고 바이너리 모드로 변경되지 않은 메모리로 읽은 다음 이 바이트 배열의 각 요소 위치를 구문 분석하고 일부 정보를 기록합니다. XML 콘텐츠를 추출해야 하는 경우 레코드의 위치 및 기타 정보를 사용하여 원본 바이트 배열을 디코딩하고 문자열을 반환합니다. 이 모든 것이 단순해 보이지만 이 간단한 프로세스에는 여러 성능 세부 정보가 포함되어 있으며 여러 잠재적 기능이 숨겨져 있습니다. 먼저 각 성능 세부 사항을 설명하겠습니다.
과도한 객체 생성을 피하기 위해 VTD-XML은 원래 숫자 유형을 레코드 유형으로 사용하기로 결정하여 힙이 필요하지 않습니다. VTD-XML의 기록 메커니즘을 VTD(Virtual Token Descriptor)라고 합니다. VTD는 토큰화 단계에서 성능 병목 현상을 해결하는데, 이는 정말 영리하고 사려 깊은 접근 방식입니다. VTD는 각 요소의 시작 위치(offset), 길이(length), 깊이(깊이), 토큰 유형(type) 등의 정보를 기록하는 64비트 길이의 숫자 유형입니다.
VTD는 고정 길이입니다(공식적으로 64비트를 사용하기로 결정함). 이는 성능 향상을 위한 것입니다. 길이가 고정되어 있으므로 읽기, 쿼리 및 기타 작업 시 매우 효율적입니다(O(1)). 즉, VTD를 구성하는 데 사용할 수 있는 효율적인 구조인 배열은 대량의 객체 사용으로 인해 발생하는 성능 문제를 크게 줄여줍니다.
VTD의 최고 강점(과장하지 않음)은 XML과 같은 트리 모양의 데이터 구조를 바이트 배열에 대한 연산으로 간단히 변환할 수 있다는 점이며, 바이트 배열에 대해 상상할 수 있는 모든 연산에 모두 적용할 수 있습니다. XML. 읽어온 XML이 바이너리(바이트 배열)이고 VTD가 각 요소의 위치와 기타 액세스 정보를 기록하기 때문입니다. 연산할 VTD를 찾으면 오프셋, 길이 등의 정보만 사용하면 됩니다. 원본 바이트 배열에서 작업을 수행하거나 VTD에서 직접 작업할 수 있습니다. 예를 들어, 큰 XML에서 요소를 찾아서 삭제하려면 이 요소의 VTD만 찾고(순회 방법은 나중에 설명함) VTD 배열에서 이 VTD를 삭제한 다음 다음을 사용하면 됩니다. all 삭제된 VTD는 삭제할 요소의 위치를 표시하므로 이 요소는 새로 작성된 바이트 배열에 나타나지 않습니다. VTD를 사용하여 새 바이트 배열은 실제로는 다음의 복사본입니다. 바이트 배열이며 효율성이 상당히 높습니다. 이는 소위 증분 업데이트입니다.
VTD-XML의 순회 방식은 깊이를 기준으로 VTD를 기반으로 구축된 단순한 트리 형태의 테이블 구조인 LC(Location Cache)를 사용합니다. LC 항목도 64비트 길이의 숫자 유형입니다. 처음 32비트는 VTD의 인덱스를 나타내고 마지막 32비트는 이 VTD의 첫 번째 하위 항목의 인덱스를 나타냅니다. 이 정보를 사용하여 도달하려는 위치를 계산할 수 있습니다. 구체적인 이동 방법은 공식 웹사이트의 기사를 참조하세요. 이 순회 방법을 기반으로 하는 VTD-XML은 DOM과 다른 작업 인터페이스를 가지고 있으며, VTD-XML의 이 순회 방법은 최소한의 단계로 필요한 위치로 이동할 수 있으므로 순회 성능이 매우 뛰어납니다.
요약
위에서 볼 수 있듯이 VTD-XML에는 매력적인 기능이 있으며 이제 버전 1.5에는 XPath에 대한 지원이 추가되었습니다(트래버스가 가능한 한 XPath를 지원할 수 있습니다. 시간 문제입니다 :-)), 그 실용성은 오늘날 우리가 상상하는 범위를 넘어섰습니다. VTD-XML의 또 다른 강력한 기능은 현재 처리 방법을 기반으로 미래의 Binary XML 표준을 완벽하게 지원하고 Binary를 통해 XML 응용 프로그램을 더 높은 수준으로 끌어올릴 수 있다는 것입니다! 이것이 내가 지금 기대하고 있는 것입니다! :-)
그러나 VTD-XML에는 아직 개선과 완성도가 필요한 부분이 많이 있으며, 이 부분은 우리의 노력과 논의의 가치가 있습니다.
위는 새롭게 떠오르는 XML 처리 방식 VTD-XML에 대한 소개입니다. 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 주목해주세요!