- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我们的代码是用 C++ 11(VS2012/Win 7-64 位)编写的。 C++ 库提供了我们使用的 sleep_for
函数。我们观察到 C++ sleep_for
有时会出现较大的超调。换句话说,我们要求 sleep 15 毫秒,但 sleep 结果是例如100 毫秒。当系统负载很高时,我们会看到这一点。
我的第一 react 是:“当然,如果系统负载很大并且其他线程正在使用 CPU,那么 sleep 当然会“花更长的时间””。然而,“有趣”的是,如果我们将 sleep_for
替换为 Windows API“Sleep”调用,那么我们将看不到这种行为。我还看到水下的 sleep_for
函数调用了 Window API Sleep
方法。
sleep_for 的文档状态:
The function blocks the calling thread for at least the time that's specified by Rel_time. This function does not throw any exceptions.
所以从技术上讲,该功能正在运行。然而,我们没想到会看到 C++ sleep_for
和常规 Sleep(Ex)
函数之间的区别。
有人可以解释这种行为吗?
最佳答案
如果使用 sleep_for 与 SleepEx,则会执行相当多的额外代码。
例如,调用 SleepEx(15) 在 Debug模式下生成以下程序集 (Visual Studio 2015):
; 9 : SleepEx(15, false);
mov esi, esp
push 0
push 15 ; 0000000fH
call DWORD PTR __imp__SleepEx@8
cmp esi, esp
call __RTC_CheckEsp
对比这段代码
const std::chrono::milliseconds duration(15);
std::this_thread::sleep_for(duration);
生成以下内容:
; 9 : std::this_thread::sleep_for(std::chrono::milliseconds(15));
mov DWORD PTR $T1[ebp], 15 ; 0000000fH
lea eax, DWORD PTR $T1[ebp]
push eax
lea ecx, DWORD PTR $T2[ebp]
call duration
push eax
call sleep_for
add esp, 4
这调用到:
duration PROC ; std::chrono::duration<__int64,std::ratio<1,1000> >::duration<__int64,std::ratio<1,1000> ><int,void>, COMDAT
; _this$ = ecx
; 113 : { // construct from representation
push ebp
mov ebp, esp
sub esp, 204 ; 000000ccH
push ebx
push esi
push edi
push ecx
lea edi, DWORD PTR [ebp-204]
mov ecx, 51 ; 00000033H
mov eax, -858993460 ; ccccccccH
rep stosd
pop ecx
mov DWORD PTR _this$[ebp], ecx
; 112 : : _MyRep(static_cast<_Rep>(_Val))
mov eax, DWORD PTR __Val$[ebp]
mov eax, DWORD PTR [eax]
cdq
mov ecx, DWORD PTR _this$[ebp]
mov DWORD PTR [ecx], eax
mov DWORD PTR [ecx+4], edx
; 114 : }
mov eax, DWORD PTR _this$[ebp]
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 4
duration ENDP
并呼入
sleep_for PROC ; std::this_thread::sleep_for<__int64,std::ratio<1,1000> >, COMDAT
; 151 : { // sleep for duration
push ebp
mov ebp, esp
sub esp, 268 ; 0000010cH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-268]
mov ecx, 67 ; 00000043H
mov eax, -858993460 ; ccccccccH
rep stosd
mov eax, DWORD PTR ___security_cookie
xor eax, ebp
mov DWORD PTR __$ArrayPad$[ebp], eax
; 152 : stdext::threads::xtime _Tgt = _To_xtime(_Rel_time);
mov eax, DWORD PTR __Rel_time$[ebp]
push eax
lea ecx, DWORD PTR $T1[ebp]
push ecx
call to_xtime
add esp, 8
mov edx, DWORD PTR [eax]
mov DWORD PTR $T2[ebp], edx
mov ecx, DWORD PTR [eax+4]
mov DWORD PTR $T2[ebp+4], ecx
mov edx, DWORD PTR [eax+8]
mov DWORD PTR $T2[ebp+8], edx
mov eax, DWORD PTR [eax+12]
mov DWORD PTR $T2[ebp+12], eax
mov ecx, DWORD PTR $T2[ebp]
mov DWORD PTR __Tgt$[ebp], ecx
mov edx, DWORD PTR $T2[ebp+4]
mov DWORD PTR __Tgt$[ebp+4], edx
mov eax, DWORD PTR $T2[ebp+8]
mov DWORD PTR __Tgt$[ebp+8], eax
mov ecx, DWORD PTR $T2[ebp+12]
mov DWORD PTR __Tgt$[ebp+12], ecx
; 153 : sleep_until(&_Tgt);
lea eax, DWORD PTR __Tgt$[ebp]
push eax
call sleep_until
add esp, 4
; 154 : }
push edx
mov ecx, ebp
push eax
lea edx, DWORD PTR $LN5@sleep_for
call @_RTC_CheckStackVars@8
pop eax
pop edx
pop edi
pop esi
pop ebx
mov ecx, DWORD PTR __$ArrayPad$[ebp]
xor ecx, ebp
call @__security_check_cookie@4
add esp, 268 ; 0000010cH
cmp ebp, esp
call __RTC_CheckEsp
mov esp, ebp
pop ebp
ret 0
npad 3
$LN5@sleep_for:
DD 1
DD $LN4@sleep_for
$LN4@sleep_for:
DD -24 ; ffffffe8H
DD 16 ; 00000010H
DD $LN3@sleep_for
$LN3@sleep_for:
DB 95 ; 0000005fH
DB 84 ; 00000054H
DB 103 ; 00000067H
DB 116 ; 00000074H
DB 0
sleep_for ENDP
一些转换发生了:
to_xtime PROC ; std::_To_xtime<__int64,std::ratio<1,1000> >, COMDAT
; 758 : { // convert duration to xtime
push ebp
mov ebp, esp
sub esp, 348 ; 0000015cH
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-348]
mov ecx, 87 ; 00000057H
mov eax, -858993460 ; ccccccccH
rep stosd
mov eax, DWORD PTR ___security_cookie
xor eax, ebp
mov DWORD PTR __$ArrayPad$[ebp], eax
; 759 : xtime _Xt;
; 760 : if (_Rel_time <= chrono::duration<_Rep, _Period>::zero())
lea eax, DWORD PTR $T7[ebp]
push eax
call duration_zero ; std::chrono::duration<__int64,std::ratio<1,1000> >::zero
add esp, 4
push eax
mov ecx, DWORD PTR __Rel_time$[ebp]
push ecx
call chronos_operator ; std::chrono::operator<=<__int64,std::ratio<1,1000>,__int64,std::ratio<1,1000> >
add esp, 8
movzx edx, al
test edx, edx
je SHORT $LN2@To_xtime
; 761 : { // negative or zero relative time, return zero
; 762 : _Xt.sec = 0;
xorps xmm0, xmm0
movlpd QWORD PTR __Xt$[ebp], xmm0
; 763 : _Xt.nsec = 0;
mov DWORD PTR __Xt$[ebp+8], 0
; 764 : }
; 765 : else
jmp $LN3@To_xtime
$LN2@To_xtime:
; 766 : { // positive relative time, convert
; 767 : chrono::nanoseconds _T0 =
; 768 : chrono::system_clock::now().time_since_epoch();
lea eax, DWORD PTR $T5[ebp]
push eax
lea ecx, DWORD PTR $T6[ebp]
push ecx
call system_clock_now ; std::chrono::system_clock::now
add esp, 4
mov ecx, eax
call time_since_ephoch ; std::chrono::time_point<std::chrono::system_clock,std::chrono::duration<__int64,std::ratio<1,10000000> > >::time_since_epoch
push eax
lea ecx, DWORD PTR __T0$8[ebp]
call duration ; std::chrono::duration<__int64,std::ratio<1,1000000000> >::duration<__int64,std::ratio<1,1000000000> ><__int64,std::ratio<1,10000000>,void>
; 769 : _T0 += _Rel_time;
mov eax, DWORD PTR __Rel_time$[ebp]
push eax
lea ecx, DWORD PTR $T4[ebp]
call duration_ratio ; std::chrono::duration<__int64,std::ratio<1,1000000000> >::duration<__int64,std::ratio<1,1000000000> ><__int64,std::ratio<1,1000>,void>
lea ecx, DWORD PTR $T4[ebp]
push ecx
lea ecx, DWORD PTR __T0$8[ebp]
call duration_ratio ; std::chrono::duration<__int64,std::ratio<1,1000000000> >::operator+=
; 770 : _Xt.sec = chrono::duration_cast<chrono::seconds>(_T0).count();
lea eax, DWORD PTR __T0$8[ebp]
push eax
lea ecx, DWORD PTR $T3[ebp]
push ecx
call duration_cast ; std::chrono::duration_cast<std::chrono::duration<__int64,std::ratio<1,1> >,__int64,std::ratio<1,1000000000> >
add esp, 8
mov ecx, eax
call duration_count ; std::chrono::duration<__int64,std::ratio<1,1> >::count
mov DWORD PTR __Xt$[ebp], eax
mov DWORD PTR __Xt$[ebp+4], edx
; 771 : _T0 -= chrono::seconds(_Xt.sec);
lea eax, DWORD PTR __Xt$[ebp]
push eax
lea ecx, DWORD PTR $T1[ebp]
call duration_ratio ; std::chrono::duration<__int64,std::ratio<1,1> >::duration<__int64,std::ratio<1,1> ><__int64,void>
push eax
lea ecx, DWORD PTR $T2[ebp]
call duration_ratio ; std::chrono::duration<__int64,std::ratio<1,1000000000> >::duration<__int64,std::ratio<1,1000000000> ><__int64,std::ratio<1,1>,void>
lea ecx, DWORD PTR $T2[ebp]
push ecx
lea ecx, DWORD PTR __T0$8[ebp]
call duration_ratio ; std::chrono::duration<__int64,std::ratio<1,1000000000> >::operator-=
; 772 : _Xt.nsec = (long)_T0.count();
lea ecx, DWORD PTR __T0$8[ebp]
call duration_ratio ; std::chrono::duration<__int64,std::ratio<1,1000000000> >::count
mov DWORD PTR __Xt$[ebp+8], eax
$LN3@To_xtime:
; 773 : }
; 774 : return (_Xt);
mov eax, DWORD PTR $T9[ebp]
mov ecx, DWORD PTR __Xt$[ebp]
mov DWORD PTR [eax], ecx
mov edx, DWORD PTR __Xt$[ebp+4]
mov DWORD PTR [eax+4], edx
mov ecx, DWORD PTR __Xt$[ebp+8]
mov DWORD PTR [eax+8], ecx
mov edx, DWORD PTR __Xt$[ebp+12]
mov DWORD PTR [eax+12], edx
mov eax, DWORD PTR $T9[ebp]
; 775 : }
push edx
mov ecx, ebp
push eax
lea edx, DWORD PTR $LN8@To_xtime
call @_RTC_CheckStackVars@8
pop eax
pop edx
pop edi
pop esi
pop ebx
mov ecx, DWORD PTR __$ArrayPad$[ebp]
xor ecx, ebp
call @__security_check_cookie@4
add esp, 348 ; 0000015cH
cmp ebp, esp
call __RTC_CheckEsp
mov esp, ebp
pop ebp
ret 0
$LN8@To_xtime:
DD 2
DD $LN7@To_xtime
$LN7@To_xtime:
DD -24 ; ffffffe8H
DD 16 ; 00000010H
DD $LN5@To_xtime
DD -40 ; ffffffd8H
DD 8
DD $LN6@To_xtime
$LN6@To_xtime:
DB 95 ; 0000005fH
DB 84 ; 00000054H
DB 48 ; 00000030H
DB 0
$LN5@To_xtime:
DB 95 ; 0000005fH
DB 88 ; 00000058H
DB 116 ; 00000074H
DB 0
to_xtime ENDP
最终会调用导入的函数,与 SleepEx 使用的函数相同。
sleep_until PROC ; std::this_thread::sleep_until, COMDAT
; 131 : { // sleep until _Abs_time
push ebp
mov ebp, esp
sub esp, 192 ; 000000c0H
push ebx
push esi
push edi
lea edi, DWORD PTR [ebp-192]
mov ecx, 48 ; 00000030H
mov eax, -858993460 ; ccccccccH
rep stosd
; 132 : _Thrd_sleep(_Abs_time);
mov esi, esp
mov eax, DWORD PTR __Abs_time$[ebp]
push eax
call DWORD PTR __imp___Thrd_sleep
add esp, 4
cmp esi, esp
call __RTC_CheckEsp
; 133 : }
pop edi
pop esi
pop ebx
add esp, 192 ; 000000c0H
cmp ebp, esp
call __RTC_CheckEsp
mov esp, ebp
pop ebp
ret 0
sleep_until ENDP
您还应该知道,根据 MSDN 文档 https://msdn.microsoft.com/en-us/library/windows/desktop/ms686307(v=vs.85).aspx,即使 SleepEx 也可能无法给出 100% 准确的结果。
此函数会导致线程放弃其时间片的剩余部分,并在基于 dwMilliseconds 值的时间间隔内变得不可运行。系统时钟以恒定速率“滴答”。如果 dwMilliseconds 小于系统时钟的分辨率,线程可能会休眠少于指定的时间长度。如果 dwMilliseconds 大于 1 个滴答声但小于 2 个滴答声,则等待时间可以在 1 到 2 个滴答声之间的任何时间,依此类推。要提高 sleep 间隔的准确性,请调用 timeGetDevCaps 函数来确定支持的最小计时器分辨率,并调用 timeBeginPeriod 函数将计时器分辨率设置为其最小值。调用 timeBeginPeriod 时要小心,因为频繁调用会显着影响系统时钟、系统电源使用和调度程序。如果您调用 timeBeginPeriod,请在应用程序的早期调用一次,并确保在应用程序的最后调用 timeEndPeriod 函数。
关于c++ - Windows 7:超越 C++ std::this_thread::sleep_for,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32904371/
我正在尝试做一件非常简单的事情(但花了几个小时没有结果):打印一行,睡一会儿,打印第二行。我希望下面的代码可以做到这一点,但是,它首先会休眠,然后同时打印两行!谁能看到我在这里缺少的东西? 这是完整的
我想在线程内运行一个循环,每毫秒计算一些数据。但是我在 sleep 功能上遇到了麻烦。它睡得太久了。 我在 visual studio 中创建了一个基本的控制台应用程序: #include #inc
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: std::this_thread::sleep_for() and GCC 尝试编写一个简单的计时器和一些代
我正在使用 this_thread::sleep_for() 进行测试创建一个类似于 cout 的对象, 除了在打印字符串时它会在每个字符之间有一个小的延迟。但是,它不是在每个字符之间等待 0.1 秒
我有一个包含两个线程的简单程序,一个将 packaged_task 推送到一个 deque 中,另一个执行它。在任务中有一个 this_thread::sleep_for,我希望只有“进程”线程会等待
有人可以解释这两种停止线程然后再继续的方式在行为上的区别吗? Sleep(); //from Win32 std::this_thread::sleep_for(); 我评论的是多线程行为,而不是系统
我正在用纯 c++11 编写,想在关闭它后做一个简单的“等待 x 秒并打开一个成员变量”。此示例中类的成员变量是“动画”的标志。 cout animating = false;
我很震惊地跟踪这个简单的代码: #include void foo() { for (int i = 0; i >(const std::chrono::duration > & _Rel
在我的应用程序中,我想用这段代码显示一些图像 myImage = scene->addPixmap(image); myImage->setOffset(x, y); 然后我想睡几秒钟: std::t
在使用 std::this_thread::sleep_for() 毫秒及以上时,是否需要考虑任何已知的可移植性问题? 在我正在进行的项目中,我希望使用 Microsoft 的 Sleep() 到 n
我正处于使用 gcc 在 Linux 下将一些遗留 C++ 代码升级到 C++11 的阶段。在尝试设置优先级时,我想到了以下问题。将对 usleep 的调用与对 std::this_thread::s
我有一个循环,我想确保它在每个循环中运行(大约)固定的时间量。 我正在使用 sleep_for 来实现此行为,但我也希望程序能够在不完全支持标准线程库的环境中编译。现在我有这样的东西: using n
请注意,这不是关于 std::condition_variable::wait_for() 的问题。我知道这可能会虚假唤醒。 我的程序的行为表明这个问题的答案是肯定的,但是 STL 文档对于 cond
std::this_thread::sleep_for()或usleep() 在main()中使用哪种更好?这可能很愚蠢,但是我是C++ 11功能的新手。 最佳答案 前者实际上是可移植的C++函数。后
如果我并排放置两个调用来确定最小可测量持续时间: // g++ -std=c++11 -O3 -Wall test.cpp #include typedef std::chrono::high_re
我正在尝试在 Google 测试中 sleep 。根据this post ,我可以使用以下内容: #include #include TEST_F(TestSuite, TestOne) {
我正在使用 VS2012,但我遇到以下示例的问题: #include #include int main() { // doesn't compile and I don't unders
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); 编译:clang++ main.cpp -o main.exe -g -st
谁能说出以下示例的问题所在? 它每秒产生 65 帧而不是 300 帧。 #define WIN32_LEAN_AND_MEAN #include #include #include #inclu
当我尝试编译这个简单的程序时: #include void f() { std::this_thread::sleep_for(std::chrono::seconds(3)); } int ma
我是一名优秀的程序员,十分优秀!