2012-01-22 4 views
3

아래 첫 번째 코드 스 니펫부터 시작하여 줄 목록을 검색하고 각 줄의 모든 키워드 (각 줄에서 식별 됨)를 소문자로 변환했습니다. 약 800 줄의 내 테스트 목록의 경우 키워드 목록이 100 개 이하인 경우 전체 줄 목록에 대한 키워드 대체가 1 초 미만입니다. 목록을 101 개 항목 이상으로 확장하면 처리 시간이 9 초 이상으로 늘어납니다.정규 표현식 실행 시간이 100 번째 패턴 이후에 급격하게 증가합니다.

두 번째 코드 단편 (키워드 목록의 모든 패턴이 컴파일되는 곳)을 사용하면 총 처리 시간이 1 초 미만으로 줄어 듭니다.

컴파일되지 않은 대체 검색의 처리 시간이 입력 행마다 검색된 항목의 수에 너무 민감한 이유를 알고있는 사람이 있습니까? 나는 그것이 100 개의 키워드 후에 너무 예리하게 뛰는 것이 놀랍다.

조각 # 1

for line in lines_in: 
    for keyword in keywords: 
     rawstring = r'\b' + keyword + r'\b' 
     line = re.sub(rawstring, keyword, line, 0, re.IGNORECASE) 

조각 번호가 re.compile 2

for i in range(len(keywords)): 
    re_pattern = re.compile(r'\b' + keywords[i] + r'\b', re.IGNORECASE) 
    pattern.append(re_pattern) 

for line in lines_in: 
    for i in range(len(keywords)): 
     line = pattern[i].sub(keywords[i], line, 0) 

답변

6

이것은 파이썬이 컴파일 된 정규식을 내부적으로 캐시하고 그 내부 캐시의 크기가 100이기 때문에 발생합니다 (라인 227에서 here으로 볼 수 있습니다.) 또한 246-247 행에서 캐시가 끝났을 때 최대 크기는. 이것은 본질적으로 루프를 반복 할 때마다 캐시를 ​​불어 모든 100 개 + 정규 표현식에 다시 컴파일하는 원인이되는 것을 의미한다.

성능이 돌아 오히려 더 진보 된 캐시 무효화 알고리즘을 사용하는 것보다 지워집니다 성공적으로 컴파일 된 정규 표현식을 유지하기 위해 내부 캐시에 의존하지 않기 때문에 두 번째 예제에서 "normal"로 변경하십시오.

+0

이유를 지적 해 주셔서 감사합니다. 작동하도록 설계된 것처럼 항상 작동하는 것이 좋습니다. – smith7959

0

Documentation는 말한다 :

참고 가장 최근 패턴의 컴파일 된 버전 다시 전달 .match(), re.search() 또는 re.compile()이 캐시되므로 에서 onl을 사용하는 프로그램 y 정규식을 컴파일 할 때 한 번에 몇 가지 정규식을 사용하면 걱정할 필요가 없습니다.

이제 캐시의 크기를 알 것 같습니다.

+0

@ grncdr 이유를 지적 해 주셔서 감사합니다. 항상 설계된 것처럼 작동하는 것이 좋습니다. – smith7959

1

이것은 re 모듈 내에서 컴파일 된 정규 표현식의 내부 캐싱 때문입니다. 코드에서 regexp를 많이 사용하고 있다면 re.match 나 re.search를 직접 사용하지 말고 사전 컴파일하면 훨씬 빠릅니다.

내부 리 캐시는 고성능이 아닌 일반적인 간단한 사용 사례에서 편리한 속도를 제공합니다.