Simple, fast, accurate single-header microbenchmarking functionality for C++11/14/17/20

ankerl::nanobench

ankerl::nanobench logo

Release GitHub license Travis CI Build Status Appveyor Build Status Join the chat at https://gitter.im/nanobench/community

ankerl::nanobench is a platform independent microbenchmarking library for C++11/14/17/20.

5.0) { d -= 5.0; } ankerl::nanobench::doNotOptimizeAway(d); }); } ">
#define ANKERL_NANOBENCH_IMPLEMENT
#include <nanobench.h>

int main() {
    double d = 1.0;
    ankerl::nanobench::Bench().run("some double ops", [&] {
        d += 1.0 / d;
        if (d > 5.0) {
            d -= 5.0;
        }
        ankerl::nanobench::doNotOptimizeAway(d);
    });
}

The whole executable runs for ~60ms and prints

|               ns/op |                op/s |    err% |          ins/op |          cyc/op |    IPC |         bra/op |   miss% |     total | benchmark
|--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:----------
|                7.52 |      132,948,239.79 |    1.1% |            6.65 |           24.07 |  0.276 |           1.00 |    8.9% |      0.00 | `some double ops`

Which github renders as

ns/op op/s err% ins/op cyc/op IPC bra/op miss% total benchmark
7.52 132,948,239.79 1.1% 6.65 24.07 0.276 1.00 8.9% 0.00 some double ops

The benchmarked code takes 7.52 nanoseconds to run, so ~133 million times per seconds. Measurements fluctuate by 1.1%. On average 6.65 instructions are executed in 24.07 CPU cycles, resulting in 0.276 instructions per cycle. A single branch is in the code, which branch prediction missed in 8.9% of the cases. Total runtime of the benchmark with the name some double ops is 0.00, so just a few milliseconds.

Design Goals

Documentation

Extensive documentation is available.

More

  • Code of Conduct - Contributor Covenant Code of Conduct
  • I need a better logo. Currently I use a small bench. Nanobench. Ha ha.
Owner
Martin Leitner-Ankerl
s/Martin Ankerl/Martin Leitner-Ankerl/
Martin Leitner-Ankerl
Comments
  • Idea? Timing only particular sections of code

    Idea? Timing only particular sections of code

    Recently I've been testing a few different sorting algorithms, the rough setup has a preallocated block of memory filled with random data. However that means for each benchmark run after a sort, I have to scramble or generate more random data, and this code is shared between all the benchmarks. Which roughly translates to a benchmark which is really measuring the cost of those two things together, rather than just the sorting algorithm on its own. Presumably the sort algorithm overwhelms the cost of generating new data, but it's difficult to gauge exactly how much of a cost generating data is without running a benchmark with that part on it's own.

    It seems almost as if with a few edits to add additional callbacks it'd be possible to add timings or even ignore parts of code which are not really part of the test. If a second callback doesn't make the code more unstable / slow to test it'd probably be a handy tool for cases like this.

    Might look like:

        template <typename Start, typename Op, typename End>
        ANKERL_NANOBENCH(NOINLINE)
        Bench& run(std::string const& benchmarkName, Start&& start, Op&& op, End&& end);
    
  • Use steady_clock instead of high_resolution_clock

    Use steady_clock instead of high_resolution_clock

    std::high_resolution_clock is nothing but an alias to either system or steady clock, which means it can differ from one std library implementation to another. libstdc++ for example will use the realtime clock which is less precise than the monotone clock (steady). An interesting resource about clocks speed and precision is available at https://gitlab.com/chriscox/CppPerformanceBenchmarks/-/wikis/ClockTimeAnalysis . Howard Hinnant (who wrote the scpecification) also says it was a mistake to even standardize it (https://youtu.be/adSAN282YIw?t=4612). Google benchmark uses high_resolution_clock only if high_resolution_clock::is_steady() returns true, otherwise uses steady_clock.

    Ideally it might be interesting to provide our own clock using clock_gettime, QueryPerformanceCounter directly. An alternative would be to use rdtsc directly but there are issues with it on some CPUs, and it is x86 only.

  • Add support for custom information per benchmark run

    Add support for custom information per benchmark run

    • Set via bench.context("name", "value")
    • Render/access via {{context(name)}}
    • Rendering variables without a value ~~produce empty output (for that variable)~~ throws an exception
    • Values persist to subsequent calls to Bench::run; my use case assumes that all variables are needed for all runs
    • Reset via bench.clearContext()

    Unfortunately, I haven't been able to build and therefore check the docs I wrote.

    Also, I saw that some methods are overloaded for char const* and std::string const&. Should Bench::context do the same? What about Result::context?

    Do you think context is a feasible name? If not, how should these methods be called?

  • Doesn't compile on macOS

    Doesn't compile on macOS

    Works great for me on Linux but not on macOS:

      FAILED: _deps/nanobench-build/CMakeFiles/nanobench.dir/src/test/app/nanobench.cpp.o 
      ccache /usr/local/opt/ccache/libexec/c++  -I_deps/nanobench-src/src/include -isysroot /Applications/Xcode_12.4.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.sdk -mmacosx-version-min=10.14 -MD -MT _deps/nanobench-build/CMakeFiles/nanobench.dir/src/test/app/nanobench.cpp.o -MF _deps/nanobench-build/CMakeFiles/nanobench.dir/src/test/app/nanobench.cpp.o.d -o _deps/nanobench-build/CMakeFiles/nanobench.dir/src/test/app/nanobench.cpp.o -c _deps/nanobench-src/src/test/app/nanobench.cpp
      In file included from _deps/nanobench-src/src/test/app/nanobench.cpp:2:
      Warning: _deps/nanobench-src/src/include/nanobench.h:117:15: warning: alias declarations are a C++11 extension [-Wc++11-extensions]
      using Clock = std::conditional<std::chrono::high_resolution_clock::is_steady, std::chrono::high_resolution_clock,
                    ^
      Error: _deps/nanobench-src/src/include/nanobench.h:296:19: error: expected function body after function declarator
      char const* csv() noexcept;
                        ^
      Error: _deps/nanobench-src/src/include/nanobench.h:308:27: error: expected function body after function declarator
      char const* htmlBoxplot() noexcept;
                                ^
      Error: _deps/nanobench-src/src/include/nanobench.h:319:20: error: expected function body after function declarator
      char const* json() noexcept;
                         ^
      Error: _deps/nanobench-src/src/include/nanobench.h:347:7: error: function definition does not declare parameters
          T pageFaults{};
            ^
      Error: _deps/nanobench-src/src/include/nanobench.h:348:7: error: function definition does not declare parameters
          T cpuCycles{};
            ^
      Error: _deps/nanobench-src/src/include/nanobench.h:349:7: error: function definition does not declare parameters
          T contextSwitches{};
            ^
      Error: _deps/nanobench-src/src/include/nanobench.h:350:7: error: function definition does not declare parameters
          T instructions{};
            ^
      Error: _deps/nanobench-src/src/include/nanobench.h:351:7: error: function definition does not declare parameters
          T branchInstructions{};
            ^
      Error: _deps/nanobench-src/src/include/nanobench.h:352:7: error: function definition does not declare parameters
          T branchMisses{};
            ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:360:33: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          std::string mBenchmarkTitle = "benchmark";
                                      ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:361:32: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          std::string mBenchmarkName = "noname";
                                     ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:362:23: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          std::string mUnit = "op";
                            ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:363:19: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          double mBatch = 1.0;
                        ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:364:25: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          double mComplexityN = -1.0;
                              ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:365:23: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          size_t mNumEpochs = 11;
                            ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:366:37: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          size_t mClockResolutionMultiple = static_cast<size_t>(1000);
                                          ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:367:44: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          std::chrono::nanoseconds mMaxEpochTime = std::chrono::milliseconds(100);
                                                 ^
      Error: _deps/nanobench-src/src/include/nanobench.h:368:30: error: function definition does not declare parameters
          std::chrono::nanoseconds mMinEpochTime{};
                                   ^
      Error: _deps/nanobench-src/src/include/nanobench.h:369:14: error: function definition does not declare parameters
          uint64_t mMinEpochIterations{1};
                   ^
      Error: _deps/nanobench-src/src/include/nanobench.h:370:14: error: function definition does not declare parameters
          uint64_t mEpochIterations{0}; // If not 0, run *exactly* these number of iterations per epoch.
                   ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:371:22: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          uint64_t mWarmup = 0;
                           ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:372:24: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          std::ostream* mOut = nullptr;
                             ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:373:45: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          std::chrono::duration<double> mTimeUnit = std::chrono::nanoseconds{1};
                                                  ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:374:31: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          std::string mTimeUnitName = "ns";
                                    ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:375:35: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          bool mShowPerformanceCounters = true;
                                        ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:376:22: warning: in-class initialization of non-static data member is a C++11 extension [-Wc++11-extensions]
          bool mIsRelative = false;
                           ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:381:29: warning: rvalue references are a C++11 extension [-Wc++11-extensions]
          Config& operator=(Config&&);
                                  ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:383:18: warning: rvalue references are a C++11 extension [-Wc++11-extensions]
          Config(Config&&) noexcept;
                       ^
      Error: _deps/nanobench-src/src/include/nanobench.h:383:21: error: expected ';' at end of declaration list
          Config(Config&&) noexcept;
                          ^
                          ;
      Error: _deps/nanobench-src/src/include/nanobench.h:373:71: error: expected '(' for function-style cast or type construction
          std::chrono::duration<double> mTimeUnit = std::chrono::nanoseconds{1};
                                                    ~~~~~~~~~~~~~~~~~~~~~~~~^
      Warning: _deps/nanobench-src/src/include/nanobench.h:391:10: warning: scoped enumerations are a C++11 extension [-Wc++11-extensions]
          enum class Measure : size_t {
               ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:407:29: warning: rvalue references are a C++11 extension [-Wc++11-extensions]
          Result& operator=(Result&&);
                                  ^
      Warning: _deps/nanobench-src/src/include/nanobench.h:409:18: warning: rvalue references are a C++11 extension [-Wc++11-extensions]
          Result(Result&&) noexcept;
                       ^
      Error: _deps/nanobench-src/src/include/nanobench.h:409:21: error: expected ';' at end of declaration list
          Result(Result&&) noexcept;
                          ^
                          ;
      Error: _deps/nanobench-src/src/include/nanobench.h:415:61: error: expected ';' at end of declaration list
          ANKERL_NANOBENCH(NODISCARD) Config const& config() const noexcept;
                                                                  ^
                                                                  ;
      Error: _deps/nanobench-src/src/include/nanobench.h:420:60: error: expected ';' at end of declaration list
          ANKERL_NANOBENCH(NODISCARD) double sum(Measure m) const noexcept;
                                                                 ^
                                                                 ;
      Error: _deps/nanobench-src/src/include/nanobench.h:421:80: error: expected ';' at end of declaration list
          ANKERL_NANOBENCH(NODISCARD) double sumProduct(Measure m1, Measure m2) const noexcept;
                                                                                     ^
                                                                                     ;
      Error: _deps/nanobench-src/src/include/nanobench.h:422:64: error: expected ';' at end of declaration list
          ANKERL_NANOBENCH(NODISCARD) double minimum(Measure m) const noexcept;
                                                                     ^
                                                                     ;
      fatal error: too many errors emitted, stopping now [-ferror-limit=]
    
  • the cycles/value output doesn't show on some platform

    the cycles/value output doesn't show on some platform

    Hi,

    I'm using nanobench in some of my projects, everything's good. Some question though. On one of my linux system using arch-linux, I got all the cycles/value, IPC, branch etc measures displayed. One of my coworker use Linux Mint ubuntu 18.04 and he got non of those.

    Is there a specific package to install so that the extra perf counter get picked up ?

  • API of latest release (v3.1.0) doesn't match tutorial / README

    API of latest release (v3.1.0) doesn't match tutorial / README

    The latest v3.1.0 release does not match any of the examples since changing Config to Bench. This is quite a big (currently) undocumented API break and potentially warrants a new release?

  • comparisons of results

    comparisons of results

    Ability to store and later compare results. Maybe multiple results, to create a graph with changes over time

    Some statistical analysis would be nice. Maybe output in a format that's understood by some good tool

  • Won't compile due to undefined references errors

    Won't compile due to undefined references errors

    It compiles fine with g++, fails with clang++ with e.g

    nb.cpp:(.text+0x2f): undefined reference to `ankerl::nanobench::Config::Config()'
    nb.cpp:(.text+0xcf): undefined reference to `ankerl::nanobench::Config::~Config()'
    nb.cpp:(.text+0x11d): undefined reference to `ankerl::nanobench::Config::~Config()'
    /tmp/nb-dff5f7.o: In function `ankerl::nanobench::Result ankerl::nanobench::Config::run<main::$_0>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, main::$_0)':
    nb.cpp:(.text+0x197): undefined reference to `ankerl::nanobench::detail::IterationLogic::IterationLogic(ankerl::nanobench::Config const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
    nb.cpp:(.text+0x1af): undefined reference to `ankerl::nanobench::detail::IterationLogic::numIters() const'
    nb.cpp:(.text+0x26f): undefined reference to `ankerl::nanobench::detail::IterationLogic::add(std::chrono::duration<long, std::ratio<1l, 1000000000l> >)'
    nb.cpp:(.text+0x2a2): undefined reference to `ankerl::nanobench::detail::IterationLogic::result() const'
    nb.cpp:(.text+0x2de): undefined reference to `ankerl::nanobench::detail::IterationLogic::result() const'
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    ``
    
    This is likely because the definition of those methods can't be resolved by clang++ somehow.
    
  • truncation warning in 4.3.8

    truncation warning in 4.3.8

    With the new 4.3.8, there is a truncation warning (warning == error for me). This warning happens when the container has a 32 bit range (eg. Qt5 vector).

    This is in Rng::shuffle:

    auto b1 = static_cast<size_t>

    suggested fix:

    auto b1 = static_cast<decltype(i)>

    Same thing for b2 = ....

  • how to deal with unstable results?

    how to deal with unstable results?

    I'm benchmarking protobuf. There are always some warning on unstable result on first run, even after increasing the warmup and minimum iteration:

    TEST_CASE("varint encode benchmark"){
    
        nanobench::Bench b;
        b.title("varint encode")
            .warmup(100000)
            .relative(true);
        b.performanceCounters(true);
    
        uint8_t buf[10] = {};
    
        b.minEpochIterations(10000000).run("google uint32_t", [&]{
            nanobench::doNotOptimizeAway(
                google::protobuf::io::CodedOutputStream::WriteVarint32ToArray(static_cast<uint32_t>(2961488830), buf));
        });
    
        b.minEpochIterations(10000000).run("google uint64_t", [&]{
            nanobench::doNotOptimizeAway(
                google::protobuf::io::CodedOutputStream::WriteVarint64ToArray(static_cast<uint64_t>(-41256202580718336), buf));
        });
    
    //     std::ofstream f{"varint encode benchmark.html"};
    //     b.render(nanobench::templates::htmlBoxplot(), f);
    
    } // TEST_CASE("varint encode benchmark")
    
    
    TEST_CASE("varint decode benchmark"){
    
        nanobench::Bench b;
        b.title("varint decode")
            .warmup(100000)
            .relative(true);
        b.performanceCounters(true);
    
        std::initializer_list<uint8_t> buf32 = {0xbe, 0xf7, 0x92, 0x84, 0x0b};
        std::initializer_list<uint8_t> buf64 = {0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01};
    
        b.minEpochIterations(10000000).run("google uint32_t", [&]{
            uint32_t v;
            nanobench::doNotOptimizeAway(
                google::protobuf::io::CodedInputStream{buf32.begin(), (int)buf32.size()}.ReadVarint32(&v));
        });
    
        b.minEpochIterations(10000000).run("google uint64_t", [&]{
            uint64_t v;
            nanobench::doNotOptimizeAway(
                google::protobuf::io::CodedInputStream{buf64.begin(), (int)buf64.size()}.ReadVarint64(&v));
        });
    
    //     std::ofstream f{"varint decode benchmark.html"};
    //     b.render(nanobench::templates::htmlBoxplot(), f);
    
    } // TEST_CASE("varint decode benchmark")
    

    encode results for 3 runs:

    | relative | ns/op | op/s | err% | total | varint encode |---------:|--------------------:|--------------------:|--------:|----------:|:-------------- | 100.0% | 6.95 | 143,943,329.37 | 5.3% | 0.87 | :wavy_dash: google uint32_t (Unstable with ~11,003,388.7 iters. Increase minEpochIterations to e.g. 110033887) | 54.0% | 12.86 | 77,751,471.35 | 2.0% | 1.56 | google uint64_t

    | relative | ns/op | op/s | err% | total | varint encode |---------:|--------------------:|--------------------:|--------:|----------:|:-------------- | 100.0% | 7.26 | 137,743,666.50 | 4.8% | 0.88 | google uint32_t | 55.0% | 13.21 | 75,702,505.04 | 1.6% | 1.62 | google uint64_t

    | relative | ns/op | op/s | err% | total | varint encode |---------:|--------------------:|--------------------:|--------:|----------:|:-------------- | 100.0% | 7.22 | 138,464,875.81 | 2.9% | 0.86 | google uint32_t | 56.4% | 12.80 | 78,102,820.79 | 1.9% | 1.55 | google uint64_t

    decode results for 3 runs:

    | relative | ns/op | op/s | err% | total | varint decode |---------:|--------------------:|--------------------:|--------:|----------:|:-------------- | 100.0% | 26.93 | 37,132,748.98 | 1.9% | 3.26 | google uint32_t | 101.0% | 26.67 | 37,490,487.35 | 3.4% | 3.23 | google uint64_t

    | relative | ns/op | op/s | err% | total | varint decode |---------:|--------------------:|--------------------:|--------:|----------:|:-------------- | 100.0% | 26.64 | 37,543,305.23 | 1.4% | 3.23 | google uint32_t | 102.7% | 25.93 | 38,558,548.08 | 1.2% | 3.17 | google uint64_t

    | relative | ns/op | op/s | err% | total | varint decode |---------:|--------------------:|--------------------:|--------:|----------:|:-------------- | 100.0% | 27.45 | 36,434,999.13 | 0.8% | 3.31 | google uint32_t | 103.1% | 26.62 | 37,568,188.30 | 2.8% | 3.23 | google uint64_t

    compiled with vs2019 16.8 msvc /O2 runs on Win10, [email protected]

  • Option to suppress unstable warnings at run-time?

    Option to suppress unstable warnings at run-time?

    Though it is a good thing to show warnings for unstable results (:wavy_dash: ... (Unstable with ...), sometimes one wants to run benchmarks in an environment where the execution is potentially perturbed by other processes and so results are known to be unstable; for example, in continuous integration.

    So, it might be handy if an environment variable (NANOBENCH_NO_UNSTABLE_WARNING or something) could change the behaviour and suppress warnings for unstable results.

    Changing the behaviour by a command-line option could be an alternative way, but I think an environment variable is more suitable for CI, and I guess it is easier to implement.

  • fix compilation error on msvc < 1928

    fix compilation error on msvc < 1928

    Hi. I met compilation errors on msvc 1927. https://godbolt.org/z/9Ph4v674E

    error C2610: 'ankerl::nanobench::Config::Config(ankerl::nanobench::Config &&) noexcept': 
    is not a special member function or comparison operator which can be defaulted
    

    It was caused by adding STL containers member to Config and Result since nanobench 7.3.8, because STL containers in msvc < 1928 seem not to have noexcept move constructor.

    Simple reproduce code is following: https://godbolt.org/z/5YM7bMTrW

    It works fine on msvc 1928. https://godbolt.org/z/YdThcWh3E

    Please review my PR and merge it if possible. It works fine on msvc 1927. https://godbolt.org/z/K7TPhYzj8

  • Add CMake options to disable building tests and examples

    Add CMake options to disable building tests and examples

    When building the library using

    cmake -B build/ -S .
    cmake --build build/
    

    examples and tests are also built. Is it possible to add CMake options for disabling that (see, e.g., google benchmark)? It's useful for packaging.

  • Randomly unstable results on Alder Lake, Win 11

    Randomly unstable results on Alder Lake, Win 11

    Can give hugely (about 100 times slower) differ results when run AVX2 code

    int main(int argc, char ** argv)
    {
    	alignas(32) float res[8];
    	float * mem = static_cast<float *>(operator new(256, std::align_val_t(32)));
    	float * mulmem = static_cast<float *>(operator new(256, std::align_val_t(32)));
    
    	Bench().run("simd", [&]()
    	{
    		__m256 simdvec_ = _mm256_loadu_ps(mem);
    		__m256 simdvecmul_ = _mm256_loadu_ps(mulmem);
    		simdvec_ = _mm256_mul_ps(simdvec_, simdvecmul_);
    		_mm256_storeu_ps(res, simdvec_);
    	});
    	return res[0];
    }
    

    Sometimes when i rebuild writes about 0.5 ns/op, and when i relaunch writes about 29 ns/op, i think it related to Windows 11 thread manager or/and because my processor is Alder Lake i5-12600k with E-cores.

    Google Benchmark seems give more consistent results about 0.23 ns

  • Setup with vcpkg

    Setup with vcpkg

    Trying to add nanobench via vcpkg manifest yields bizarre results. vcpkg manifest dependency looks like so,

    ...
        "dependencies": [
            "xtensor-blas",
            "nanobench",
            {
                "name": "highfive",
                "default-features": false,
                "features": [ "xtensor" ]
            },
    ...
    

    It only seems to be happy if I don't add anything to CMake at all. If I try to find_package(nanobench) or link against nanobench it complains that it can't be found or that I have to add to CMake_Prefix_List etc

    Is not having anything setup against it in CMake standard practice for this or is there some wizardry going on?

  • Manual Timing

    Manual Timing

    Is there a mechanism (similar to google benchmark) to perform manual timing. I.e. not use the clock builtin to nanbench but provide our own iteration time to nanobench.

A modern, C++11-native, single-file header-only, tiny framework for unit-tests, TDD and BDD (includes C++98 variant)

lest – lest errors escape testing This tiny C++11 test framework is based on ideas and examples by Kevlin Henney [1,2] and on ideas found in the CATCH

Dec 28, 2022
Upp11 - C++11 lightweight single header unit test framework

upp11 Lightweight C++11 single header unit test framework To use framework: Copy upp11.h in you project dir. Create unit test source files or modify e

Apr 4, 2019
The fastest feature-rich C++11/14/17/20 single-header testing framework
The fastest feature-rich C++11/14/17/20 single-header testing framework

master branch dev branch doctest is a new C++ testing framework but is by far the fastest both in compile times (by orders of magnitude) and runtime c

Jan 5, 2023
Header-only C++11 library for property-based testing.

autocheck Header-only C++11 library for QuickCheck (and later, SmallCheck) testing. Please consult the wiki for documentation. Install conan remote ad

Dec 22, 2022
A modern, C++-native, header-only, test framework for unit-tests, TDD and BDD - using C++11, C++14, C++17 and later (or C++03 on the Catch1.x branch)
A modern, C++-native, header-only, test framework for unit-tests, TDD and BDD - using C++11, C++14, C++17 and later (or C++03 on the Catch1.x branch)

Catch2 v3 is being developed! You are on the devel branch, where the next major version, v3, of Catch2 is being developed. As it is a significant rewo

Jan 9, 2023
Header only C++14 mocking framework
Header only C++14 mocking framework

Trompeloeil Get: trompe l'oeil noun (Concise Encyclopedia) Style of representation in which a painted object is intended to deceive the viewer into be

Dec 29, 2022
C++ Unit Testing Easier: A Header-only C++ unit testing framework

CUTE C++ Unit Testing Easier: A Header-only C++ unit testing framework usually available as part of the Cevelop C++ IDE (http://cevelop.com) Dependenc

Dec 26, 2022
A complete unit testing framework in a header

liblittletest A complete unit testing framework in a header liblittletest is an easy to use all-in-an-header testing framework; all you have to do in

Nov 11, 2021
C unit tests with a small header-only library.
C unit tests with a small header-only library.

C unit tests Minimalistic unit tests in C. Uses the __attribute__((constructor)) which, as far as I know, is supported by GCC and clang. So this proba

Dec 5, 2022
C++ mocking made easy. A simple yet very expressive, headers only library for c++ mocking.

FakeIt GCC: MSC: FakeIt is a simple mocking framework for C++. It supports GCC, Clang and MS Visual C++. FakeIt is written in C++11 and can be used fo

Jan 4, 2023
QuickCheck clone for C++ with the goal of being simple to use with as little boilerplate as possible.

RapidCheck RapidCheck is a C++ framework for property based testing inspired by QuickCheck and other similar frameworks. In property based testing, yo

Dec 27, 2022
Simple C testing framework

MrTest Simple C testing framework Usage Copy the mrtest.c and mrtest.h file into your project. In order to use the mrtest main: create a .c file that

Jul 20, 2022
A simple, cross-platform, and continuously integrated C++14 project template

Project Name A simple, cross-platform, and continuously integrated C++14 project template. Making cross platform C++ projects is widely known to be a

Dec 5, 2022
MMCTX (Memory Management ConTeXualizer), is a tiny (< 300 lines), single header C99 library that allows for easier memory management by implementing contexts that remember allocations for you and provide freeall()-like functionality.

MMCTX (Memory Management ConTeXualizer), is a tiny (< 300 lines), single header C99 library that allows for easier memory management by implementing contexts that remember allocations for you and provide freeall()-like functionality.

Oct 2, 2021
Solve 20 simple math questions and see how accurate/fast you are!
Solve 20 simple math questions and see how accurate/fast you are!

Math-Quiz Solve 20 simple math questions and see how accurate/fast you are! Want to try? Clone this repository $ git clone https://github.com/Mini-War

Sep 11, 2022
Tundra is a code build system that tries to be accurate and fast for incremental builds

Tundra, a build system Tundra is a high-performance code build system designed to give the best possible incremental build times even for very large s

Dec 23, 2022
Fast and Accurate Extrinsic Calibration for Multiple LiDARs and Cameras
Fast and Accurate Extrinsic Calibration for Multiple LiDARs and Cameras

Fast and Accurate Extrinsic Calibration for Multiple LiDARs and Cameras The pre-print version of our paper is available here. The pre-release code has

Dec 24, 2022
BLEND: A Fast, Memory-Efficient, and Accurate Mechanism to Find Fuzzy Seed Matches

BLEND is a mechanism that can efficiently find fuzzy seed matches between sequences to significantly improve the performance and accuracy while reducing the memory space usage of two important applications: 1) finding overlapping reads and 2) read mapping.

Jan 3, 2023
A simple header-only C++ argument parser library. Supposed to be flexible and powerful, and attempts to be compatible with the functionality of the Python standard argparse library (though not necessarily the API).

args Note that this library is essentially in maintenance mode. I haven't had the time to work on it or give it the love that it deserves. I'm not add

Jan 4, 2023
A simple header-only C++ argument parser library. Supposed to be flexible and powerful, and attempts to be compatible with the functionality of the Python standard argparse library (though not necessarily the API).

args Note that this library is essentially in maintenance mode. I haven't had the time to work on it or give it the love that it deserves. I'm not add

Aug 31, 2021