views:

74

answers:

3

I'm trying to pull the two components out of a timeval struct and place them into strings.

I'm not having much luck with this. I've attempted casting and converting first to a long and then to a string. I need the most efficient way to do this.

Any ideas? I do NOT want to convert to another data structure first (localtime, etc). I need the seconds and the microseconds in their original state.

EDIT: I know stringstream is an option here -- I'm just not sure how efficient that is. Every microsecond counts here, so I'm looking for the fastest implementation.

+1  A: 

Boost's lexical_cast should be reasonably fast.

Edit:
Let me elaborate. Here's an example of its usage:

std::string strSeconds = lexical_cast<std::string>(time.tv_sec);
std::string strMicroSec = lexical_cast<std::string>(time.tv_usec);

For more complicated string formatting, the Boost documentation recommends the basic std::stringstream. Something like:

std::stringstream ss;
ss << time.tv_sec << " seconds, " << (time.tv_usec/1000L) << " milliseconds";
return ss.str();

Reasonably fast, readable, safe and standard. You might be able to get a little more speed by using sprintf from the cstdio header. (preferably sprintf_s if available) There's no explicit support for long variables in printf, but these days on 32-bit+ machines they're usually the same size so you can use the %d specifier to handle them:

std::string tvtostr(timeval time) {
    // unless corrupted, the number of microseconds is always less than 1 second
    assert(time.tv_sec >= 0 && time.tv_usec >= 0 && time.tv_usec < 1000000000L);
    static_assert(sizeof(long)==4 && sizeof(int)==sizeof(long), 
        "assuming 32 bit ints and longs" ); 

    // space for one unbounded positive long, one long from 0 to 999,
    // the string literal below, and a '\0' string terminator
    boost::array<CHAR, 10+3+23+1> buffer; 

    sprintf_s(buffer.data(), buffer.size(), "%d seconds, %d milliseconds", 
        time.tv_sec, (time.tv_usec/1000L) );

    return buffer.data();
}
Gunslinger47
A: 

Unless I'm missing something here you basically want to convert integer to strings in the fastest possible way. If that's so check out Matthew Wilson's series of articles in DDJ and take your pick:

Flexible C++ #1: Efficient Integer to String Conversions

Flexible C++ #2: Efficient Integer to String Conversions

Flexible C++ #3: Efficient Integer to String Conversions

Flexible C++ #4: Efficient Integer to String Conversions

Eugen Constantin Dinca
`long` to `std::string`
Gunslinger47
A: 

Unless you have conclusive proof from profiling that std::ostringstream is too slow, I would use it as it's the most straightforward approach. Don't try to prematurely optimize these sorts of conversions.

That being said, for microseconds, if you're willing to give up a chunk of memory you can create an array of 1000000 strings for each possible value of that field, and index the string you need directly.

Mark B
Obligatory note: `std::endl` triggers a stream flush. This implies system calls, file-writes, heap-allocations, etc. Use '\n' in performance code when repeated flushes aren't needed.
Gunslinger47