Pergunta

Estou tentando usar estatísticas de “rusage” em meu programa para obter dados semelhantes aos do tempo ferramenta.No entanto, tenho certeza de que estou fazendo algo errado.Os valores parecem corretos, mas às vezes podem ser um pouco estranhos.Não encontrei bons recursos online.Alguém sabe como fazer melhor?

Desculpe pelo código longo.

class StopWatch {
public:
    void start() {
        getrusage(RUSAGE_SELF, &m_begin);
        gettimeofday(&m_tmbegin, 0);
    }

    void stop() {
        getrusage(RUSAGE_SELF, &m_end);
        gettimeofday(&m_tmend, 0);
        timeval_sub(m_end.ru_utime, m_begin.ru_utime, m_diff.ru_utime);
        timeval_sub(m_end.ru_stime, m_begin.ru_stime, m_diff.ru_stime);
        timeval_sub(m_tmend, m_tmbegin, m_tmdiff);
    }

    void printf(std::ostream& out) const {
        using namespace std;

        timeval const& utime = m_diff.ru_utime;
        timeval const& stime = m_diff.ru_stime;

        format_time(out, utime);
        out << "u ";
        format_time(out, stime);
        out << "s ";
        format_time(out, m_tmdiff);
    }

private:
    rusage m_begin;
    rusage m_end;
    rusage m_diff;
    timeval m_tmbegin;
    timeval m_tmend;
    timeval m_tmdiff;

    static void timeval_add(timeval const& a, timeval const& b, timeval& ret) {
        ret.tv_usec = a.tv_usec + b.tv_usec;
        ret.tv_sec = a.tv_sec + b.tv_sec;
        if (ret.tv_usec > 999999) {
            ret.tv_usec -= 1000000;
            ++ret.tv_sec;
        }
    }

    static void timeval_sub(timeval const& a, timeval const& b, timeval& ret) {
        ret.tv_usec = a.tv_usec - b.tv_usec;
        ret.tv_sec = a.tv_sec - b.tv_sec;
        if (a.tv_usec < b.tv_usec) {
            ret.tv_usec += 1000000;
            --ret.tv_sec;
        }
    }

    static void format_time(std::ostream& out, timeval const& tv) {
        using namespace std;
        long usec = tv.tv_usec;
        while (usec >= 1000)
            usec /= 10;
        out << tv.tv_sec << '.' << setw(3) << setfill('0') << usec;
    }
}; // class StopWatch
Foi útil?

Solução

Qual é o propósito de:

while (usec >= 1000)
    usec /= 10;

Presumo que você queira os três dígitos mais significativos do usec;nesse caso, a maneira mais direta que consigo pensar é dividir usec por 1000 e pronto.

Casos de teste:

  • 999999 ⇒ 999
  • 99999 ⇒ 999 (deve ser 099)
  • 9999 ⇒ 999 (deveria ser 009)
  • 999 ⇒ 999 (deve ser 000)

Outras dicas

Acho que provavelmente há um bug em algum lugar na sua composição de sec e usec.Não posso dizer exatamente o que exatamente sem saber os tipos de erros que você está vendo.Um palpite aproximado seria que usec nunca pode ser> 999999, então você depende do overflow para saber quando ajustar sec.Também pode ser apenas um problema com o formato de saída da duração.

De qualquer forma.Por que não armazenar os componentes utime e stime como segundos flutuantes em vez de tentar criar seu próprio rusage na saída?Tenho certeza de que o seguinte lhe dará os segundos adequados.

static int timeval_diff_ms(timeval const& end, timeval const& start) {
    int micro_seconds = (end.tv_sec  - start.tv_sec) * 1000000 
        + end.tv_usec - start.tv_usec;

    return micro_seconds;
}

static float timeval_diff(timeval const& end, timeval const& start) {
    return (timeval_diff_ms(end, start)/1000000.0f);
}

Se você quiser decompor isso de volta em um rusage, você pode sempre int-div e modulo.

@Cris:

Presumo que você queira os três dígitos mais significativos do usec

Sim.O número total de dígitos em usec varia e quero reduzir aqueles abaixo de 1000.Por exemplo, se usec=1000, quero obter o resultado 100 (não 1, como você propõe).Portanto, não posso simplesmente dividir por 1000.

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