Я пытаюсь использовать статистику «rusage» в своей программе, чтобы получить данные, аналогичные данным инструмента время. Однако я почти уверен, что делаю что-то не так. Значения кажутся примерно правильными, но временами могут быть немного странными. Я не нашел хороших ресурсов в Интернете. Кто-нибудь знает, как это сделать лучше?
Извините за длинный код.
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





Я думаю, что где-то в вашем составе sec и usec есть ошибка. Я не могу точно сказать, что именно, не зная, какие ошибки вы видите. Приблизительно предположим, что usec никогда не может быть> 999999, поэтому вы полагаетесь на переполнение, чтобы знать, когда настраивать sec. Это также может быть проблема с вашим форматом вывода продолжительности.
Так или иначе. Почему бы не сохранить компоненты utime и stime в виде секунд с плавающей запятой вместо того, чтобы пытаться создать свой собственный rusage на выходе? Я почти уверен, что следующее даст вам правильные секунды.
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);
}
Если вы хотите разложить это обратно на rusage, вы всегда можете int-div и modulo.
Какова цель:
while (usec >= 1000)
usec /= 10;
Я так понимаю, вам нужны три старшие цифры usec; в этом случае самый простой способ, который я могу придумать, - это разделить мксек на 1000 и покончить с этим.
Тестовые случаи:
@Крис:
I gather that you want the most significant three digits of the usec
Да. Общее количество цифр в usec варьируется, и я хочу сократить число цифр ниже 1000. Например, если usec=1000, я хочу получить результат 100 (а не 1, как вы предлагаете). Следовательно, я не могу просто разделить на 1000.
Крис, тег @, похоже, в любом случае не работает. По поводу вашего комментария: я больше не работаю над этим кодом и больше не уверен, что именно я хотел получить. : - / AFAIR Я хотел посчитать 999 чисел в вашем ответе, то есть нет те, которые вы указали как «должно быть». Теперь я думаю, ты был прав.
Я не уверен, что вы имеете в виду, говоря, что количество используемых цифр меняется. Насколько мне известно, все значения в нем должны быть от 0 до 999 999, что соответствует 0 мс и 999,999 мс соответственно. «Старшие три цифры» для меня означало, что вам нужен счет в миллисекундах. Я что-то не так прочитал?