@ -50,15 +50,17 @@ JVM benchmark was run with: ``-server -XX:+UseParallelGC -Xss256k``.
##### In Summary #####
200 threads ran 60,702,000 JDBC operations each, HikariCP did this in a median of *230ms* per thread.
------------------------------
#### (In)correctness ####
Sometimes "correctness" is objective, and sometimes it is subjective. One example of
objective *incorrectness* in BoneCP is ``ResultSet`` handling. Every connection pool needs to
wrap the underlying ``Connection``, ``Statement``, ``CallableStatement``, and
``PreparedStatement``, and ``ResultSet`` classes. However, BoneCP does not wrap ResultSet.
``ResultSet`` *must* be wrapped, because ResultSet.getStatement() *must* return the **wrapped**
``Statement`` that generated it, not the **underlying** ``Statement``. Hibernate 4.3 for one
relies on this semantic.
``ResultSet`` *must* be wrapped, because ``ResultSet.getStatement()``*must* return the
**wrapped** ``Statement`` that generated it, not the **underlying** ``Statement``.
Hibernate 4.3 for one relies on this semantic.
If BoneCP were to wrap ResultSet, which comprises 20,100,000 of the 60,702,000 operations in
MixedBench, its performance numbers would be far poorer. Also take note that HikariCP *does*
@ -75,7 +77,7 @@ application was running, you certainly didn't do it with BoneCP.
Over on the BoneCP site, you can find a comparison of BoneCP vs. DBCP and C3P0. DBCP and C3P0,
as poor as they are, at least are performing aliveness tests before dispatching connections.
So, it's not really a fair comparison. HikariCP supports the JDBC4 ``Connection.isValid()``
API, which for many drivers provides a non-query based aliveness test.
API, which for many drivers provides a fast non-query based aliveness test.
A particularly silly "benchmark" on the BoneCP site starts 500 threads each performing 100
DataSource.getConnection() / connection.close() calls with 0ms delay between. Who does that?
@ -90,43 +92,94 @@ Microseconds):
The times are per-thread reflecting 100 getConnection()/close() operations with no wait between.
------------------------------------------
#### Knobs ####
Where are all the knobs? You know, the ones used to tune and tweak the connection pool?
HikariCP has plenty of "knobs" as you can see in the configuration section below, but
comparatively less than some other pools. This was a design decision, not lack of development resources or foresight.
Where are all the knobs? HikariCP has plenty of "knobs" as you can see in the configuration section below, but comparatively less than some other pools. This is a design philosophy.
Configuring a connection pool, even for a large production environment, is not rocket science.
The HikariCP design semantic is minimalist. You probably need to configure the idle timeout
for connections in the pool, but do you really need to configure how often the pool is swept
to retire them? You might *think* you do, but if you do you're probably doing something
wrong.
##### ***Missing Knobs*** #####
Some knobs and features were intentionally left out. Here are the reasons.
In keeping with the *simple is better* or *less is more* design philosophy, some knobs and features are intentionally left out. Here are some, and the reasons.
**Statement Cache**<br/>
Many (most?) major database JDBC drivers already have a PreparedStatement cache that can be
configured (Oracle, MySQL, PostgreSQL, Derby, etc). A cache in the pool would add unneeded
weight, no additional functionality, and possibly incorrect behavior...
configured (Oracle, MySQL, PostgreSQL, Derby, etc). A statement cache in the pool would add
unneeded weight, no additional functionality, and possibly incorrect behavior...
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 a special relationship with the database.
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 I encountered (using BoneCP btw).
Take for example DDL. This is from a real world application we encountered (using BoneCP btw).
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 (probably there were some kind of UUID contained within). When the statement pool
invalid (probably there was some kind of UUID contained within). When the statement pool
returned one of these statements, the application blew up. 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.
Regardless of correctness or not (I'm sure it varies by DB vendor), it is unnecessary with
modern databases.
modern database drivers to implement this at the pool level.
**Log Statement Text**<br/>
Like Statement caching, most major database vendors support statement logging through
properties of their own driver. This includes Oracle, MySQL, Derby, MSSQL. For those few
databases that do not support it, [log4jdbc](https://code.google.com/p/log4jdbc/) is a good option. Actually *log4jdbc* provides some nice additional stuff like various timings, and
PreparedStatement bound parameter logging.
properties of their own driver. This includes Oracle, MySQL, Derby, MSSQL. We consider this
a "development-time" feature. For those few databases that do not support it,
[log4jdbc](https://code.google.com/p/log4jdbc/) is a good option. Actually *log4jdbc* provides some nice additional stuff like various timings, and PreparedStatement bound parameter logging.
HikariCP is focused (primarily) on performance in a Production environment, so it is doubtful
that we will ever implement this feature given inherent driver support and alternative
that we will ever implement this kind of feature given inherent driver support and alternative