Skip to content

perf(txn): avoid default event callback allocations#25710

Open
VioletQwQ-0 wants to merge 2 commits into
matrixorigin:mainfrom
VioletQwQ-0:perf/txn-default-event-callbacks
Open

perf(txn): avoid default event callback allocations#25710
VioletQwQ-0 wants to merge 2 commits into
matrixorigin:mainfrom
VioletQwQ-0:perf/txn-default-event-callbacks

Conversation

@VioletQwQ-0

Copy link
Copy Markdown
Collaborator

What type of PR is this?

  • API-change
  • BUG
  • Improvement
  • Documentation
  • Feature
  • Test and CI
  • Code Refactoring

Which issue(s) this PR fixes:

issue #25472

What this PR does / why we need it:

Every new transaction currently builds a callback map and slice to install the
two client-owned ClosedEvent callbacks. Under the 1000-VU point-select
workload, AppendEventCallback accounted for about 2.65 GB of allocation in a
30-second profile.

This change stores the immutable default close callbacks once on txnClient.
Transaction operators share them until a caller adds a custom callback, at
which point the operator allocates its own callback map using copy-on-write.
Default callbacks still run before custom callbacks and preserve first-error,
commit, rollback, and restart behavior.

Changes:

  • share immutable client-owned default ClosedEvent callbacks;
  • allocate an operator callback map only when custom callbacks are appended;
  • reset custom callbacks when an operator is reused;
  • add ordering, isolation, close-once, restart, race, and allocation coverage.

Benchmark results on Apple M1 (-benchmem, five runs; allocation values were
stable across all runs):

Benchmark Before After
New + rollback 2544 B / 17 allocs 2000 B / 12 allocs
New + one callback + rollback 2664 B / 19 allocs 2528 B / 17 allocs
New + 14 trace callbacks + rollback 5976 B / 50 allocs 4088 B / 46 allocs

Clean remote point-select A/B/A at 1000 VU:

  • baseline A: 180,508.66 TPS;
  • patched: 188,905.01 TPS;
  • baseline B: 178,377.58 TPS;
  • patched profile run: 186,083.03 TPS versus 180,208.74 TPS control;
  • AppendEventCallback disappeared from the patched allocation profile without
    an equivalent allocation transfer.

Validation:

  • go test -count=1 ./pkg/txn/client
  • go test -race -count=1 ./pkg/txn/client -run '^(TestEventCallbacksDefaultOrderAndFirstError|TestDefaultEventCallbacksCopyOnWrite|TestClientClosedEventDefaultsRunBeforeCustomOnce|TestRestartTxnRestoresDefaultsAndDropsCustomCallbacks|TestClosedEvent|TestCommitClosedEventWhenWaitRunningSQLFails|TestRollbackClosedEventWhenWaitRunningSQLFails)$'
  • go test -count=1 ./pkg/frontend ./pkg/sql/compile
  • go test -run '^$' -bench '^(BenchmarkTxnNewRollback|BenchmarkTxnNewAppendCallbackRollback|BenchmarkTxnNewAppendTraceCallbacksRollback)$' -benchmem -count=5 ./pkg/txn/client

@VioletQwQ-0 VioletQwQ-0 force-pushed the perf/txn-default-event-callbacks branch from 2efbb14 to 90cd31f Compare July 14, 2026 07:18
@matrix-meow matrix-meow added the size/M Denotes a PR that changes [100,499] lines label Jul 14, 2026

@XuPeng-SH XuPeng-SH left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed from lifecycle, concurrency, error-path, compatibility, and performance angles.

The client-owned defaults are initialized before publication and remain immutable; operators share only the read-only container, while the first custom append performs copy-on-write under the operator lock. Default-before-custom ordering, first-error behavior, close-once semantics, RestartTxn cleanup, failed creation, and snapshot/mirror behavior are preserved. The reset path also avoids retaining custom callback backing arrays across operator reuse.

Local validation on 54f0738:

  • pkg/txn/client: count=3 PASS
  • pkg/txn/client under -race: PASS, including the 50x100 concurrent New/Rollback lifecycle test
  • focused callback lifecycle tests under -race count=3: PASS
  • pkg/frontend and pkg/sql/compile compile tests: PASS
  • allocation benchmarks reproduce 2000 B/12 allocs, 2528 B/17 allocs, and 4088 B/46 allocs for the three documented paths

No blocking correctness or robustness issue found. CI is still running and should remain a merge prerequisite.

@VioletQwQ-0 VioletQwQ-0 marked this pull request as ready for review July 15, 2026 10:46
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

…t-callbacks

# Conflicts:
#	pkg/txn/client/client.go
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/enhancement size/M Denotes a PR that changes [100,499] lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants