Skip to content

[WP7] Mapper hot-path allocation: eager AST build + always-on DISTINCT #201

Description

@shihyuho

此內容由 AI 產生(specification-mapper 全庫審查 2026-07-16.執行圖)。

Work package WP7 · findings: PERF-03, PERF-04 · worst severity: medium · effort: M

From the 2026-07-16 whole-codebase review of branch jakarta (snapshot 7de4a33; modules mapper/ + starter/). Every finding below is CONFIRMED by independent adversarial verification. File:line coordinates are from the snapshot and may have drifted.

Findings

PERF-03 — AST debug tree is fully built and stringified on every toSpec call even when DEBUG is off (performance, medium)

  • File: mapper/src/main/java/tw/com/softleader/data/jpa/spec/SpecMapper.java:89
  • Evidence: the debug AST is constructed and its recursive toString is materialized unconditionally, then discarded when the logger's DEBUG level is disabled — pure allocation/CPU on every mapping call on the hot path.

PERF-04 — distinct=true default forces SELECT DISTINCT on every joined query (performance, low)

  • File: mapper/src/main/java/tw/com/softleader/data/jpa/spec/annotation/Join.java:72
  • Evidence: the annotation defaults distinct to true, so even to-one joins (which cannot multiply rows) emit SELECT DISTINCT, adding a needless sort/dedup.

Plan

  1. PERF-03: gate the AST build+stringify behind log.isDebugEnabled() (guard both the tree construction and the toString), so the allocation only happens when DEBUG logging is active.
  2. PERF-04: keep the distinct=true default (changing it is a breaking behavior change), but document that to-one joins can set distinct=false, and — as a non-breaking optimization — skip emitting DISTINCT when no collection (to-many) join participates in the query, if that can be determined safely. (If it cannot be determined safely without risking correctness, restrict this finding to the documentation change and note it.)

Acceptance criteria

  • With DEBUG disabled, toSpec no longer builds or stringifies the AST tree (verifiable by a test asserting the AST writer is not invoked, or a micro-benchmark note).
  • Existing distinct/join behavior is unchanged for to-many joins; make test green.

Metadata

Metadata

Assignees

Labels

status: ready-for-agentFully specified and ready for an autonomous AFK agent to implementtype: enhancementNew feature or request

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions