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.

  • 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.
    
  • 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.

  • Why a fork on pyperf?

    Why a fork on pyperf?

    Hi, Is there a reason why does it recommend a fork of pyperf (https://github.com/vstinner/pyperf) instead of pyperf itself? (https://github.com/psf/pyperf)

    Thanks!

  • which one is more important, ns/op or total?

    which one is more important, ns/op or total?

    | ns/op | op/s | err% | ins/op | cyc/op | IPC | bra/op | miss% | total | benchmark |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:---------- | 7,266,190.00 | 137.62 | 3.3% | 4,721,603.00 | 15,556,024.00 | 0.304 | 1,302,758.00 | 13.0% | 0.18 | hopscotch_map | 35,033,938.00 | 28.54 | 0.9% | 4,961,470.00 | 76,638,408.00 | 0.065 | 1,097,837.00 | 23.8% | 0.44 | unordered_map | 6,696,755.00 | 149.33 | 1.7% | 8,040,577.00 | 14,634,752.00 | 0.549 | 767,069.00 | 17.1% | 0.12 | flat_hash_map | 7,676,762.00 | 130.26 | 2.3% | 7,126,320.00 | 16,794,536.00 | 0.424 | 774,163.00 | 17.6% | 0.09 | F14FastMap

    flat_hash_map: ns/op : 6,696,755.00, total : 0.12 F14FastMap: ns/op: 7,676,762.00, total: 0.09

  • Enable perf counters on older kernels

    Enable perf counters on older kernels

    As stated in the comments and the manual page , PERF_COUNT_HW_REF_CPU_CYCLES is available since linux 3.3. It tried it locally with an older kernel (3.10) and it works fine.

    Can you maybe clarify why the check was done against version 3.14 and not 3.3 ?

    Thanks.

  • 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

Aug 5, 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

Aug 17, 2022
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

Apr 18, 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

Aug 16, 2022
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

Aug 3, 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

Jul 22, 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

May 10, 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

Aug 6, 2022
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

Aug 14, 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

Jul 27, 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

Apr 10, 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

Jul 17, 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

Aug 7, 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.

Jul 29, 2022
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 5, 2022
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