SlideShare a Scribd company logo
1 of 27
Download to read offline
제 4장
빛의 속도록 

XML 파싱하기
김경렬
XML 파싱 모형.
❖ SAX(Simple API for XML) - 스트림과 ‘태그 시작, 끝, 문
자자료’등의 콜백으로 데이터 처리.!
❖ Pull Parsing - SAX 유사, iterator 객체를 통해 제어.!
❖ DOM(Document Object Model) - 입력을 문서 객체로 변
환후 처리.
pugixml DOM 파서
❖ 메모리 안에 들어갈 정도로 작은 문서.!
❖ 방문할 노드들이 서로 참조하는 복잡한 구조를 가진 문서!
❖ 복잡한 방식으로 변환해야 하는 문서.
pugixml 설계상의 선택
❖ 아주 빠르고 가벼운 DOM 기반 XML 조작 라이브러리를
목표로 개발.!
❖ 성능과 XML 검증의 절충점.!
❖ well-formed 검증.!
❖ DTD(Document Type Declaration)은 검증 않함.!
❖ 종종 well-formed 가 아닌 경우도 성공으로 처리.
파싱
❖ 토큰 스트림 대신 문자 스트림에 대해 파싱을 수행.!
❖ UTF-8 문자만 지원.!
❖ 제자리 파싱(In-place parsing) - 스트림에 있는 자료를 직
접 처리하는 방식.

문자열 복사를 최소화하기 위해.
In-place parsing
❖ 문자열을 만나면 그 문자열의 포인터와 길이를 저장.!
❖ 성능 좋아지지만, 메모리 사용량은 증가.

- 원본 스트림 유지.
< n > T h e n o d e t e x t < / n >
포인터0xabc3, 길이 130xabc0
In-place parsing - 널문자 처리
❖ 문자열 접근을 보다 빠르게 하기 위하여 널문자를 삽입.!
❖ XML은 문자열 끝 다음 문자는 < 기호로 구분됨.
< n > T h e n o d e t e x t 0 / n >
포인터0xabc3, 길이 130xabc0
In-place parsing - 문자 표현 처리
❖ 문자열이 표현과 다른 경우 파싱중 처리.!
❖ `line1xDxAline2xDline3xAxA` 을

line1xAline2xAline3xAxA` 로 변환.!
❖ 문자 참조 확장 - &#97; 을 a 로 변환.!
❖ 개체 참조 확장 - &lt; (<), &gt;(>), &quot;(“), &apos;(‘);
&amp;(&)!
❖ 특성 값 정규화(Attribute-value normalization) - 모든 공
백문자를 빈칸으로 변환.
In-place parsing - 문자 표현 처리
❖ 변환 때문에 물자열이 더 길어져서는 안된다.!
❖ 변환 결과가 더 길면 문서 자료를 덮어 쓸 수 있기 때문.
< n > A & # 3 2 ; & l t ; B . < / n >0xabc0
< n > A < B . 0 l t ; B . < / n >0xabc0
In-place parsing - Copy-on-Write
❖ memory-mapped file I/O 을 사용.!
❖ 널종료와 텍스트 변환을 지원하기 위해 Copy-on-Write 방식을 적
용하여 원본 파일이 변경되는 것을 막음.!
❖ 프로세스 주소 공간에 직접 대응 시키므로 메모리 복사를 피할
수 있음.!
❖ 파일이 캐시되지 않은 경우 커널이 로딩하므로 입출력과 파싱이
병렬적으로 진행.!
❖ 수정된 페이지만 물리적 메모리에 할당되므로 메모리 소비를 줄
일 수 있음.
문자별 연산의 최적화

Optimizing character-wise operations
❖ 문자 하나에 소비된 평균 프로세서 주기(cycle) 수이다.!
❖ 문자 집합 소속 여부 검출

한 문자가 어떤 문자 집합에 속하는지 판정하는 것.
! enum chartype_t!
! {!
! ! ct_parse_pcdata = 1,! // 0, &, r, <!
! ! ct_parse_attr = 2,!! // 0, &, r, ', "!
! ! ct_parse_attr_ws = 4,! // 0, &, r, ', ", n, tab!
! ! ct_space = 8,! ! ! // r, n, space, tab!
! ! ct_parse_cdata = 16,! // 0, ], >, r!
! ! ct_parse_comment = 32,!// 0, -, >, r!
! ! ct_symbol = 64,! ! ! // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, .!
! ! ct_start_symbol = 128! // Any symbol > 127, a-z, A-Z, _, :!
! };!
!
! static const unsigned char chartype_table[256] =!
! {!
! ! 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15!
! ! 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31!
! ! 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47!
! ! 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63!
! ! 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79!
! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95!
! ! 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111!
! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127!
!
! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+!
! ! … … …!
! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192!
! };!
!
! bool ischartype_utf8(char c, chartype_t ct){!
! ! return ct & chartype_table[(unsigned char)c];!
! }!
특정 구간의 모든 문자
❖ 주어진 문자가 숫자인지 판정하는 함수!
❖ bool isdigit(char ch) { return (ch >= '0' && ch <= '9'); }!
❖ bool isdigit(char ch) { return (unsigned)(ch - '0') < 10; }
UTF-8 바이트열
❖ 연속된 4 바이트가 ASCII 기호를 나타내는 UTF-8 바이트
열인지 판별하는 코드.!
❖ (*(const uint32_t*)data & 0x80808080) == 0
표준 라이브러리 is*() 함수
❖ 성능이 중요한 코드에서는 isalpha()등을 피해야 함.!
❖ locale 이 “C” 인지 점검하는 과정때문.
문자열 변환의 최적화
Optimizing string transformations
❖ 문자열 값을 읽고 변환하는 과정에서 시간 소비가 크다.!
❖ A&#32;&lt; B.!
❖ A < B.
PCDATA 파싱 함수
❖ bool 플래그 2개 -> 4개 변형.!
❖ 문자들은 문자 집합 판정 이
용.
template <bool opt_eol, bool opt_escape> struct!
! strconv_pcdata_impl {!
! static char_t* parse(char_t* s) {!
! gap g;!
! while (true) {!
! while (!PUGI__IS_CHARTYPE(*s, ct_parse_pcdata)) ++s;!
! if (*s == '<') { // PCDATA ends here!
! *g.flush(s) = 0;!
! return s + 1;!
! } else if (opt_eol && *s == 'r') { // 0x0d or 0x0d 0x0a pair!
! *s++ = 'n'; // replace first one with 0x0a!
! if (*s == 'n') g.push(s, 1);!
! } else if (opt_escape && *s == '&') {!
! s = strconv_escape(/s, g);!
! } else if (*s == 0) {!
! return s;!
! } else {!
! ++s;!
! }!
! }!
! }!
! };!
PCDATA 틈(GAP) 관리
❖ &quot; 를 “ 로 대체하면 문자 다섯개의 틈이 생김.!
❖ 두 틈을 병합 - 기존 틈과 새 틈 사이 자료를 앞으로 옮김.!
❖ 읽기/쓰기 포인터보다 좀 더 빠르게 병합(memmove)
제어 흐름의 최적화
Optimizing control flow
❖ 재귀적 하강 파서(recursive-descent parser) 형태에서 성
능 향상을 위해 재귀를 반복 루프로 변경.!
❖ 노드 커서는 스택방식으로 동작.!
❖ 스택 공간 소비량이 입력 문서와 무관하게 일정.!
❖ 안정성을 증가.!
❖ 잠재적인 비싼 함수 호출을 피함. ???
분기 순서와 코드 국소성
❖ 자주 실행되는 부분(태그이름,속성)과 거의 실행되지 않
는 부분(DOCTYPE)!
❖ 처리 확률 - ‘<‘ 문자 다음 ‘태그 이름’, ‘/‘, ‘!’, ‘?’ 순의 확률
로 나타남.!
❖ 코드 조각들의 확률에 따라 재배치!
❖ 인라인 코드량을 제한.
❖ 조건 분기들을 확률이 높은 거에서 낮은 것 순서로 재배치.!
❖ 평균적인 조건 판정 및 분기 수행 횟수가 최소화.
! if (data[0] == '<')!
! {!
! if (data[1] == '!') { ... }!
! else if (data[1] == '/') { ... }!
! else if (data[1] == '?') { ... }!
! else { /* start-tag or unrecognized tag */ }!
! }!
!
! if (data[0] == '<')!
! {!
! if (PUGI__IS_CHARTYPE(data[1], ct_start_symbol)) { /* start-tag */ }!
! else if (data[1] == '/') { ... }!
! else if (data[1] == '!') { ... }!
! else if (data[1] == '?') { ... }!
! else { /* unrecognized tag */ }!
! }!
메모리 안정성 보장
❖ 버퍼 오버플로우를 막기 위해.!
❖ 현재 읽기와 버퍼 끝을 비교.!
❖ 하나의 레지스터가 더 필요.!
❖ 함수 호출시 현재 위치와 끝위치를 전달할 포인터 필요!
❖ 널문자 처리.!
❖ 입력 버퍼와 버퍼 크기를 전달하는 경우 사용의 불편함
발생.
DOM 자료 구조
❖ 연결 목록 기반 접근 방식을 사용하
는 노드 수정은 O(1).!
❖ 연결 목록 접근 방식- 고정 크기 할
당을 위한 빠른 메모리 할당자를 설
계하는 것이 임의 크기 할당자보다
쉽다.!
❖ 메모리 절약 - last_child 제거,
prev_sibling_cyclic 으로 대체O(1).
struct Node {!
Node* first_child;!
Node* last_child;!
Node* prev_sibling;!
Node* next_sibling;!
};!
struct Node {!
Node* first_child;!
Node* prev_sibling_cyclic;!
Node* next_sibling;!
};!
Node* last_child(Node* node) {!
return (node->first_child) ?!
node->first_child->prev_sibling_cyclic : NULL;!
}!
!
Node* prev_sibling(Node* node) {!
return (/node->prev_sibling_cyclic->next_sibling) ?!
node->prev_sibling_cyclic : NULL;!
}!
스택 기반 메모리 할당
❖ 가변 크기 문자열 할당.!
❖ 할당 국소성을 유지.!
❖ DOM 파괴 속도을 위한 메모리 해제.
스택 할당자
const size_t allocator_page_size = 32768;!
struct allocator_page {!
allocator_page* next_page;!
size_t offset;!
char data[allocator_page_size];!
};!
struct allocator_state {!
allocator_page* current;!
};!
!
void* allocate_new_page_data(size_t size) {!
size_t extra_size = (size >
allocator_page_size) ?!
size - allocator_page_size : 0;!
return malloc(sizeof(allocator_page) +
extra_size);!
}
void* allocate_oob(allocator_state* state,
size_t size) {!
allocator_page* page =
(allocator_page*)allocate_new_page_data(siz
e);!
// add page to page list!
page->next_page = state->current;!
state->current = page;!
// user data is located at the beginning
of the page!
page->offset = size;!
return page->data;!
}!
!
void* allocate(allocator_state* state,
size_t size) {!
if (state->current->offset + size <=
allocator_page_size) {!
void* result = state->current->data +
state->current->offset;!
state->current->offset += size;!
return result;!
}!
return allocate_oob(state, size);!
}!
스택 기반 할당자의 메모리 해제 지원
❖ 메모리 해제와 재사용을 위해 참조 카운트 방식 도입.!
❖ 모든 페이지는 32바이트 경계로 정렬되고 모든 페이지 포인터의
하위 다섯 비트는 항상 0이다. ???!
❖ 5비트에 XML 메타 데이터를 저장.!
❖ 할당된 요소의 위치를 페이지 시작 위치를 기준으로 오프셋으로
저장.!
❖ 페이지 포인터의 주소 => 

(allocator_page*)((char*)(object) -object->offset -
offsetof(allocator_page, data))

More Related Content

Similar to Ch4 pugixml

Programming skills 1부
Programming skills 1부Programming skills 1부
Programming skills 1부JiHyung Lee
 
04장 고급변수 사용
04장 고급변수 사용04장 고급변수 사용
04장 고급변수 사용유석 남
 
Http 완벽 가이드(2장 url과 리소스)
Http 완벽 가이드(2장 url과 리소스)Http 완벽 가이드(2장 url과 리소스)
Http 완벽 가이드(2장 url과 리소스)Choonghyun Yang
 
[Kgc2013] 모바일 엔진 개발기
[Kgc2013] 모바일 엔진 개발기[Kgc2013] 모바일 엔진 개발기
[Kgc2013] 모바일 엔진 개발기changehee lee
 
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)Sang Don Kim
 
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기Chris Ohk
 
[전파교육] css day 2014
[전파교육] css day 2014[전파교육] css day 2014
[전파교육] css day 2014Kyoung Hwan Min
 
Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3plusperson
 

Similar to Ch4 pugixml (8)

Programming skills 1부
Programming skills 1부Programming skills 1부
Programming skills 1부
 
04장 고급변수 사용
04장 고급변수 사용04장 고급변수 사용
04장 고급변수 사용
 
Http 완벽 가이드(2장 url과 리소스)
Http 완벽 가이드(2장 url과 리소스)Http 완벽 가이드(2장 url과 리소스)
Http 완벽 가이드(2장 url과 리소스)
 
[Kgc2013] 모바일 엔진 개발기
[Kgc2013] 모바일 엔진 개발기[Kgc2013] 모바일 엔진 개발기
[Kgc2013] 모바일 엔진 개발기
 
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
[Td 2015]녹슨 c++ 코드에 모던 c++로 기름칠하기(옥찬호)
 
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
[TechDays Korea 2015] 녹슨 C++ 코드에 모던 C++로 기름칠하기
 
[전파교육] css day 2014
[전파교육] css day 2014[전파교육] css day 2014
[전파교육] css day 2014
 
Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3Daejeon IT Developer Conference Hibernate3
Daejeon IT Developer Conference Hibernate3
 

More from Kyungryul KIM

전문검색기술도전
전문검색기술도전전문검색기술도전
전문검색기술도전Kyungryul KIM
 
Nib_NSWindowController
Nib_NSWindowControllerNib_NSWindowController
Nib_NSWindowControllerKyungryul KIM
 
서버인프라를지탱하는기술5 1 2
서버인프라를지탱하는기술5 1 2서버인프라를지탱하는기술5 1 2
서버인프라를지탱하는기술5 1 2Kyungryul KIM
 
Chaper24 languages high_and_low
Chaper24 languages high_and_lowChaper24 languages high_and_low
Chaper24 languages high_and_lowKyungryul KIM
 
Ch22 운영체제
Ch22 운영체제Ch22 운영체제
Ch22 운영체제Kyungryul KIM
 

More from Kyungryul KIM (20)

Node ch12
Node ch12Node ch12
Node ch12
 
11.scripting
11.scripting11.scripting
11.scripting
 
32 osx app_release
32 osx app_release32 osx app_release
32 osx app_release
 
Meteor ddp
Meteor ddpMeteor ddp
Meteor ddp
 
Cocos2dx 7.1-7.2
Cocos2dx 7.1-7.2Cocos2dx 7.1-7.2
Cocos2dx 7.1-7.2
 
Cocos2 d x-7.3_4
Cocos2 d x-7.3_4Cocos2 d x-7.3_4
Cocos2 d x-7.3_4
 
Cocos2d x-ch5-1
Cocos2d x-ch5-1Cocos2d x-ch5-1
Cocos2d x-ch5-1
 
Coco2d x
Coco2d xCoco2d x
Coco2d x
 
23 drag drop
23 drag drop23 drag drop
23 drag drop
 
Hadoop ch5
Hadoop ch5Hadoop ch5
Hadoop ch5
 
전문검색기술도전
전문검색기술도전전문검색기술도전
전문검색기술도전
 
Nib_NSWindowController
Nib_NSWindowControllerNib_NSWindowController
Nib_NSWindowController
 
Dsas
DsasDsas
Dsas
 
서버인프라를지탱하는기술5 1 2
서버인프라를지탱하는기술5 1 2서버인프라를지탱하는기술5 1 2
서버인프라를지탱하는기술5 1 2
 
Chaper24 languages high_and_low
Chaper24 languages high_and_lowChaper24 languages high_and_low
Chaper24 languages high_and_low
 
Ch22 운영체제
Ch22 운영체제Ch22 운영체제
Ch22 운영체제
 
Mibis ch20
Mibis ch20Mibis ch20
Mibis ch20
 
Mibis ch15
Mibis ch15Mibis ch15
Mibis ch15
 
Mibis ch8
Mibis ch8Mibis ch8
Mibis ch8
 
Mibis ch4
Mibis ch4Mibis ch4
Mibis ch4
 

Ch4 pugixml

  • 1. 제 4장 빛의 속도록 
 XML 파싱하기 김경렬
  • 2. XML 파싱 모형. ❖ SAX(Simple API for XML) - 스트림과 ‘태그 시작, 끝, 문 자자료’등의 콜백으로 데이터 처리.! ❖ Pull Parsing - SAX 유사, iterator 객체를 통해 제어.! ❖ DOM(Document Object Model) - 입력을 문서 객체로 변 환후 처리.
  • 3. pugixml DOM 파서 ❖ 메모리 안에 들어갈 정도로 작은 문서.! ❖ 방문할 노드들이 서로 참조하는 복잡한 구조를 가진 문서! ❖ 복잡한 방식으로 변환해야 하는 문서.
  • 4. pugixml 설계상의 선택 ❖ 아주 빠르고 가벼운 DOM 기반 XML 조작 라이브러리를 목표로 개발.! ❖ 성능과 XML 검증의 절충점.! ❖ well-formed 검증.! ❖ DTD(Document Type Declaration)은 검증 않함.! ❖ 종종 well-formed 가 아닌 경우도 성공으로 처리.
  • 5. 파싱 ❖ 토큰 스트림 대신 문자 스트림에 대해 파싱을 수행.! ❖ UTF-8 문자만 지원.! ❖ 제자리 파싱(In-place parsing) - 스트림에 있는 자료를 직 접 처리하는 방식.
 문자열 복사를 최소화하기 위해.
  • 6. In-place parsing ❖ 문자열을 만나면 그 문자열의 포인터와 길이를 저장.! ❖ 성능 좋아지지만, 메모리 사용량은 증가.
 - 원본 스트림 유지. < n > T h e n o d e t e x t < / n > 포인터0xabc3, 길이 130xabc0
  • 7. In-place parsing - 널문자 처리 ❖ 문자열 접근을 보다 빠르게 하기 위하여 널문자를 삽입.! ❖ XML은 문자열 끝 다음 문자는 < 기호로 구분됨. < n > T h e n o d e t e x t 0 / n > 포인터0xabc3, 길이 130xabc0
  • 8. In-place parsing - 문자 표현 처리 ❖ 문자열이 표현과 다른 경우 파싱중 처리.! ❖ `line1xDxAline2xDline3xAxA` 을
 line1xAline2xAline3xAxA` 로 변환.! ❖ 문자 참조 확장 - &#97; 을 a 로 변환.! ❖ 개체 참조 확장 - &lt; (<), &gt;(>), &quot;(“), &apos;(‘); &amp;(&)! ❖ 특성 값 정규화(Attribute-value normalization) - 모든 공 백문자를 빈칸으로 변환.
  • 9. In-place parsing - 문자 표현 처리 ❖ 변환 때문에 물자열이 더 길어져서는 안된다.! ❖ 변환 결과가 더 길면 문서 자료를 덮어 쓸 수 있기 때문. < n > A & # 3 2 ; & l t ; B . < / n >0xabc0 < n > A < B . 0 l t ; B . < / n >0xabc0
  • 10. In-place parsing - Copy-on-Write ❖ memory-mapped file I/O 을 사용.! ❖ 널종료와 텍스트 변환을 지원하기 위해 Copy-on-Write 방식을 적 용하여 원본 파일이 변경되는 것을 막음.! ❖ 프로세스 주소 공간에 직접 대응 시키므로 메모리 복사를 피할 수 있음.! ❖ 파일이 캐시되지 않은 경우 커널이 로딩하므로 입출력과 파싱이 병렬적으로 진행.! ❖ 수정된 페이지만 물리적 메모리에 할당되므로 메모리 소비를 줄 일 수 있음.
  • 11. 문자별 연산의 최적화
 Optimizing character-wise operations ❖ 문자 하나에 소비된 평균 프로세서 주기(cycle) 수이다.! ❖ 문자 집합 소속 여부 검출
 한 문자가 어떤 문자 집합에 속하는지 판정하는 것.
  • 12. ! enum chartype_t! ! {! ! ! ct_parse_pcdata = 1,! // 0, &, r, <! ! ! ct_parse_attr = 2,!! // 0, &, r, ', "! ! ! ct_parse_attr_ws = 4,! // 0, &, r, ', ", n, tab! ! ! ct_space = 8,! ! ! // r, n, space, tab! ! ! ct_parse_cdata = 16,! // 0, ], >, r! ! ! ct_parse_comment = 32,!// 0, -, >, r! ! ! ct_symbol = 64,! ! ! // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, .! ! ! ct_start_symbol = 128! // Any symbol > 127, a-z, A-Z, _, :! ! };! ! ! static const unsigned char chartype_table[256] =! ! {! ! ! 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15! ! ! 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31! ! ! 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47! ! ! 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63! ! ! 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79! ! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95! ! ! 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111! ! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127! ! ! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+! ! ! … … …! ! ! 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192! ! };! ! ! bool ischartype_utf8(char c, chartype_t ct){! ! ! return ct & chartype_table[(unsigned char)c];! ! }!
  • 13. 특정 구간의 모든 문자 ❖ 주어진 문자가 숫자인지 판정하는 함수! ❖ bool isdigit(char ch) { return (ch >= '0' && ch <= '9'); }! ❖ bool isdigit(char ch) { return (unsigned)(ch - '0') < 10; }
  • 14. UTF-8 바이트열 ❖ 연속된 4 바이트가 ASCII 기호를 나타내는 UTF-8 바이트 열인지 판별하는 코드.! ❖ (*(const uint32_t*)data & 0x80808080) == 0
  • 15. 표준 라이브러리 is*() 함수 ❖ 성능이 중요한 코드에서는 isalpha()등을 피해야 함.! ❖ locale 이 “C” 인지 점검하는 과정때문.
  • 16. 문자열 변환의 최적화 Optimizing string transformations ❖ 문자열 값을 읽고 변환하는 과정에서 시간 소비가 크다.! ❖ A&#32;&lt; B.! ❖ A < B.
  • 17. PCDATA 파싱 함수 ❖ bool 플래그 2개 -> 4개 변형.! ❖ 문자들은 문자 집합 판정 이 용. template <bool opt_eol, bool opt_escape> struct! ! strconv_pcdata_impl {! ! static char_t* parse(char_t* s) {! ! gap g;! ! while (true) {! ! while (!PUGI__IS_CHARTYPE(*s, ct_parse_pcdata)) ++s;! ! if (*s == '<') { // PCDATA ends here! ! *g.flush(s) = 0;! ! return s + 1;! ! } else if (opt_eol && *s == 'r') { // 0x0d or 0x0d 0x0a pair! ! *s++ = 'n'; // replace first one with 0x0a! ! if (*s == 'n') g.push(s, 1);! ! } else if (opt_escape && *s == '&') {! ! s = strconv_escape(/s, g);! ! } else if (*s == 0) {! ! return s;! ! } else {! ! ++s;! ! }! ! }! ! }! ! };!
  • 18. PCDATA 틈(GAP) 관리 ❖ &quot; 를 “ 로 대체하면 문자 다섯개의 틈이 생김.! ❖ 두 틈을 병합 - 기존 틈과 새 틈 사이 자료를 앞으로 옮김.! ❖ 읽기/쓰기 포인터보다 좀 더 빠르게 병합(memmove)
  • 19. 제어 흐름의 최적화 Optimizing control flow ❖ 재귀적 하강 파서(recursive-descent parser) 형태에서 성 능 향상을 위해 재귀를 반복 루프로 변경.! ❖ 노드 커서는 스택방식으로 동작.! ❖ 스택 공간 소비량이 입력 문서와 무관하게 일정.! ❖ 안정성을 증가.! ❖ 잠재적인 비싼 함수 호출을 피함. ???
  • 20. 분기 순서와 코드 국소성 ❖ 자주 실행되는 부분(태그이름,속성)과 거의 실행되지 않 는 부분(DOCTYPE)! ❖ 처리 확률 - ‘<‘ 문자 다음 ‘태그 이름’, ‘/‘, ‘!’, ‘?’ 순의 확률 로 나타남.! ❖ 코드 조각들의 확률에 따라 재배치! ❖ 인라인 코드량을 제한.
  • 21. ❖ 조건 분기들을 확률이 높은 거에서 낮은 것 순서로 재배치.! ❖ 평균적인 조건 판정 및 분기 수행 횟수가 최소화. ! if (data[0] == '<')! ! {! ! if (data[1] == '!') { ... }! ! else if (data[1] == '/') { ... }! ! else if (data[1] == '?') { ... }! ! else { /* start-tag or unrecognized tag */ }! ! }! ! ! if (data[0] == '<')! ! {! ! if (PUGI__IS_CHARTYPE(data[1], ct_start_symbol)) { /* start-tag */ }! ! else if (data[1] == '/') { ... }! ! else if (data[1] == '!') { ... }! ! else if (data[1] == '?') { ... }! ! else { /* unrecognized tag */ }! ! }!
  • 22. 메모리 안정성 보장 ❖ 버퍼 오버플로우를 막기 위해.! ❖ 현재 읽기와 버퍼 끝을 비교.! ❖ 하나의 레지스터가 더 필요.! ❖ 함수 호출시 현재 위치와 끝위치를 전달할 포인터 필요! ❖ 널문자 처리.! ❖ 입력 버퍼와 버퍼 크기를 전달하는 경우 사용의 불편함 발생.
  • 23. DOM 자료 구조 ❖ 연결 목록 기반 접근 방식을 사용하 는 노드 수정은 O(1).! ❖ 연결 목록 접근 방식- 고정 크기 할 당을 위한 빠른 메모리 할당자를 설 계하는 것이 임의 크기 할당자보다 쉽다.! ❖ 메모리 절약 - last_child 제거, prev_sibling_cyclic 으로 대체O(1). struct Node {! Node* first_child;! Node* last_child;! Node* prev_sibling;! Node* next_sibling;! };! struct Node {! Node* first_child;! Node* prev_sibling_cyclic;! Node* next_sibling;! };!
  • 24. Node* last_child(Node* node) {! return (node->first_child) ?! node->first_child->prev_sibling_cyclic : NULL;! }! ! Node* prev_sibling(Node* node) {! return (/node->prev_sibling_cyclic->next_sibling) ?! node->prev_sibling_cyclic : NULL;! }!
  • 25. 스택 기반 메모리 할당 ❖ 가변 크기 문자열 할당.! ❖ 할당 국소성을 유지.! ❖ DOM 파괴 속도을 위한 메모리 해제.
  • 26. 스택 할당자 const size_t allocator_page_size = 32768;! struct allocator_page {! allocator_page* next_page;! size_t offset;! char data[allocator_page_size];! };! struct allocator_state {! allocator_page* current;! };! ! void* allocate_new_page_data(size_t size) {! size_t extra_size = (size > allocator_page_size) ?! size - allocator_page_size : 0;! return malloc(sizeof(allocator_page) + extra_size);! } void* allocate_oob(allocator_state* state, size_t size) {! allocator_page* page = (allocator_page*)allocate_new_page_data(siz e);! // add page to page list! page->next_page = state->current;! state->current = page;! // user data is located at the beginning of the page! page->offset = size;! return page->data;! }! ! void* allocate(allocator_state* state, size_t size) {! if (state->current->offset + size <= allocator_page_size) {! void* result = state->current->data + state->current->offset;! state->current->offset += size;! return result;! }! return allocate_oob(state, size);! }!
  • 27. 스택 기반 할당자의 메모리 해제 지원 ❖ 메모리 해제와 재사용을 위해 참조 카운트 방식 도입.! ❖ 모든 페이지는 32바이트 경계로 정렬되고 모든 페이지 포인터의 하위 다섯 비트는 항상 0이다. ???! ❖ 5비트에 XML 메타 데이터를 저장.! ❖ 할당된 요소의 위치를 페이지 시작 위치를 기준으로 오프셋으로 저장.! ❖ 페이지 포인터의 주소 => 
 (allocator_page*)((char*)(object) -object->offset - offsetof(allocator_page, data))