perf(logging): eliminate hot-path allocations - #60
Merged
Conversation
AddSource가 켜진 formatter는 record마다 *slog.Source를 두 번 할당하고 slog이 그것을 3-attr group으로 전개하면서 또 할당했다. alloc 프로파일에서 이 세 지점이 실제 출력 경로 할당의 약 80%를 차지했다. shortenSource가 group 대신 "dir/file.go:line" 한 문자열을 돌려주도록 바꿔 Source 재할당과 group 전개를 함께 제거한다. PC 0 record는 빈 Source를 낳으므로 빈 Attr을 돌려주는 가드를 둔다. 이 가드가 없으면 ":0"이 실려, 지금까지 slog이 통째로 생략하던 합성 source가 async summary record에 되살아난다. JSON 출력 계약이 바뀐다. source가 객체에서 문자열이 되고 function 필드가 빠진다. 절대 경로 미노출과 line 보존은 그대로다.
LogAndWrapError와 LogWarnWithErrorAttrs는 ErrorAttrs 결과와 호출자 attr을 mergedAttrs로 합쳐 넘겼다. log가 방금 없앤 병합 slice가 소비자들이 실제로 쓰는 진입점에 그대로 남아 있었다. logWith가 두 attr 묶음을 따로 받아 Record에 직접 넣도록 하고, runtime.Callers skip을 상수로 분리한다. helper 경유 경로의 source가 helper 본문이 아니라 실제 호출 지점을 가리키게 되는 것이 부수 효과다. alloc 상한은 race 빌드에서 값이 달라지므로 promptguard와 같은 !race 파일로 분리하고, CI가 race 없는 별도 스텝에서 돌리도록 확장한다. 이 스텝이 없으면 새 상한은 CI에서 아예 실행되지 않는다.
shortenSource와 skip 상수 블록에서 시그니처와 아래 주석이 이미 말해주는 설명을 덜어낸다. PC 0 가드와 프레임 체인처럼 코드로 확인할 수 없는 설명은 그대로 둔다.
park285
marked this pull request as ready for review
August 11, 2026 08:26
Owner
Author
|
소비자 3개 저장소를 이 브랜치의
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
배경
chat-bot-go-kakao,hololive-bot,twentyq-bot이 공통으로 사용하는pkg/logging의 enabled-log 경로를 프로파일링했습니다. 실제 비용의 핵심은slog의 primitive attr 처리보다 다음 공통 wrapper 비용이었습니다.context.Value호출마다 interface boxing allocation을 발생ContextAttrs와 event/context/user attrs 병합을 위한 임시 slice 2개 생성Enabled호출 후Logger.LogAttrs가 다시Enabled를 호출slog.Group도 sanitizer가 매번 새 group/slice로 재구축변경 사항
Log계열이 level gate 뒤slog.Record를 직접 구성하고 handler에 전달하도록 변경Enabled는 정확히 한 번만 호출Record의 inline attr 저장소를 사용해 일반적인 5개 이하 attr 경로에서 임시 slice 제거runtime.Callers로 기존AddSource계약을 유지하고 direct wrapper의 실제 호출 위치 기록Enabled호출 횟수, source caller, key 정규화, sanitizer copy-on-write 동작을 회귀 테스트로 고정측정 결과
격리된
pkg/logginghot path를 로컬 Go 1.23.2, Linux/amd64에서 반복 측정했습니다. 0-allocation 계약은 별도로 Go 1.26.5 CI에서도 통과했습니다.동기 파일 lane, source 값 복사, redaction 정책은 내구성·호출자 불변성·보안 의미가 있으므로 완화하지 않았습니다.
호환성
slog.Loggerlogging API 동작 유지ContextAttrs순서 유지: runtime → component → request_id → job_idWithAttrs/WithGroupsanitizer 동작 유지검증
로컬에서 현재 package 소스를 재구성해 다음을 통과시켰습니다.
go test ./pkg/logginggo vet ./pkg/logginggo test -race -count=1 ./pkg/loggingGitHub Actions CI #388도 Go 1.26.5에서 모두 통과했습니다.
gofmtgo vet ./...golangci-lintgo test -race -count=1 ./...