|
|
|
@ -16,7 +16,7 @@ are old and slow.
|
|
|
|
|
##### MixedBench #####
|
|
|
|
|
This is the so called "Mixed" benchmark, and it executes a representative array of JDBC
|
|
|
|
|
operations in a realistic mix. We think *median* is the number to pay attention to, rather
|
|
|
|
|
than average (which can get skewed). *Median* meaning 50% of the iterations were slower, %50 were faster.
|
|
|
|
|
than average (which can get skewed). *Median* meaning 50% of the iterations were slower, 50% were faster.
|
|
|
|
|
500 threads were started, and the underlying connection pool contained 200 connections. Measurements taken
|
|
|
|
|
in nanoseconds and converted to milliseconds.
|
|
|
|
|
|
|
|
|
@ -87,7 +87,7 @@ you'll find that at an application level there is very little performance impact
|
|
|
|
|
A particularly silly "benchmark" on the BoneCP site starts 500 threads each performing 100 ds.getConnection() /
|
|
|
|
|
connection.close() calls with 0ms delay between. Who does that? The typical "mix" is dozens or hundreds of
|
|
|
|
|
JDBC operations between obtaining the connection and closing it (hence the "MixBench") above. But ok, we can
|
|
|
|
|
run this "benchmark" too (times in *Microseconds*):
|
|
|
|
|
run this "benchmark" too; times in *Microseconds* and measure the per-thread times across all 500 threads.
|
|
|
|
|
|
|
|
|
|
| Pool | Med (μs) | Avg (μs) | Max (μs) |
|
|
|
|
|
| -------- | ---------:| ---------:| ---------:|
|
|
|
|
@ -109,8 +109,8 @@ wrong.
|
|
|
|
|
We're not going to (overly) question the design decisions of other pools, but we will say
|
|
|
|
|
that some other pools seem to implement a lot of "gimmicks" that proportedly improve
|
|
|
|
|
performance. HikariCP achieves high-performance even in pools beyond realistic deployment
|
|
|
|
|
sizes. Either these "gimmicks" are a case of premature optimization or reflective of a poor
|
|
|
|
|
design/lack of understanding of how to leaverage the JVM JIT to full effect.
|
|
|
|
|
sizes. Either these "gimmicks" are a case of premature optimization, poor design, or lack
|
|
|
|
|
of understanding of how to leaverage what the JVM JIT can do for you to full effect.
|
|
|
|
|
|
|
|
|
|
##### ***Missing Knobs*** #####
|
|
|
|
|
In keeping with the *simple is better* or *less is more* design philosophy, some knobs and
|
|
|
|
@ -119,26 +119,13 @@ features are intentionally left out. Here are two, and the rationale.
|
|
|
|
|
**Statement Cache**<br/>
|
|
|
|
|
Most major database JDBC drivers already have a PreparedStatement cache that can be
|
|
|
|
|
configured (Oracle, MySQL, PostgreSQL, Derby, etc). A statement cache in the pool would add
|
|
|
|
|
unneeded weight, no additional functionality, and possibly incorrect behavior...
|
|
|
|
|
unneeded weight and no additional functionality.
|
|
|
|
|
|
|
|
|
|
JDBC drivers have a special relationship with the remote database in that they are directly
|
|
|
|
|
connected and can share internal state that is synchronized with the backend. **It is
|
|
|
|
|
inherently unsafe to cache PreparedStatements outside of the driver.** Why? Again, drivers
|
|
|
|
|
have the advantage of deep knowledge of the the database for which they are designed.
|
|
|
|
|
|
|
|
|
|
Take for example DDL. This is from a real world application we encountered. Data was inserted
|
|
|
|
|
into a table lets call X1. Every night, programatically X1 was renamed to X2, and a new X1 was
|
|
|
|
|
created with identical structure. Basically, the application was "rolling" tables over daily
|
|
|
|
|
(while running). In spite of the structure of X1 being identical after rolling, the database
|
|
|
|
|
considered a PreparedStatement compiled against the old table to be invalid. When the connection
|
|
|
|
|
pool (not HikariCP) statement cache returned one of these statements, the application failed.
|
|
|
|
|
Turning off the cache in the connection pool, and enabling it in the driver fixed the issue. How?
|
|
|
|
|
It is only speculation, but it seems likely that driver in this case checks with the DB to ensure
|
|
|
|
|
the statement is still valid and if not recompiles it transparently. *Just because a connection
|
|
|
|
|
is still valid does not mean that prepared statements previously generated by it are valid.*
|
|
|
|
|
|
|
|
|
|
Regardless of correctness or not it is unnecessary with modern database drivers to implement this
|
|
|
|
|
at the pool level.
|
|
|
|
|
connected and can share internal state that is synchronized with the backend in a way that
|
|
|
|
|
an external cache cannot.
|
|
|
|
|
|
|
|
|
|
It is simply unnecessary with modern database drivers to implement this at the pool level.
|
|
|
|
|
|
|
|
|
|
**Log Statement Text / Slow Query Logging**<br/>
|
|
|
|
|
Like Statement caching, most major database vendors support statement logging through
|
|
|
|
@ -146,11 +133,12 @@ properties of their own driver. This includes Oracle, MySQL, Derby, MSSQL, and
|
|
|
|
|
consider this a "development-time" feature. For those few databases that do not support it,
|
|
|
|
|
[jdbcdslog-exp](https://code.google.com/p/jdbcdslog-exp/) is a good option. It also provides
|
|
|
|
|
some nice additional stuff like timing, logging slow queries only, and PreparedStatement bound
|
|
|
|
|
parameter logging.
|
|
|
|
|
parameter logging. Great stuff during development, and even pre-Production.
|
|
|
|
|
|
|
|
|
|
Trust us, you don't want this feature -- even disabled -- in a production connection pool. If
|
|
|
|
|
we can figure out how to do it without impacting performance we will, but *we consider even
|
|
|
|
|
checking a additional boolean as inducing too much overhead into your queries and results.*
|
|
|
|
|
we can figure out how to do it without impacting performance we *might* implement it, but *we
|
|
|
|
|
consider even checking a additional boolean as inducing too much overhead into your queries and
|
|
|
|
|
results.*
|
|
|
|
|
|
|
|
|
|
----------------------------------------------------
|
|
|
|
|
|
|
|
|
@ -159,7 +147,8 @@ The following is the various properties that can be configured in the pool, thei
|
|
|
|
|
and their defaults. **HikariCP uses milliseconds for *all* time values, be careful.**
|
|
|
|
|
|
|
|
|
|
Rather than coming out of the box with almost nothing configured, HikariCP comes with *sane*
|
|
|
|
|
defaults that let a great many deployments run without any additional tweaking.
|
|
|
|
|
defaults that let a great many deployments run without any additional tweaking (except for
|
|
|
|
|
the DataSource and connection URL).
|
|
|
|
|
|
|
|
|
|
``acquireIncrement``<br/>
|
|
|
|
|
This property controls the maximum number of connections that are acquired at one time, with
|
|
|
|
|