Commit cef6425bcac678157f58e9eafabb7e63c5831d18
1 parent
da71dc6f
Disable QTC inside the library by default (fixes #714)
This results in measurable performance improvements to packaged binary libqpdf distributions. QTC remains available for library users and is still selectively enabled in CI.
Showing
9 changed files
with
71 additions
and
11 deletions
CMakeLists.txt
| @@ -43,6 +43,9 @@ CMAKE_DEPENDENT_OPTION( | @@ -43,6 +43,9 @@ CMAKE_DEPENDENT_OPTION( | ||
| 43 | GENERATE_AUTO_JOB "Automatically regenerate job files" OFF | 43 | GENERATE_AUTO_JOB "Automatically regenerate job files" OFF |
| 44 | "NOT MAINTAINER_MODE" ON) | 44 | "NOT MAINTAINER_MODE" ON) |
| 45 | CMAKE_DEPENDENT_OPTION( | 45 | CMAKE_DEPENDENT_OPTION( |
| 46 | + ENABLE_QTC "Enable QTC test coverage" OFF | ||
| 47 | + "NOT MAINTAINER_MODE" ON) | ||
| 48 | +CMAKE_DEPENDENT_OPTION( | ||
| 46 | SHOW_FAILED_TEST_OUTPUT "Show qtest output on failure" OFF | 49 | SHOW_FAILED_TEST_OUTPUT "Show qtest output on failure" OFF |
| 47 | "NOT CI_MODE" ON) | 50 | "NOT CI_MODE" ON) |
| 48 | 51 | ||
| @@ -110,8 +113,15 @@ endif() | @@ -110,8 +113,15 @@ endif() | ||
| 110 | 113 | ||
| 111 | add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:POINTERHOLDER_TRANSITION=4>) | 114 | add_compile_definitions($<$<COMPILE_LANGUAGE:CXX>:POINTERHOLDER_TRANSITION=4>) |
| 112 | 115 | ||
| 116 | +if(ENABLE_QTC) | ||
| 117 | + set(ENABLE_QTC_ARG) | ||
| 118 | +else() | ||
| 119 | + add_compile_definitions(QPDF_DISABLE_QTC=1) | ||
| 120 | + set(ENABLE_QTC_ARG --disable-tc) | ||
| 121 | +endif() | ||
| 122 | + | ||
| 113 | enable_testing() | 123 | enable_testing() |
| 114 | -set(RUN_QTEST perl ${qpdf_SOURCE_DIR}/run-qtest) | 124 | +set(RUN_QTEST perl ${qpdf_SOURCE_DIR}/run-qtest ${ENABLE_QTC_ARG}) |
| 115 | 125 | ||
| 116 | if(WIN32) | 126 | if(WIN32) |
| 117 | find_program(COPY_COMMAND NAMES cp copy) | 127 | find_program(COPY_COMMAND NAMES cp copy) |
| @@ -335,6 +345,7 @@ message(STATUS " build shared libraries: ${BUILD_SHARED_LIBS}") | @@ -335,6 +345,7 @@ message(STATUS " build shared libraries: ${BUILD_SHARED_LIBS}") | ||
| 335 | message(STATUS " build static libraries: ${BUILD_STATIC_LIBS}") | 345 | message(STATUS " build static libraries: ${BUILD_STATIC_LIBS}") |
| 336 | message(STATUS " build manual: ${BUILD_DOC}") | 346 | message(STATUS " build manual: ${BUILD_DOC}") |
| 337 | message(STATUS " compiler warnings are errors: ${WERROR}") | 347 | message(STATUS " compiler warnings are errors: ${WERROR}") |
| 348 | +message(STATUS " QTC test coverage: ${ENABLE_QTC}") | ||
| 338 | message(STATUS " system: ${CPACK_SYSTEM_NAME}") | 349 | message(STATUS " system: ${CPACK_SYSTEM_NAME}") |
| 339 | message(STATUS "") | 350 | message(STATUS "") |
| 340 | message(STATUS "*** Options Summary ***") | 351 | message(STATUS "*** Options Summary ***") |
ChangeLog
| 1 | +2022-08-07 Jay Berkenbilt <ejb@ql.org> | ||
| 2 | + | ||
| 3 | + * Add new build configuration option ENABLE_QTC, which is off by | ||
| 4 | + default when not running in MAINTAINER_MODE. When this is off, | ||
| 5 | + QTC coverage calls sprinkled throughout the qpdf source code are | ||
| 6 | + compiled out for increased performance. See "Build Options" in the | ||
| 7 | + manual for a discussion. Fixes #714. | ||
| 8 | + | ||
| 1 | 2022-08-06 Jay Berkenbilt <ejb@ql.org> | 9 | 2022-08-06 Jay Berkenbilt <ejb@ql.org> |
| 2 | 10 | ||
| 3 | * Added by m-holger: QPDF::getObject() method as a simpler form of | 11 | * Added by m-holger: QPDF::getObject() method as a simpler form of |
TODO
| @@ -4,14 +4,9 @@ Next | @@ -4,14 +4,9 @@ Next | ||
| 4 | 4 | ||
| 5 | Before Release: | 5 | Before Release: |
| 6 | 6 | ||
| 7 | -* Improve performance around QTC | ||
| 8 | - * Make it possible to compile it out and deal with it in the tests | ||
| 9 | - * Make sure at least some CI test is run with coverage enabled | ||
| 10 | - * Cache environment variables | ||
| 11 | - * Remove coverage cases for things that are heavily exercised or are | ||
| 12 | - in critical paths | ||
| 13 | * Make ./performance_check usable by other people by having published | 7 | * Make ./performance_check usable by other people by having published |
| 14 | files to use for testing. | 8 | files to use for testing. |
| 9 | + * https://opensource.adobe.com/dc-acrobat-sdk-docs/standards/pdfstandards/pdf/PDF32000_2008.pdf | ||
| 15 | * Evaluate issues tagged with `next` | 10 | * Evaluate issues tagged with `next` |
| 16 | * Stay on top of https://github.com/pikepdf/pikepdf/pull/315 | 11 | * Stay on top of https://github.com/pikepdf/pikepdf/pull/315 |
| 17 | 12 |
build-scripts/test-sanitizers
| @@ -10,7 +10,8 @@ env CFLAGS="-fsanitize=address -fsanitize=undefined" \ | @@ -10,7 +10,8 @@ env CFLAGS="-fsanitize=address -fsanitize=undefined" \ | ||
| 10 | CC=clang CXX=clang++ \ | 10 | CC=clang CXX=clang++ \ |
| 11 | cmake -S . -B build \ | 11 | cmake -S . -B build \ |
| 12 | -DCI_MODE=1 -DBUILD_SHARED_LIBS=0 -DCMAKE_BUILD_TYPE=Debug \ | 12 | -DCI_MODE=1 -DBUILD_SHARED_LIBS=0 -DCMAKE_BUILD_TYPE=Debug \ |
| 13 | - -DREQUIRE_CRYPTO_OPENSSL=1 -DREQUIRE_CRYPTO_GNUTLS=1 | 13 | + -DREQUIRE_CRYPTO_OPENSSL=1 -DREQUIRE_CRYPTO_GNUTLS=1 \ |
| 14 | + -DENABLE_QTC=1 | ||
| 14 | cmake --build build -j$(nproc) -- -k | 15 | cmake --build build -j$(nproc) -- -k |
| 15 | cd build | 16 | cd build |
| 16 | # libtests automatically runs with all crypto providers. | 17 | # libtests automatically runs with all crypto providers. |
include/qpdf/QTC.hh
| @@ -24,10 +24,24 @@ | @@ -24,10 +24,24 @@ | ||
| 24 | 24 | ||
| 25 | #include <qpdf/DLL.h> | 25 | #include <qpdf/DLL.h> |
| 26 | 26 | ||
| 27 | +// Defining QPDF_DISABLE_QTC will effectively compile out any QTC::TC | ||
| 28 | +// calls in any code that includes this file, but QTC will still be | ||
| 29 | +// built into the library. That way, it is possible to build and | ||
| 30 | +// package qpdf with QPDF_DISABLE_QTC while still making QTC::TC | ||
| 31 | +// available to end users. | ||
| 32 | + | ||
| 27 | namespace QTC | 33 | namespace QTC |
| 28 | { | 34 | { |
| 29 | QPDF_DLL | 35 | QPDF_DLL |
| 30 | - void TC(char const* const scope, char const* const ccase, int n = 0); | 36 | + void TC_real(char const* const scope, char const* const ccase, int n = 0); |
| 37 | + | ||
| 38 | + inline void | ||
| 39 | + TC(char const* const scope, char const* const ccase, int n = 0) | ||
| 40 | + { | ||
| 41 | +#ifndef QPDF_DISABLE_QTC | ||
| 42 | + TC_real(scope, ccase, n); | ||
| 43 | +#endif // QPDF_DISABLE_QTC | ||
| 44 | + } | ||
| 31 | }; // namespace QTC | 45 | }; // namespace QTC |
| 32 | 46 | ||
| 33 | #endif // QTC_HH | 47 | #endif // QTC_HH |
libqpdf/QTC.cc
| @@ -13,7 +13,7 @@ tc_active(char const* const scope) | @@ -13,7 +13,7 @@ tc_active(char const* const scope) | ||
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | void | 15 | void |
| 16 | -QTC::TC(char const* const scope, char const* const ccase, int n) | 16 | +QTC::TC_real(char const* const scope, char const* const ccase, int n) |
| 17 | { | 17 | { |
| 18 | static std::map<std::string, bool> active; | 18 | static std::map<std::string, bool> active; |
| 19 | auto is_active = active.find(scope); | 19 | auto is_active = active.find(scope); |
manual/installation.rst
| @@ -257,6 +257,16 @@ CHECK_SIZES | @@ -257,6 +257,16 @@ CHECK_SIZES | ||
| 257 | that ensures an exact match between classes in ``sizes.cc`` and | 257 | that ensures an exact match between classes in ``sizes.cc`` and |
| 258 | classes in the library's public API. This option requires Python 3. | 258 | classes in the library's public API. This option requires Python 3. |
| 259 | 259 | ||
| 260 | +ENABLE_QTC | ||
| 261 | + This is off by default, except in maintainer mode. When off, | ||
| 262 | + ``QTC::TC`` calls are compiled out by having ``QTC::TC`` be an empty | ||
| 263 | + inline function. The underlying ``QTC::TC`` remains in the library, | ||
| 264 | + so it is possible to build and package the qpdf library with | ||
| 265 | + ``ENABLE_QTC`` turned off while still allowing developer code to use | ||
| 266 | + ``QTC::TC`` if desired. If you are modifying qpdf code, it's a good | ||
| 267 | + idea to have this on for more robust automated testing. Otherwise, | ||
| 268 | + there's no reason to have it on. | ||
| 269 | + | ||
| 260 | GENERATE_AUTO_JOB | 270 | GENERATE_AUTO_JOB |
| 261 | Some qpdf source files are automatically generated from | 271 | Some qpdf source files are automatically generated from |
| 262 | :file:`job.yml` and the CLI documentation. If you are adding new | 272 | :file:`job.yml` and the CLI documentation. If you are adding new |
| @@ -297,6 +307,8 @@ MAINTAINER_MODE | @@ -297,6 +307,8 @@ MAINTAINER_MODE | ||
| 297 | 307 | ||
| 298 | - ``CHECK_SIZES`` | 308 | - ``CHECK_SIZES`` |
| 299 | 309 | ||
| 310 | + - ``ENABLE_QTC`` | ||
| 311 | + | ||
| 300 | - ``GENERATE_AUTO_JOB`` | 312 | - ``GENERATE_AUTO_JOB`` |
| 301 | 313 | ||
| 302 | - ``WERROR`` | 314 | - ``WERROR`` |
manual/release-notes.rst
| @@ -7,6 +7,12 @@ For a detailed list of changes, please see the file | @@ -7,6 +7,12 @@ For a detailed list of changes, please see the file | ||
| 7 | :file:`ChangeLog` in the source distribution. | 7 | :file:`ChangeLog` in the source distribution. |
| 8 | 8 | ||
| 9 | 11.0.0 | 9 | 11.0.0 |
| 10 | + - Performance improvements | ||
| 11 | + | ||
| 12 | + - Many performance enhancements have been added. In developer | ||
| 13 | + performance benchmarks, gains on the order of 20% have been | ||
| 14 | + observed. | ||
| 15 | + | ||
| 10 | - Replacement of ``PointerHolder`` with ``std::shared_ptr`` | 16 | - Replacement of ``PointerHolder`` with ``std::shared_ptr`` |
| 11 | 17 | ||
| 12 | - The qpdf-specific ``PointerHolder`` smart pointer implementation | 18 | - The qpdf-specific ``PointerHolder`` smart pointer implementation |
| @@ -231,6 +237,14 @@ For a detailed list of changes, please see the file | @@ -231,6 +237,14 @@ For a detailed list of changes, please see the file | ||
| 231 | - The qpdf source code is now formatted automatically with | 237 | - The qpdf source code is now formatted automatically with |
| 232 | ``clang-format``. See :ref:`code-formatting` for information. | 238 | ``clang-format``. See :ref:`code-formatting` for information. |
| 233 | 239 | ||
| 240 | + - Test coverage with ``QTC`` is enabled during development but | ||
| 241 | + compiled out of distributed qpdf binaries by default. This | ||
| 242 | + results in a significant performance improvement, especially on | ||
| 243 | + Windows. ``QTC::TC`` is still available in the library and is | ||
| 244 | + still usable by end user code even though calls to it made | ||
| 245 | + internally by the library are turned off. Internally, there is | ||
| 246 | + some additional caching to reduce the overhead of repeatedly | ||
| 247 | + reading environment variables at runtime. | ||
| 234 | 248 | ||
| 235 | 10.6.3: March 8, 2022 | 249 | 10.6.3: March 8, 2022 |
| 236 | - Announcement of upcoming change: | 250 | - Announcement of upcoming change: |
run-qtest
| @@ -13,6 +13,7 @@ my $code = undef; | @@ -13,6 +13,7 @@ my $code = undef; | ||
| 13 | my @bin = (); | 13 | my @bin = (); |
| 14 | my $color = undef; | 14 | my $color = undef; |
| 15 | my $show_on_failure = 0; | 15 | my $show_on_failure = 0; |
| 16 | +my $disable_tc = 0; | ||
| 16 | my @tc = (); | 17 | my @tc = (); |
| 17 | 18 | ||
| 18 | if ($^O =~ m/^MSWin32|msys$/) | 19 | if ($^O =~ m/^MSWin32|msys$/) |
| @@ -51,6 +52,10 @@ while (@ARGV) | @@ -51,6 +52,10 @@ while (@ARGV) | ||
| 51 | usage() unless @ARGV; | 52 | usage() unless @ARGV; |
| 52 | $show_on_failure = cmake_bool(shift(@ARGV)); | 53 | $show_on_failure = cmake_bool(shift(@ARGV)); |
| 53 | } | 54 | } |
| 55 | + elsif ($arg eq '--disable-tc') | ||
| 56 | + { | ||
| 57 | + $disable_tc = 1; | ||
| 58 | + } | ||
| 54 | elsif ($arg eq '--tc') | 59 | elsif ($arg eq '--tc') |
| 55 | { | 60 | { |
| 56 | usage() unless @ARGV; | 61 | usage() unless @ARGV; |
| @@ -94,7 +99,7 @@ push(@cmd, | @@ -94,7 +99,7 @@ push(@cmd, | ||
| 94 | "-datadir", "$code/qtest", | 99 | "-datadir", "$code/qtest", |
| 95 | "-junit-suffix", basename($code)); | 100 | "-junit-suffix", basename($code)); |
| 96 | 101 | ||
| 97 | -if (scalar(@tc)) | 102 | +if (scalar(@tc) && (! $disable_tc)) |
| 98 | { | 103 | { |
| 99 | my @tc_srcs = map { | 104 | my @tc_srcs = map { |
| 100 | File::Spec->abs2rel(abs_path($_)) | 105 | File::Spec->abs2rel(abs_path($_)) |