c# - 如何在不加载 CPU 的情况下每 X 微秒运行一个方法 (0 < X < 1000)?

标签 c# performance scheduled-tasks scheduling

我正在寻找任何定时器的设计,它可以调度周期小于1毫秒的任务。最优化的场景:负载1个核心的25%,当1个单独的线程用于运行时这个模式。

1 毫秒是所有计时器的限制,我知道:

  • System.Windows.Forms.Timer
  • 系统.定时器.定时器
  • 系统.Threading.Timer

我已经实现了计时器,它每 X 微秒运行一次任务。但当使用 1 个单独的线程运行此模式时,它仍然加载几乎一个核心。

代码:

private readonly TimeSpan _period;

private readonly Stopwatch _stopwatch;

private TimeSpan _lastElapsedTime;

private Double _iterationsPerPeriod;

void Run() 
{
    TimeSpan elapsed = _stopwatch.Elapsed;
    TimeSpan interval = elapsed - _lastElapsedTime;
    if (interval < _period)
    {
        Int32 iterationsToWait = (Int32) (_iterationsPerPeriod * (interval.TotalMilliseconds / _period.TotalMilliseconds));
        Thread.SpinWait(iterationsToWait);
    }

    _lastElapsedTime = _stopwatch.Elapsed;
    // RunTask();
}

void RunTimer() 
{
    while(true)
    {
        Run();
    }
}

如何在不加载 CPU 的情况下每 X 微秒运行一个方法?

最佳答案

“停止”CPU 的唯一方法就是停止它 - 这是 Windows 上的内核级指令。唤醒 CPU 的唯一方法是给它一个中断——同样是内核级的。虽然可以在 x86 上创建精度远高于毫秒的计时器中断,但您需要创建自己的操作系统(可能是虚拟化的 - 如果它专门使用 CPU)来使用它。

在应用程序级别,您需要完全依赖可用的接口(interface)。并且您需要与同一 CPU/操作系统上运行的其他进程合作。这意味着您需要使用OS 任务调度——而Windows 任务调度有限制。您可能等待的最短间隔取决于操作系统允许的时间 - 在 Windows 上,这曾经与系统计时器相关(~20 毫秒,可配置低至 0.5 毫秒)。但即使使用较新的调度程序,您也不能随意调度线程以微秒精度运行。

如果您需要这样的硬实时环境,您根本无法使用 Windows 或任何其他抢占式多任务系统。每隔半毫秒 sleep 一次已经插入了同时运行数百个进程和数千个线程的现代系统的实际功能。如果您有能力让该线程自行占用 CPU,则忙碌等待可以让您接近(实际上仍然在游戏中使用) - 否则,其他线程可以轻松地从您的线程中窃取 CPU(轻松 20 毫秒或更长)。当然,如果系统负载过大,它仍然会很快失败。

一如既往,这是一场权衡游戏。制作一个可以如此精确地调度线程的现代多任务系统是可能的,但并不值得。即使在具有独占 CPU 访问权限的旧游戏中,您通常也不会“ sleep 20us”——相反,您会等待垂直回扫中断或类似的东西(这在 DirectX/OpenGL/Vulkan 中仍然可用。 .)。很少有应用程序既需要现代多任务系统,又需要如此高的调度程序精度。在大多数用户应用程序中,您可以使用允许您在 25% 的时间中休眠的算法,而无需每 20us 切换一次线程上下文(例如,每个“帧”执行更多工作,并相应地休眠更长的时间)。

关于c# - 如何在不加载 CPU 的情况下每 X 微秒运行一个方法 (0 < X < 1000)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42133447/

相关文章:

java - NullPointerExceptions 在停止发生后会导致 Tomcat 性能问题吗?

C# if/return 或 if/return/else 更好?

mysql - 优化 MySQL 中的嵌套查询(特别是 GROUP BY)

Django - 带有 django-celery-beat/rabbitmq : Nothing? 的 Celery 4.1

linux - SCHED_DEADLINE 的 sched_setaffinity()

c# - SqlCommand.ExecuteReader 是否会自动打开数据库连接?

c# - 使用 Entity Framework 4.1 将位字段参数传递给存储过程

c# - ulong 属性的符合 CLS 的替代方案

c# - 如何使用查询字符串和哈希重定向到另一个 Controller ?

algorithm - 任务/作业调度问题