그러고보니 지난 호에서는 일반적인 XML 읽기 방법을 정리했지만 일반적으로 XML 소스의 모든 데이터를 반드시 사용하는 것은 아니기 때문에 첫 글자를 기준으로 위치 등 일부 데이터를 읽어오는 실험을 해봤습니다. 제목의.
세 가지 임의 읽기 방법은 쿼리 조건만 변경하면 됩니다.
XmlDocument: var nodeList = doc.DocumentElement.SelectNodes("item[substring(title,1,1)='M'][position() mod 10 = 0]"); XPathNavigator: var nodeList = nav.Select("/channel/item[substring(title,1,1)='M'][position() mod 10 = 0]"); Xml Linq: var nodelist = from node in xd.XPathSelectElements("/channel/item[substring(title,1,1)='M'][position() mod 10 = 0]")
XPath를 사용하면 코드 한 줄만 변경하면 됩니다. XPath는 또한 익히기가 매우 쉽고 SQL보다 훨씬 간단합니다. XPath 사용자를 위한 W3C Shcool의 구문 소개와 MSDN의 LINQ To XML을 참조하면 15분 안에 그 비밀을 익힐 수 있습니다.
하지만 XmlReader 방식의 경우 M으로 시작하는 제목도 읽어서 10개 항목 중 1개 항목을 선택하는 것도 쉽지 않습니다. 우아하게 구현되어서 이렇게 해야 했습니다. :
Code
static List<Channel> testXmlReader2() { var lstChannel = new List<Channel>(); var reader = XmlReader.Create(xmlStream); int n = 0;Channel channel = null; Search: while (reader.Read()) { if (reader.Name == "item" && reader.NodeType == XmlNodeType.Element) { while (reader.Read()) { if (reader.Name == "item") break; if (reader.NodeType != XmlNodeType.Element) continue; switch (reader.Name) { case "title": var title = reader.ReadString(); if (title[0] != 'M') goto Search; n++; if (n % 10 != 0) goto Search; channel = new Channel(); channel.Title = title; break; case "link": channel.Link = reader.ReadString(); break; case "description": channel.Description = reader.ReadString(); break; case "content": channel.Content = reader.ReadString(); break; case "pubDate": channel.PubDate = reader.ReadString(); break; case "author": channel.Author = reader.ReadString(); break; case "category": channel.Category = reader.ReadString(); break; default: break; } lstChannel.Add(channel); } } } return lstChannel; }
코드 구조가 크게 변경된 것을 볼 수 있습니다. 조건부 필터링을 수행하려면 로컬 변수 n을 추가하고, 엔터티 클래스의 초기화를 조정하고, 컬렉션 문의 위치를 추가해야 했고, 수년 동안 잊어버렸던 goto 문을 사용해야 했습니다. 점프합니다(VB가 더 좋습니다). Lao Zhao의 말에 따르면, 비즈니스 로직이 코드 세부사항의 구현에 스며들고 있습니다.
작업이 하위 계층에 매우 가깝기 때문에 매크로 수준에서 좋은 코드 최적화 방법을 찾기가 어렵습니다. 필터링 조건, 즉 비즈니스 로직이 더 복잡해지면 코드도 완전히 달라지게 되고, 이해성과 유지보수성은 거울과 같게 됩니다.
이제 시간 성능을 비교해 보겠습니다.
XmlDocment 26ms XPathNavigator 26ms XmlTextReader 20ms Xml Linq 28ms
4가지 방법의 데이터가 가까워졌습니다. Document와 Navigator의 시간 소모가 크게 줄었고, Reader 방법도 크게 줄지 않았습니다. 처음부터 끝까지 읽어야 하기 때문에 3ms가 줄어든 것은 엔터티 객체 생성 오버헤드가 줄어들었기 때문일 수 있습니다. 더 이상한 점은 Linq 방식이 바뀌지 않고 결국 떨어졌다는 것입니다.
다양한 쿼리 조건을 테스트할 수 있습니다. 이 네 가지 방법에는 각각 XML 소스의 크기와 관련된 자체 성능 제한이 있음을 알 수 있습니다. 예를 들어 처음 두 메서드의 경우 XmlDocument.Load 메서드의 실행 시간에 따라 달라집니다. 내 컴퓨터에서는 Xml을 로드하는 데 23ms가 걸립니다. Linq 메서드는 깨지지 않습니다. 처리할 결과가 거의 없으면 실행 시간이 1~2밀리초 줄어듭니다.
문서 및 탐색기 모드에서는 데이터 양이 증가함에 따라 성능이 크게 저하됩니다. 쓸모없는 물건을 많이 만들어내기 때문이라고 추측하기 쉽습니다. 각 방식의 메모리 사용량을 살펴보면, 필터링 없이 모든 데이터를 로드했을 때 Document 방식은 약 23.3M 정도의 메모리를 차지하는 반면, Navigator 방식은 약 22.9M 정도만 차지하는 것을 알 수 있습니다. 이 역시 성능이 좋은 이유를 설명합니다. Document 메소드의 감소가 더욱 뚜렷해졌습니다. 리더 모드는 데이터가 가득 차 있으며 약 20.1M 정도의 메모리만 필요합니다. 프로그램 시작 자체의 오버헤드를 제외하면 이전 두 가지 방법에 비해 절반 미만의 메모리를 차지합니다. Linq 방식은 Reader 방식에 비해 메모리 사용량이 500k도 채 안 되는 놀라운 메모리 성능을 자랑합니다.
추가 분석을 통해 추가 결론에 도달했습니다. 특별한 필요가 없는 한 XmlTextReader는 변경에 대한 준비가 제대로 되어 있지 않으며 오류가 발생하기 쉽습니다. 어떤 경우에는 시간 성능이 Navigator 방법보다 약간 낮기는 하지만 Linq 방법을 사용하는 것이 더 강력하게 권장됩니다. 그러나 뛰어난 메모리 사용 성능이 첫 번째 선택이 되었습니다. 그리고 저는 Linq To XML이 앞으로 더욱 강력해질 것이라고 믿습니다.
위는 XML 데이터 읽기 방식의 성능 비교입니다(2). 더 많은 관련 내용은 PHP 중국어 홈페이지(www.php.cn)를 참고해주세요!