...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
MySQL and MariaDB ship with official C connectors: libmysqlclient and libmariadb. Both implement the client/server protocol, as Boost.MySQL does. The question then arises: is Boost.MySQL as fast as the official drivers?
![]() |
Note |
---|---|
TL;DR: Boost.MySQL is as fast as the official C APIs, and may be faster under some circumstances. |
These benchmarks focus on the speed of the protocol implementation, in an attempt to answer the question above. This should take into account, at least, (de)serialization and buffering. It shouldn't take into account features unique to Boost.MySQL, like the static interface or connection pooling.
Both libmysqlclient and libmariadb offer a connection type, similar to any_connection
,
with both sync and async primitives. Sync functions are similar to the ones
in Boost.MySQL (although C-flavored). Async functions are much lower-level,
and often require either integration into a framework (like Asio or libuv)
or writing poll
/epoll
code by hand. None of these options
is trivial. Additionally, sync functions have less overhead, so they're best
suited to answer our question. For this reason, we only
use sync functions in the benchmarks.
The benchmarks use prepared statements only.
The official drivers handle text queries (issued by mysql_real_query
)
and prepared statements differently. Rows generated by text queries are returned
as strings, and need to be parsed by the user. Boost.MySQL handles this parsing
automatically for you. For this reason, comparing text queries doesn't make
much sense. Prepared statements are handled similarly, and are better suited
for big rows and datasets.
All tests use a real database. Neither Boost.MySQL nor the official C clients expose (de)serialization functions. Buffering and optimizing the number of system calls is also critical for efficiency, and can only be measured with real communication. The downside is that database processing introduces delays, and might end up being the bottleneck.
The benchmarks try to minimize communication overhead by using UNIX sockets.
Benchmark source code can be found in the bench/ folder of the repo. The following benchmarks are performed:
any_connection::execute
.
any_connection::start_execution
,
which allows zero-copying.
any_connection::start_execution
because the resultset size is big.
Benchmark conditions:
BOOST_MYSQL_SEPARATE_COMPILATION
),
since it's slightly faster.
The three libraries exhibit a similar level of performance, which is expected from a correctly implemented binary protocol. Boost.MySQL outperforms libmysqlclient in the single row benchmarks, and is on par with libmariadb. Differences in the other benchmarks don't appear to be statistically significant.
During these benchmarks, some potential performance improvement areas have been identified. See [https://github.com/boostorg/mysql/issues/458 this issue] for details.
Remember that protocol is just one piece to the whole puzzle. Correctly using
features like connection_pool
,
with_params
,
multi-function operations and multi-queries can make a huge performance difference
in your application. Never assume anything and always measure!
Acknowledgments: thanks LowLevelMahn for proposing the benchmarks.