我有一个没有格式存储在uint64中的协调世界时日期时间,即:20090520145024798
我需要从这个时间中获取小时、分钟、秒和毫秒。通过将其转换为字符串并使用substring,我可以很容易地做到这一点。但是,这段代码需要非常快,所以我希望避免字符串操作。有没有更快的方法,比如使用位操作?哦,顺便说一下,这需要在Linux上的C++中完成。
发布于 2009-05-20 16:17:54
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位除法更快。
发布于 2009-05-20 16:56:32
为了基于pts和onebyone的建议,这里是他们在core 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位模式下会产生巨大的差异。
基准测试是在2.2 gcc的core2duo T7500处理器上进行的,并在-O3上使用gcc 4.3.3编译。你看到的那些内存障碍是为了确保编译器不会试图优化实际操作,同时允许它选择内联它。
https://stackoverflow.com/questions/890847
复制