2
0
mirror of https://github.com/boostorg/mysql.git synced 2026-01-22 05:22:22 +00:00
Files
mysql/tools/ci/ci_util/cmake.py
Anarthal (Rubén Pérez) 303b9f0b59 Added benchmarks against the official drivers
Added one_small_row, one_big_row, many_rows, stmt_params benchmarks against libmysqlclient and libmariadb
Added a CI build to compile and run benchmarks
Added a Python script to run the benchmarks
Refactored the connection_pool benchmark to be use data independent from examples

close #458
2025-04-02 11:32:43 +02:00

293 lines
8.4 KiB
Python

#!/usr/bin/python3
#
# Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
from pathlib import Path
import os
from typing import Optional, Dict
from .common import run, BOOST_ROOT, IS_WINDOWS, mkdir_and_cd
from .db_setup import db_setup, db_setup_bench
from .install_boost import install_boost
from .bench import run_benchmarks
def _cmake_prefix_path(extra_path: Optional[Path] = None) -> str:
prefix_path_args = [extra_path, 'C:\\openssl-64' if IS_WINDOWS else None]
return ';'.join(str(p) for p in prefix_path_args if p is not None)
def _cmake_bool(value: bool) -> str:
return 'ON' if value else 'OFF'
class _CMakeRunner:
def __init__(self, generator: str, build_type: str) -> None:
self._generator = generator
self._build_type = build_type
os.environ['CMAKE_BUILD_PARALLEL_LEVEL'] = '4'
def configure(self, source_dir: Path, binary_dir: Path, variables: Dict[str, str]) -> None:
mkdir_and_cd(binary_dir)
run(
[
'cmake',
'-G',
self._generator,
'-DCMAKE_BUILD_TYPE={}'.format(self._build_type),
] +
['-D{}={}'.format(name, value) for name, value in variables.items()] +
[str(source_dir)]
)
def build(self, target: str) -> None:
run(['cmake', '--build', '.', '--target', target, '--config', self._build_type])
def build_all(self) -> None:
run(['cmake', '--build', '.', '--config', self._build_type])
def ctest(self, no_tests_error: bool = True) -> None:
run(
['ctest', '--output-on-failure'] +
(['--no-tests=error'] if no_tests_error else []) +
['--build-config', self._build_type]
)
# Regular CMake build
def cmake_build(
source_dir: Path,
boost_branch: str,
generator: str,
build_shared_libs: bool,
build_type: str,
cxxstd: str,
server_host: str,
install_test: bool,
) -> None:
# Config
cmake_distro = Path(os.path.expanduser('~')).joinpath('cmake-distro')
test_folder = BOOST_ROOT.joinpath('libs', 'mysql', 'test', 'cmake_test')
runner = _CMakeRunner(generator=generator, build_type=build_type)
# Get Boost
install_boost(
source_dir=source_dir,
boost_branch=boost_branch,
)
# Setup DB
db_setup(source_dir, server_host)
# Build the library, run the tests, and install, as the Boost superproject does
bin_dir = BOOST_ROOT.joinpath('__build')
runner.configure(
source_dir=BOOST_ROOT,
binary_dir=bin_dir,
variables={
'CMAKE_PREFIX_PATH': _cmake_prefix_path(),
'BOOST_INCLUDE_LIBRARIES': 'mysql',
'BUILD_SHARED_LIBS': _cmake_bool(build_shared_libs),
'CMAKE_INSTALL_PREFIX': str(cmake_distro),
'BUILD_TESTING': 'ON',
'CMAKE_INSTALL_MESSAGE': 'NEVER',
'BOOST_MYSQL_INTEGRATION_TESTS': 'ON',
**({ 'CMAKE_CXX_STANDARD': cxxstd } if cxxstd else {})
}
)
runner.build(target='tests')
runner.ctest()
runner.build(target='install')
# The library can be consumed using add_subdirectory
runner.configure(
source_dir=test_folder,
binary_dir=test_folder.joinpath('__build_add_subdirectory'),
variables={
'CMAKE_PREFIX_PATH': _cmake_prefix_path(),
'BOOST_CI_INSTALL_TEST': 'OFF',
'BUILD_SHARED_LIBS': _cmake_bool(build_shared_libs)
}
)
runner.build_all()
runner.ctest()
# The library can be consumed using find_package on a Boost distro built by cmake.
# Generating a modular installation requires CMake 3.13+, so this test can be disabled
# for jobs running old cmake versions
if install_test:
runner.configure(
source_dir=test_folder,
binary_dir=test_folder.joinpath('__build_find_package'),
variables={
'BOOST_CI_INSTALL_TEST': 'ON',
'BUILD_SHARED_LIBS': _cmake_bool(build_shared_libs),
'CMAKE_PREFIX_PATH': _cmake_prefix_path(cmake_distro)
}
)
runner.build_all()
runner.ctest()
# Check that we bail out correctly when no OpenSSL is available
def cmake_noopenssl_build(
source_dir: Path,
boost_branch: str,
generator: str
):
# Config
runner = _CMakeRunner(generator=generator, build_type='Release')
# Get Boost
install_boost(
source_dir=source_dir,
boost_branch=boost_branch,
)
# Build Boost and install. This won't build the library if there is no OpenSSL,
# but shouldn't cause any error.
runner.configure(
source_dir=BOOST_ROOT,
binary_dir=BOOST_ROOT.joinpath('__build'),
variables={
'BOOST_INCLUDE_LIBRARIES': 'mysql',
'BOOST_MYSQL_INTEGRATION_TESTS': 'ON',
'BUILD_TESTING': 'ON',
'CMAKE_INSTALL_MESSAGE': 'NEVER',
}
)
runner.build(target='tests')
runner.ctest(no_tests_error=False)
runner.build(target='install')
# Check that disabling integration tests works
def cmake_nointeg_build(
source_dir: Path,
boost_branch: str,
generator: str
):
# Config
runner = _CMakeRunner(generator=generator, build_type='Release')
# Get Boost
install_boost(
source_dir=source_dir,
boost_branch=boost_branch,
)
# Build the library and run the tests, as the Boost superproject does
bin_dir = BOOST_ROOT.joinpath('__build')
runner.configure(
source_dir=BOOST_ROOT,
binary_dir=bin_dir,
variables={
'CMAKE_PREFIX_PATH': _cmake_prefix_path(),
'BOOST_INCLUDE_LIBRARIES': 'mysql',
'BUILD_TESTING': 'ON'
}
)
runner.build(target='tests')
runner.ctest()
runner.build(target='install')
# Check that CMake can consume a Boost distribution created by b2
def find_package_b2_test(
source_dir: Path,
boost_branch: str,
generator: str
) -> None:
# Config
b2_distro = Path(os.path.expanduser('~')).joinpath('b2-distro')
prefix_path = _cmake_prefix_path(b2_distro)
runner = _CMakeRunner(generator=generator, build_type='Release')
# Get Boost
install_boost(
source_dir=source_dir,
boost_branch=boost_branch,
)
# Generate a b2 Boost distribution
run([
'b2',
'--prefix={}'.format(b2_distro),
'--with-charconv',
'-d0',
'install'
])
# Check that the library can be consumed using find_package on the distro above
test_dir = BOOST_ROOT.joinpath('libs', 'mysql', 'test', 'cmake_b2_test')
runner.configure(
source_dir=test_dir,
binary_dir=test_dir.joinpath('__build'),
variables={
'CMAKE_PREFIX_PATH': prefix_path,
'BUILD_TESTING': 'ON'
}
)
runner.build_all()
runner.ctest()
# Same as the above, but for separate-build mode
test_dir = BOOST_ROOT.joinpath('libs', 'mysql', 'test', 'cmake_b2_separate_compilation_test')
runner.configure(
source_dir=test_dir,
binary_dir=test_dir.joinpath('__build'),
variables={
'CMAKE_PREFIX_PATH': prefix_path,
'BUILD_TESTING': 'ON'
}
)
runner.build_all()
runner.ctest()
def bench_build(
source_dir: Path,
boost_branch: str,
connection_pool_iters: int,
protocol_iters: int,
server_host: str,
) -> None:
# Get Boost
install_boost(
source_dir=source_dir,
boost_branch=boost_branch,
)
# Setup DB
db_setup_bench(source_dir)
# Build the benchmark code
runner = _CMakeRunner(generator='Ninja', build_type='Release')
bin_dir = BOOST_ROOT.joinpath('__build')
runner.configure(
source_dir=BOOST_ROOT,
binary_dir=bin_dir,
variables={
'CMAKE_PREFIX_PATH': '/opt/mysql-8.4.4', # Container's location
'BOOST_INCLUDE_LIBRARIES': 'mysql',
'BOOST_MYSQL_BENCH': 'ON',
'CMAKE_CXX_STANDARD': '23',
}
)
runner.build(target='boost_mysql_bench')
# Run the benchmarks
run_benchmarks(
exe_dir=bin_dir.joinpath('stage', 'bin'),
server_host=server_host,
connection_pool_iters=connection_pool_iters,
protocol_iters=protocol_iters,
)