비교할 문제
예외 처리 성능에서 확인할 질문은 예외가 드문 경로와 자주 발생하는 입력에서 try/except와 명시적 검사는 어떻게 달라지는가입니다. 없는 key를 같은 값으로 처리하고 정상·오류 결과를 동일하게 유지합니다. None이 유효한 값이면 sentinel을 사용해 의미를 맞춥니다. 결과값, 순서, 오류 처리와 부수 효과가 다르면 같은 성능 비교가 아닙니다. 먼저 두 후보가 같은 일을 하는지 작은 입력으로 확인합니다.
원인 분석과 재현
예외가 실제로 발생할 때 stack 생성과 unwinding 비용이 있으므로 흔한 정상 분기를 예외로 표현할지는 workload에서 측정해야 합니다.
miss 0%·1%·50%, key 100개·10만 개에서 CPython version별 시간과 allocation을 측정합니다. runtime version, 운영체제, CPU와 memory 제한도 결과와 함께 기록합니다.
비교 질문은 예외가 드문 경로와 자주 발생하는 입력에서 try/except와 명시적 검사는 어떻게 달라지는가입니다.
| 후보 | 유리한 조건 | 함께 치르는 비용 |
|---|---|---|
| try/except | 실패가 정말 예외적이고 성공 경로가 단순 | 예외가 잦으면 object·traceback 생성 비용이 반복 |
| dict.get / membership | missing이 정상적인 분기 | 조회 중복이나 sentinel 계약을 주의 |
| 사전 validation | 외부 입력 오류를 한 경계에서 모아 안내 | 검사와 실제 사용 사이 경쟁·중복 계산 가능 |
from statistics import median
from timeit import repeat
setup = '''
data = {str(i): i for i in range(1_000)}
keys = [str(i % 1_100) for i in range(100_000)]
def with_exception():
total = 0
for key in keys:
try: total += data[key]
except KeyError: pass
return total
def with_get():
total = 0
for key in keys:
value = data.get(key)
if value is not None: total += value
return total
'''
for name in ("with_exception", "with_get"):
samples = repeat(f"result = {name}()", setup=setup, number=10, repeat=7)
print(name, {"min": min(samples), "median": median(samples)})
해결 방안과 판정
timeit.repeat() 결과 전체를 보관하고, 작은 코드 조각의 하한을 볼 때는 공식 문서가 안내하는 최솟값도 함께 확인합니다. 서비스 지연을 재는 경우에는 median과 p95를 별도로 기록합니다. CPU time, allocation, RSS·heap, GC, I/O 중 이 작업에 직접 관련된 지표만 선택합니다. Python의 예외는 올바른 오류 모델을 먼저 따릅니다. hot path에서 miss가 흔하고 profile로 확인됐을 때만 명시적 분기를 비교합니다.
차이가 반복 실행의 흔들림보다 작다면 더 단순하고 읽기 쉬운 구현을 선택합니다. 차이가 충분히 크더라도 실제 요청 전체의 지연과 자원 사용이 개선되는지 확인한 뒤 적용합니다.
공식 문서와 적용 범위
문서의 기본값과 동작은 version에 따라 달라질 수 있습니다. 현재 Python 구현과 version, dependency, 입력 크기와 실행 환경에서 다시 확인합니다.