Skip to content

TFB updates test: severe performance regression with JdbcTransactionExposedTransactionProvider, exhaustive analysis, and fix (rollback releases resources) #109

@ShreckYe

Description

@ShreckYe

This issue is drafted by Copilot.

Root Cause and Fix

A severe performance regression in the TFB updates test was traced to use of JdbcTransactionExposedTransactionProvider for statement preparation (introduced in PR #101), where a single JDBC transaction was shared across SQL preparations. While this approach was intended to optimize by reducing transaction creation overhead, it instead led to extreme throughput drops in real-world concurrent benchmarks: 90% slower on my device (2200 req/s for JDBC provider vs 27000 - 28000 req/s for Database provider).

Fix

Explicitly rolling back the shared transaction (jdbcTransaction.rollback()) releases held resources and resolves all contention, restoring expected throughput and behavior.


Investigation Path & Related Experiments (Cross Repo)

(1) Initial Analysis and Benchmarks

(2) Possible Causes Considered & Eliminated

  • ThreadLocal Serialization: Hypothesized overhead from withThreadLocalTransaction serializing parallel calls. Flame graphs showed this as a hotspot (blocking), but further prepareBatchSqlAndArgTuples analysis confirmed the batch SQL preparation logic is fully synchronous, ruling out interleaving/thread contention at the function level.
  • Internal State Contention: Explored whether underlying properties of JdbcTransaction or Database held shared resources.
  • Deadlocks: Considered possibility of deadlocks due to held JDBC transaction locks or connection state interfering on parallel event loops. No deadlocks were observed, only serialization/blocking.
  • Memory Contention: The fact that SQL preparation throughput does not scale with cores lead me into thinking about this.

(3) Extensive Profiling and Experimentation

(4) Final Finding & Fix

  • Analysis: The single shared JDBC transaction, even if used only for SQL statement preparation, holds JDBC connection state, which blocks parallel preparation and execution under Vert.x event loops during high load.
  • Fix: Calling jdbcTransaction.rollback() releases all held resources, removes blocking, and restores full parallelization. After rollback, benchmark results matched expectations, with throughput up from 2200 req/s to 27000 - 29000 req/s.

(5) Research Provenance


Key Takeaways

  • Always roll back JDBC transactions after statement preparation.

Confirmed fixed with jdbcTransaction.rollback().

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions