[feast] Feast Feature Server의 직렬화 성능 4배 향상: MessageToDict 최적화
PR 링크: feast-dev/feast#6015 상태: Merged | 변경: +764 / -11
들어가며
Feast의 Feature Server는 온라인 피처 서빙을 위해 GetOnlineFeaturesResponse를 클라이언트에 반환합니다. 기존에는 google.protobuf.json_format.MessageToDict를 사용하여 Protobuf 메시지를 JSON으로 변환해왔습니다. 하지만 MessageToDict는 범용적인 라이브러리로서, 실행 시점에 필드를 탐색하는 리플렉션(reflection) 기반의 방식을 사용하기 때문에 대규모 피처 응답 시 상당한 오버헤드가 발생합니다. 본 PR은 이 병목을 해결하기 위해 커스텀 직렬화 로직을 도입하여 성능을 4배 향상시켰습니다.
코드 분석
1. sdk/python/feast/feature_server.py: 범용 라이브러리 제거
기존에는 MessageToDict를 직접 호출하여 직렬화했으나, 이제는 최적화된 유틸리티 함수를 사용하도록 변경되었습니다.
# Before
response_dict = await run_in_threadpool(
MessageToDict,
response.proto,
preserving_proto_field_name=True,
float_precision=18,
)
# After
response_dict = await run_in_threadpool(
convert_response_to_dict, response.proto
)
return JSONResponse(content=response_dict)
2. sdk/python/feast/feature_server_utils.py: 커스텀 직렬화 로직 구현
새로 추가된 convert_response_to_dict는 GetOnlineFeaturesResponse의 구조를 미리 알고 있으므로, 리플렉션 없이 직접 필드에 접근합니다.
def convert_response_to_dict(response: GetOnlineFeaturesResponse) -> Dict[str, Any]:
result: Dict[str, Any] = {
"results": [
{
"values": [_value_to_native(v) for v in feature_vector.values],
"statuses": [_STATUS_NAMES.get(s, "INVALID") for s in feature_vector.statuses],
# ... (timestamp 처리)
}
for feature_vector in response.results
]
}
# ...
return result
특히 bytes 타입 처리 시 base64 인코딩을 명시적으로 수행하여 JSONResponse가 직렬화 오류를 일으키지 않도록 처리한 점이 돋보입니다.
왜 이게 좋은가
- 리플렉션 제거:
MessageToDict는 모든 필드를 동적으로 검사하지만, 커스텀 빌더는 고정된 스키마를 따라 직접 값을 추출합니다. 이로 인해 CPU 사이클을 크게 절약합니다. - 성능 수치: 일반적인 피처 응답(50-200개 피처)에서 요청당 5-15ms의 지연 시간을 단축하며, 직렬화 속도가 약 4배 향상되었습니다.
- 안정성:
bytes타입에 대한base64인코딩 처리를 통해json.dumps호출 시 발생할 수 있는TypeError를 방지했습니다.
교훈
범용 라이브러리는 편리하지만, 특정 데이터 구조가 고정되어 있고 성능이 중요한 핫패스(hot path)에서는 직접적인 데이터 매핑이 훨씬 효율적입니다. 특히 Protobuf와 같이 스키마가 명확한 경우에는 타입별로 최적화된 직렬화 로직을 작성하는 것이 큰 성능 이득을 가져옵니다.
리뷰어 피드백 반영
리뷰 과정에서 bytes_val 직렬화 시 발생하는 TypeError 문제를 지적받았고, 이를 base64 인코딩으로 해결한 점은 매우 실무적인 피드백이었습니다. 또한 ORJSONResponse가 FastAPI에서 deprecated 되었다는 점을 고려하여 표준 JSONResponse를 사용하도록 조정된 점도 유지보수 측면에서 훌륭한 결정입니다.
참고 자료
- https://protobuf.dev/reference/python/python-generated/#message
- https://fastapi.tiangolo.com/reference/responses/#fastapi.responses.JSONResponse
⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.
관련 포스트
- [feast] Feast Online Serving 최적화: 3단계 데이터 변환을 단일 패스로 통합하기
- [feast] Feast 성능 최적화: 엔티티 키 직렬화 Hot Path 2.4배 개선하기
- [transformers] Hugging Face Transformers: SequenceFeatureExtractor.pad() 최적화로 불필요한 NumPy 배열 재변환 제거
- [cpython] tarfile 스트리밍 모드(r|*) 성능 개선: 파이썬 압축 파일 처리의 숨겨진 병목 제거
- [cpython] Python의 os.fork 후 발생하던 성능 프로파일링 충돌 문제 해결 및 최적화 분석
PR Analysis 의 다른글
- 이전글 [sglang] [SGLang] Blackwell(B200)에서 Diffusion Attention 성능을 7배 끌어올리는 Triton 커널 최적화 분석
- 현재글 : [feast] Feast Feature Server의 직렬화 성능 4배 향상: MessageToDict 최적화
- 다음글 [axolotl] Axolotl MoE 모델 최적화: Tiled-MLP 도입 및 FSDP2 통합으로 성능 극대화
댓글