uint64 UTC时间

时间:2009-05-21 00:08:58

标签: c++ bit-manipulation utc

我有一个UTC日期时间,没有格式存储在uint64中,即:20090520145024798 我需要在这段时间内获得小时,分钟,秒和毫秒。通过将其转换为字符串并使用子字符串,我可以非常轻松地完成此操作。但是,这段代码需要非常快,所以我想避免字符串操作。是否有更快的方法,也许使用位操作来做到这一点?哦顺便说一下,这需要在Linux上用C ++完成。

2 个答案:

答案 0 :(得分:8)

uint64 u = 20090520145024798;
unsigned long w = u % 1000000000;
unsigned millisec = w % 1000;
w /= 1000;
unsigned sec = w % 100;
w /= 100;
unsigned min = w % 100;
unsigned hour = w / 100;
unsigned long v = w / 1000000000;
unsigned day = v % 100;
v /= 100;
unsigned month = v % 100;
unsigned year = v / 100;

此解决方案在中间从uint64 u切换到unsigned long w(和v)的原因是YYYYMMDD和HHMMSSIII适合32位,32位除法更快在某些系统上比64位除法。

答案 1 :(得分:6)

在pts和onebyone的建议的基础上,这是在核心2处理器上使用32位和64位操作的方法的基准:

#include <stdio.h>
#include <sys/time.h>
#include <sys/resource.h>

typedef unsigned long long uint64;

struct outs {
    unsigned millisec, sec, min, hour, day, month, year;
};

void tbreakdown2(uint64 u, struct outs *outp) {
    outp->millisec = u % 1000;
    u /= 1000;
    outp->sec = u % 100;
    u /= 100;
    outp->min = u % 100;
    u /= 100;
    outp->hour = u % 100;
    unsigned long v = u / 100;
    outp->day = v % 100;
    v /= 100;
    outp->month = v % 100;
    outp->year = v / 100;
}


void tbreakdown(uint64 u, struct outs *outp) {
    unsigned int  daypart, timepart; //4000000000
                                     //  YYYYMMDD
                                     //HHMMssssss

    daypart = u / 1000000000ULL;
    timepart = u % 1000000000ULL;

    outp->millisec = timepart % 1000;
    timepart /= 1000;
    outp->sec = timepart % 100;
    timepart /= 100;
    outp->min = timepart % 100;
    timepart /= 100;
    outp->hour = timepart;

    outp->day = daypart % 100;
    daypart /= 100;
    outp->month = daypart % 100;
    daypart /= 100;
    outp->year = daypart;
}

uint64 inval = 20090520145024798ULL;

void printstruct(uint64 u, struct outs *outp) {
    printf("%018llu\n", u);
    printf("%04d-%02d-%02d %02d:%02d:%02d.%04d\n",
            outp->year, outp->month, outp->day,
            outp->hour, outp->min, outp->sec,
            outp->millisec);
}

void print_elapsed(struct timeval *tv_begin, struct timeval *tv_end) {
    unsigned long long mcs_begin, mcs_end, mcs_delta;

    mcs_begin = (unsigned long long)tv_begin->tv_sec * 1000000ULL;
    mcs_begin += tv_begin->tv_usec;
    mcs_end = (unsigned long long)tv_end->tv_sec * 1000000ULL;
    mcs_end += tv_end->tv_usec;

    mcs_delta = mcs_end - mcs_begin;

    printf("Elapsed time: %llu.%llu\n", mcs_delta / 1000000ULL, mcs_delta % 1000000ULL);
}

int main() {
    struct outs out;
    struct outs *outp = &out;
    struct rusage rusage_s;
    struct rusage begin, end;

    __sync_synchronize();
    printf("Testing impl 1:\n");
    tbreakdown(inval, outp);
    printstruct(inval, outp);

    __sync_synchronize();
    getrusage(RUSAGE_SELF, &begin);
    for (int i = 0; i < 100000000; i++) {
        __sync_synchronize();
        tbreakdown(inval, outp);
        __sync_synchronize();
    }
    getrusage(RUSAGE_SELF, &end);
    print_elapsed(&begin.ru_utime, &end.ru_utime);

    printf("Testing impl 2:\n");
    tbreakdown2(inval, outp);
    printstruct(inval, outp);

    __sync_synchronize();
    getrusage(RUSAGE_SELF, &begin);
    for (int i = 0; i < 100000000; i++) {
        __sync_synchronize();
        tbreakdown2(inval, outp);
        __sync_synchronize();
    }
    getrusage(RUSAGE_SELF, &end);
    print_elapsed(&begin.ru_utime, &end.ru_utime);

    return 0;
}

输出:

=====32-bit=====
Testing impl 1:
020090520145024798
2009-05-20 14:50:24.0798
Elapsed time: 6.840427
Testing impl 2:
020090520145024798
2009-05-20 14:50:24.0798
Elapsed time: 19.921245

=====64-bit=====
Testing impl 1:
020090520145024798
2009-05-20 14:50:24.0798
Elapsed time: 3.152197
Testing impl 2:
020090520145024798
2009-05-20 14:50:24.0798
Elapsed time: 4.200262

正如您所看到的,避免多余的64位操作甚至在本机64位模式下也有帮助 - 但在32位上会产生巨大的差异。

Benchmark是在2.2GHz的core2duo T7500处理器下进行的,并在-O3上使用gcc 4.3.3进行编译。您看到的那些内存障碍是为了确保编译器不会尝试优化实际操作,同时允许它在选择时内联它。