Pergunta

Eu tenho uma data e hora UTC sem a formatação armazenados em um uint64, ou seja: 20090520145024798 Eu preciso para obter as horas, minutos, segundos e milissegundos fora deste tempo. Eu posso fazer isso muito facilmente, convertendo-a uma corda e usando substring. No entanto, este precisa de código para ser muito rápido, então eu gostaria de evitar manipulações de string. Existe maneira mais rápida, talvez usando manipulação de bits para fazer isso? Ah, a propósito isso precisa ser feito em C ++ em Linux.

Foi útil?

Solução

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;

A razão pela qual esta solução muda de uint64 u para unsigned long w (e v) no meio é que o DDMMAAAA e HHMMSSIII ajuste para 32 bits, e divisão de 32 bits é mais rápido do que a divisão de 64 bits em alguns sistemas.

Outras dicas

Para construir sobre pts e sugestões de onebyone, aqui é uma referência das suas abordagens utilizando 32-bit e 64-operações, em um processador de núcleo 2:

#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;
}

E a saída:

=====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

Como você pode ver, evitando manipulações 64 bits excesso ajuda mesmo em modo nativo de 64 bits -. Mas faz uma diferença enorme em 32 bits

de Referência foi realizada sob um processador Core2Duo T7500 a 2,2 GHz, e compilada usando gcc 4.3.3 em -O3. Essas barreiras de memória que você vê são para garantir o compilador não tentar otimizar afastado a operação real, permitindo que inline-lo se ele escolhe.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top