2
\$\begingroup\$

I'm trying to measure how many CPU cycles a mutex lock takes. Can you find any problems in my mutex lock benchmark?

#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>
#include <string>

std::mutex twiceMutex;
typedef std::int64_t i64;

i64 twice(i64 x)
{
    return 2 * x;
}

i64 twiceM(i64 x)
{
    std::lock_guard<std::mutex> lock(twiceMutex);
    return 2 * x;
}

const i64 I = 100'000'000; // number of iterations

struct Benchmark
{
    i64 (*fn)(i64);

    i64 operator()()const
    {
        namespace chrono = std::chrono;
        auto startTime = chrono::steady_clock::now();
        i64 res = 0;
        for (i64 i = 0; i < I; i++)
        {
            res += fn(i);
        }
        auto endTime = chrono::steady_clock::now();

        auto elapsed = chrono::duration_cast<std::chrono::nanoseconds>(endTime - startTime).count();
        return elapsed;
    }
};

int main()
{
    const double T = Benchmark{ twice }(); // total nanoseconds without mutex
    const double TM = Benchmark{ twiceM }(); // total nanoseconds with mutex

    const double K = 3.7; //GHz of my CPU
    const double t = T / I; // nanoseconds per iteration, without mutex
    const double tm = TM / I; // nanoseconds per iteration, with mutex
    const double m = tm - t; // difference nanoseconds per iteration, this should be the cost of locking a mutex in nanoseconds

    // print the results in cycles
    std::cout << t * K << std::endl;
    std::cout << tm * K << std::endl;
    std::cout << m * K << std::endl;

    {
        std::string _;
        std::getline(std::cin, _);
    }
}

I'm intentionally not taking into account thread contention; just interested in the best case cost.

The results are:

9.25905
80.1517
70.8926

So ~71 CPU cycles for locking a mutex

\$\endgroup\$
  • \$\begingroup\$ Have you disabled CPU throttling? Otherwise the time to ramp up to full CPU speed can effect the results. \$\endgroup\$ – 1201ProgramAlarm Jun 21 at 21:43
  • \$\begingroup\$ @1201ProgramAlarm nope, I don't even know how to do that. The test runs for a 3~4 seconds though \$\endgroup\$ – tuket Jun 21 at 21:48
  • \$\begingroup\$ Micro-review: the fixed-with integer types are defined in <cstdint>, so that should be included. \$\endgroup\$ – Toby Speight Jun 24 at 11:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.