2015-01-19 3 views
0

ANTLR을 사용하여 C++ 용 Parser를 개발할 때 각 파서가 각 C++ 소스 파일을 구문 분석하도록 새 파서가 구성되는 배치 구문 분석 테스트 사례를 만들었습니다. 성능은 시작시 허용됩니다 - 파일 당 약 15 초. 그러나 150 개 이상의 파일을 구문 분석 한 후에는 각 파일의 구문 분석에 오래 걸리고 마지막으로 jvm에서 "GC 제한 초과"오류가 발생합니다.ANTLR4 파서가 ATNConfig 개체를 누적하는 이유는 무엇입니까?

JProfiler를 사용하여 각 파일을 구문 분석 한 후에 많은 ATNConfig 개체가 점진적으로 누적되는 것을 발견했습니다. 약 70M에서 시작하여 힙이 가득 찰 때까지 GC가 100 % CPU 시간을 소비 할 때까지 그들은 500M 이상으로 꾸준히 쌓입니다. JProfiler가 인식 할 수있는 가장 큰 객체 (힙에 가장 많은 객체를 보유하고있는 객체)에는 DFA [] 및 PredictionContextCache가 포함됩니다.

한 가지주의 할 점은 우리가 2 개의 스레드를 사용하여 구문 분석 작업을 동시에 실행한다는 것입니다. 스레드가 파서 또는 구문 트리 개체를 공유하지는 않지만 ANTLR에서 생성 된 파서가 사용하는 정적 필드가 있음을 알 수 있습니다.이 정적 필드는 멀티 스레드 설정에서 메모리 문제를 일으킬 수 있습니다. 어쨌든 그것은 단지 용의자입니다.

누군가가 "ATNConfig 누적"의 원인이 무엇인지 실마리가 있습니까? 이미 해결책이 있습니까?

답변

1

런타임시 동적 DFA 구성에 ATNConfig 인스턴스가 사용됩니다. 필요한 인스턴스의 수는 문법과 입력의 함수입니다. 사용할 수있는 몇 가지 솔루션이 있습니다.

  1. 응용 프로그램에 제공하는 메모리 용량을 늘리십시오. 문제가 응용 프로그램에 비해 너무 적은 메모리인지 확인하려면 시작 지점으로 -Xmx12g을 시도하십시오.
  2. 각 은 특정 결정을 위해 DFA를 나타내는 DFA 인스턴스에 속합니다. 대부분의 ATNConfig 인스턴스를 포함하는 결정을 알고 있다면 문법의 결정을 단순화하기 위해 작업 할 수 있습니다.
  3. Recognizer.clearDFA()을 호출하여 캐시 된 DFA를 주기적으로 지 웁니다. DFA를 너무 자주 삭제하면 실적에 해가됩니다 (가능한 경우 DFA를 전혀 삭제하지 않음).
  4. ANTLR 4의 "최적화 된"포크를 사용할 수 있습니다. 프로젝트의이 포크는 메모리 풋 프린트를 줄이기 위해 설계 되었기 때문에 복잡한 문법의 성능을 대폭 향상시켜 특정 문법의 속도를 희생합니다.
+0

감사합니다. 샘. 우리는 이제 3 번째 해결책을 따라 문제를 해결했습니다. (우리는 사용하고있는 ANTLR 4.2에서 Reognizer.clearDFA()를 찾지 못했지만, 우리 자신의 clearDFA()가 마술을 만들었습니다.) –

+0

나는 " 대부분의 'ATNConfig' 인스턴스 "와"내 문법을 단순화하는 방법 "에 대해 설명합니다. 관련 문서/자료를 가르쳐 주시겠습니까? –

관련 문제