[英]My millisecond stopwatch seems to be slow
我很无聊,所以我用 C++ 写了一个快速的毫秒秒表程序,但我注意到它比它应该的要慢; 那是数据似乎落后于实际时间。 下面看一下我的简单代码。 我假设控制台清除方法和/或延迟会减慢它的速度,但我不确定加快程序以获得准确时间读数的解决方案。
#include <chrono>
#include <thread>
#include <Windows.h>
#include <iostream>
#include <fstream>
using namespace std;
using namespace std::this_thread; // sleep_for, sleep_until
using namespace std::chrono; // nanoseconds, system_clock,
seconds
void DELAY_IN_MILLISECONDS(int millisec) {
sleep_until(system_clock::now() + milliseconds (millisec));
}
void clearConsole()
{
system( "CLS");
}
struct Time {
unsigned int tick = 0;
unsigned int millisec = 0;
unsigned int sec = 0;
unsigned int min = 0;
unsigned int hr = 0;
unsigned int days = 0;
} timeAm;
int main()
{
cout << "Started stopwatch" << endl;
while (true)
{
//listens if user presses stop key
//stop key is ESC
//This should also write the time to a textFile
if (GetKeyState(VK_ESCAPE) & 0x8000)
{
ofstream File("time.txt");
File << "[" << timeAm.hr << " Hours] "
<< "[" << timeAm.hr << " Minutes]"
<< "[" << timeAm.min << " Seconds]"
<< "[" << timeAm.sec << " Milliseconds]";
File.close();
return 0;
}
DELAY_IN_MILLISECONDS(1); //1 second delay
//seconds
timeAm.millisec++;
//minutes
if (timeAm.millisec > 59)
{
timeAm.millisec = 0;
timeAm.sec++;
}
//hours
if (timeAm.sec > 59)
{
timeAm.sec = 0;
timeAm.min++;
}
//days
if (timeAm.min > 23)
{
timeAm.min = 0;
timeAm.hr++;
}
clearConsole(); //clears console
//prints to console
cout << "[" << timeAm.hr << " Hours] "
<< "[" << timeAm.hr << " Minutes]"
<< "[" << timeAm.min << " Seconds]"
<< "[" << timeAm.sec << " Milliseconds]";
}
}
您的计时器做出了一些不正确的假设:
(不正确)每次睡眠将精确到 1ms
如https://en.cppreference.com/w/cpp/thread/sleep_until中所述
由于调度或资源争用延迟,该函数也可能阻塞更长时间,
until
达到sleep_time
之后。
(不正确)所有其他代码都立即执行(完全为零时间)。
显然这是一个疯狂的想法。 但是你的代码目前依赖它。 它会休眠 1ms(根据上面我们已经知道实际上可能不是 1ms),然后增加它的毫秒计数。 之后,它会进行一些计算和一些 I/O,然后再回到循环顶部以休眠另一个“1ms”。
根据定义,如果睡眠之间的代码需要任何时间,那么你的时钟就会漂移。
(不正确) system_clock是单调的
文档明确指出它不是(即可以随时调整时钟)。 对于为这种事情设计的单调时钟,请改用std::steady_clock 。
那么,您应该采取什么方法呢?
计时通常的工作方式是从time_point
开始,然后在任何时候计算从那时到现在所经过的时间。 通过一些基本的数学运算,您可以将其转换为HH:MM:SS.mmm
。
这样做将处理前两个不正确的假设。 每当您的进程唤醒时,您都可以计算真正的经过时间,而与其他代码(或睡眠)花费的时间无关。
将所有内容滚动在一起,您可以执行以下操作:
#include <chrono>
#include <iomanip>
#include <iostream>
#include <thread>
int main()
{
using std::chrono::duration_cast;
using std::chrono::milliseconds;
using Clock = std::chrono::steady_clock;
std::cout << std::setfill('0');
auto tbegin = Clock::now();
unsigned long elapsedMilli = -1U;
do {
Clock::duration elapsed = Clock::now() - tbegin;
unsigned long ms = duration_cast<milliseconds>(elapsed).count();
if (elapsedMilli == ms)
{
std::this_thread::sleep_until(tbegin + milliseconds(ms + 1));
continue;
}
elapsedMilli = ms;
// Build time
unsigned int t_millisec = ms % 1000; ms /= 1000;
unsigned int t_sec = ms % 60; ms /= 60;
unsigned int t_min = ms % 60; ms /= 60;
unsigned int t_hr = ms % 24; ms /= 24;
//unsigned int t_days = ms;
// Display time
std::cout << "["
<< std::setw(2) << t_hr << ":"
<< std::setw(2) << t_min << ":"
<< std::setw(2) << t_sec << "."
<< std::setw(3) << t_millisec << "]\n";
} while (elapsedMilli < 5000);
}
现场演示: https ://godbolt.org/z/fzGbvx1sa
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.