4
\$\begingroup\$

I have to benchmark my code often, and decided that it is about time to implement an easy API for that:

current_time.h:

#ifndef CURRENT_TIME_H
#define CURRENT_TIME_H

#include <chrono>
#include <cstdint>

class CurrentTime {
    std::chrono::high_resolution_clock m_clock;

public:
    uint64_t milliseconds();
    uint64_t microseconds();
    uint64_t nanoseconds();
};

#endif  /* CURRENT_TIME_H */

current_time.cpp:

#include "current_time.h"

uint64_t CurrentTime::milliseconds() 
{
    return std::chrono::duration_cast<std::chrono::milliseconds>
              (m_clock.now().time_since_epoch()).count();
}

uint64_t CurrentTime::microseconds() 
{
    return std::chrono::duration_cast<std::chrono::microseconds>
              (m_clock.now().time_since_epoch()).count();
}

uint64_t CurrentTime::nanoseconds()
{
    return std::chrono::duration_cast<std::chrono::nanoseconds>
              (m_clock.now().time_since_epoch()).count();
}    

main.cpp:

#include <iostream>
#include "current_time.h"

using namespace std;

int main(int argc, char** argv) {
    CurrentTime current_time;

    uint64_t start1 = current_time.milliseconds();
    uint64_t start2 = current_time.microseconds();
    uint64_t start3 = current_time.nanoseconds();

    for (int i = 0; i < 100000000; ++i) {

    }

    uint64_t end1 = current_time.milliseconds();
    uint64_t end2 = current_time.microseconds();
    uint64_t end3 = current_time.nanoseconds();

    cout << "Milliseconds: "   << (end1 - start1)
         << ", microseconds: " << (end2 - start2)
         << ", nanoseconds: "  << (end3 - start3)
         << ".\n";

    return 0;
}

Any critique is much appreciated, yet I would like to hear your opinions on returning uint64_t: is there some implicit conversions going on?

\$\endgroup\$

3 Answers 3

3
\$\begingroup\$

Since std::chrono::high_resolution_clock::now() is static method you don't need any instance for it.

This is all you need.

#ifndef CURRENT_TIME_H
#define CURRENT_TIME_H

#include <chrono>
#include <cstdint>

inline uint64_t CurrentTime_milliseconds() 
{
    return std::chrono::duration_cast<std::chrono::milliseconds>
              (std::chrono::high_resolution_clock::now().time_since_epoch()).count();
}

inline uint64_t CurrentTime_microseconds() 
{
    return std::chrono::duration_cast<std::chrono::microseconds>
              (std::chrono::high_resolution_clock::now().time_since_epoch()).count();
}

inline uint64_t CurrentTime_nanoseconds()
{
    return std::chrono::duration_cast<std::chrono::nanoseconds>
              (std::chrono::high_resolution_clock::now().time_since_epoch()).count();
}  

#endif  /* CURRENT_TIME_H */
\$\endgroup\$
1
  • \$\begingroup\$ @LokiAstari Sorry, I am lost. 1. There are no objects ever because the now() method is static. 2. What do you mean by capturing time at creation? I see no member values in `CurrentTime. \$\endgroup\$
    – Jan Korous
    Jun 23, 2016 at 20:29
3
\$\begingroup\$

One File

I would put everything into the header file (so you don't need to have a separate source file). The code is so short there is no need for the two files.

#ifndef CURRENT_TIME_H
#define CURRENT_TIME_H

#include <chrono>
#include <cstdint>

class CurrentTime {
    std::chrono::high_resolution_clock m_clock;

public:
    uint64_t milliseconds();
    uint64_t microseconds();
    uint64_t nanoseconds();
};

uint64_t CurrentTime::milliseconds() 
{
    return std::chrono::duration_cast<std::chrono::milliseconds>
              (m_clock.now().time_since_epoch()).count();
}

uint64_t CurrentTime::microseconds() 
{
    return std::chrono::duration_cast<std::chrono::microseconds>
              (m_clock.now().time_since_epoch()).count();
}

uint64_t CurrentTime::nanoseconds()
{
    return std::chrono::duration_cast<std::chrono::nanoseconds>
              (m_clock.now().time_since_epoch()).count();
}    

#endif  /* CURRENT_TIME_H */

NameSpace

Put this in your own namespace.

I can easily see somebody else defining a class or function CurrentTime. You should be using namesapces to keep your code separate from other peoples.

If you are worried about all the nested namesapce making it to verbose then let people use namespace alias.

namespace EasyTime
{
    // optionally another level
    namespace Spagetti
    {
        // Your stuff here
    }
}

Then in main:

#include "current_time.h"
namespace ets = EasyTime::Spagetti;

int main()
{
    ets::CurrentTime  now;
    std::cout << now. milliseconds() << "\n";
}

Header guards

#ifndef CURRENT_TIME_H
#define CURRENT_TIME_H

Not sure if that is unique enough. I can easily imagine somebody else using the same header guard. I would add the namespace to your header guard. I use THORSANVIL_ as a prefix to all my guards and the namespace ThorsAnvil (because I own the domain thorsanvil.com).

\$\endgroup\$
2
\$\begingroup\$

Edit

If you do not wish to write std::chrono:: in client code then I would perhaps use namespace functions instead since the use of a class is a bit overkill since we do not really need to maintain any state.

The following code may be more suitable and easier to extend, plus we do not need to create an object to use it.

#ifndef CURRENT_TIME_H
#define CURRENT_TIME_H

#include <chrono>
#include <cstdint>

namespace TimeHelpers
{
    namespace
    {
        inline std::chrono::high_resolution_clock Clock()
        {
            static std::chrono::high_resolution_clock clock;
            return clock;
        }

        template<typename Out, typename In>
        Out TimeAs()
        {
            return std::chrono::duration_cast<In>
                (Clock().now().time_since_epoch()).count();
        }
    }

    template<typename Out>
    inline Out TimeFromEpochInMilliSeconds()
    {
        return TimeAs<Out, std::chrono::milliseconds>();
    }

    template<typename Out>
    inline Out TimeFromEpochInMicroSeconds()
    {
        return TimeAs<Out, std::chrono::microseconds>();
    }

    template<typename Out>
    inline Out TimeFromEpochInNanoSeconds()
    {
        return TimeAs<Out, std::chrono::nanoseconds>();
    }
}

#endif  /* CURRENT_TIME_H */

Use case then would be

auto timeASMs = TimeHelpers::TimeFromEpochInMilliSeconds<uint64_t>();
auto timeASMsDob = TimeHelpers::TimeFromEpochInMilliSeconds<double>();
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.