我遇到了一个问题,我的游戏循环卡顿大约每秒一次(可变间隔)。单帧需要超过 60 毫秒,而所有其他帧需要不到 1 毫秒。
经过大量简化后,我得到了以下重现错误的程序。它只测量帧时间并报告它。
#include <iostream>
#include "windows.h"
int main()
{
unsigned long long frequency, tic, toc;
QueryPerformanceFrequency((LARGE_INTEGER*)&frequency);
QueryPerformanceCounter((LARGE_INTEGER*)&tic);
double deltaTime = 0.0;
while( true )
{
//if(deltaTime > 0.01)
std::cerr << deltaTime << std::endl;
QueryPerformanceCounter((LARGE_INTEGER*)&toc);
deltaTime = (toc - tic) / double(frequency);
tic = toc;
if(deltaTime < 0.01) deltaTime = 0.01;
}
}
同样,许多帧中的一帧比其他帧慢得多。添加 if 让错误消失(那时永远不会调用 cerr)。我原来的问题不包含任何 cerr/cout。但是,我认为这是同一错误的重现。
cerr 在每次迭代中都会被刷新,因此创建单个慢帧时不会发生这种情况。我从一个探查器(非常困)那里知道流在内部使用了一个锁/关键部分,但这不应该改变任何东西,因为程序是单线程的。
是什么导致单次迭代停滞那么多?
编辑:我做了更多测试:
std::this_thread::sleep_for( std::chrono::milliseconds(7) ); 并因此减少进程 CPU 利用率不会改变任何东西。printf("%f\n", deltaTime); 问题就消失了(可能是因为它没有使用与流相反的互斥锁和内存分配)最佳答案
Windows 的设计并不能保证任何执行时间的上限,因为它使用某种逻辑将运行时资源动态地分配给所有程序——例如,调度程序会将资源分配给优先级高的进程,并饿死较低的进程在某些情况下优先处理。如果程序运行紧密循环并消耗大量 CPU 资源,那么程序在统计上更有可能 - 最终 - 受到此类事情的影响。因为 - 最终 - 调度程序将暂时提高正在挨饿的程序的优先级和/或降低其他正在挨饿的程序的优先级(在您的情况下,通过运行紧密循环)。
使 std::cerr 的输出成为条件并不会改变发生这种情况的事实 - 它只是改变它在指定时间间隔内发生的可能性,因为它改变了程序的方式在循环中使用系统资源,因此改变了它与系统调度程序、策略等交互的方式。
这类事情会影响在所有非实时操作系统中运行的程序,尽管确切的影响取决于每个操作系统的实现方式(例如调度策略、控制程序对资源访问的其他策略等)。发生此类停顿的概率始终为非零(即使概率很小)。
如果你想绝对保证在这些事情上没有停顿,你将需要一个实时操作系统。这些系统被设计成在时间意义上更可预测地做事,但这需要权衡取舍,因为它还要求您的程序在设计时就知道它们必须在指定的时间间隔内完成指定功能的执行。实时操作系统使用不同的策略,但如果程序在设计时没有考虑到这些问题,它们强制执行约束时间可能会导致程序出现故障。
关于C++ 主循环偶尔会卡顿,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29729017/
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:
我对如何计算通过{%assignvar=0%}赋值的变量加一完全感到困惑。这应该是最简单的任务。到目前为止,这是我尝试过的:{%assignamount=0%}{%forvariantinproduct.variants%}{%assignamount=amount+1%}{%endfor%}Amount:{{amount}}结果总是0。也许我忽略了一些明显的东西。也许有更好的方法。我想要存档的只是获取运行的迭代次数。 最佳答案 因为{{incrementamount}}将输出您的变量值并且不会影响{%assign%}定义的变量,我
我是Ruby的新手,有些闭包逻辑让我感到困惑。考虑这段代码:array=[]foriin(1..5)array[5,5,5,5,5]这对我来说很有意义,因为i被绑定(bind)在循环之外,所以每次循环都会捕获相同的变量。使用每个block可以解决这个问题对我来说也很有意义:array=[](1..5).each{|i|array[1,2,3,4,5]...因为现在每次通过时都单独声明i。但现在我迷路了:为什么我不能通过引入一个中间变量来修复它?array=[]foriin1..5j=iarray[5,5,5,5,5]因为j每次循环都是新的,我认为每次循环都会捕获不同的变量。例如,这绝对
我有一个数组数组,想将元素附加到子数组。+=做我想做的,但我想了解为什么push不做。我期望的行为(并与+=一起工作):b=Array.new(3,[])b[0]+=["apple"]b[1]+=["orange"]b[2]+=["frog"]b=>[["苹果"],["橙子"],["Frog"]]通过推送,我将推送的元素附加到每个子数组(为什么?):a=Array.new(3,[])a[0].push("apple")a[1].push("orange")a[2].push("frog")a=>[[“苹果”、“橙子”、“Frog”]、[“苹果”、“橙子”、“Frog”]、[“苹果”、“
有没有办法让Ruby能够做这样的事情?classPlane@moved=0@x=0defx+=(v)#thisiserror@x+=v@moved+=1enddefto_s"moved#{@moved}times,currentxis#{@x}"endendplane=Plane.newplane.x+=5plane.x+=10putsplane.to_s#moved2times,currentxis15 最佳答案 您不能在Ruby中覆盖复合赋值运算符。任务在内部处理。您应该覆盖+,而不是+=。plane.a+=b与plane.a=
出于某种原因,heroku尝试要求dm-sqlite-adapter,即使它应该在这里使用Postgres。请注意,这发生在我打开任何URL时-而不是在gitpush本身期间。我构建了一个默认的Facebook应用程序。gem文件:source:gemcuttergem"foreman"gem"sinatra"gem"mogli"gem"json"gem"httparty"gem"thin"gem"data_mapper"gem"heroku"group:productiondogem"pg"gem"dm-postgres-adapter"endgroup:development,:t