【问题标题】:Periodics "lags" in Embedded Linux application嵌入式 Linux 应用程序中的周期“滞后”
【发布时间】:2014-12-29 10:51:23
【问题描述】:

我的团队正在为一种产品开发嵌入式 Linux 解决方案,其中中心应用程序从硬件接收和处理数据,并将其发送到数据库和接口应用程序。为此,我们正在使用五个线程:

  1. 主线程:创建其他线程并做一些辅助处理(从界面应用读取数据等)
  2. UPP 线程:从硬件接收数据并将其放入缓冲区中
  3. DSP 线程:从前一个缓冲区中提取数据,并要求 DSP 处理器使用该数据进行计算。返回的数据存储在第二个缓冲区中
  4. DB 线程:一段时间后,选择合理数量的计算数据并将它们存储在文件系统中。
  5. 接口线程:选择当前数据并发送到接口应用程序

此应用程序不会错过任何来自 UPP 线程的数据包,它每 200 毫秒获取新数据。 DSP 线程通常花费的时间少于这 200 毫秒(现在大约需要 30 毫秒,但将来会花费更多时间)。 DB线程通常每30秒调用一次,接口线程以5 Hz的频率调用。

我们面临的问题是,线程有时会花费更多时间来完成它们的工作,特别是 DB 和 DSP 线程。 IOW,虽然系统在每次运行 UPP 时运行 DSP,但有时 UPP 最多运行 15 次,而不会对 DSP 进行任何调用,从而丢失接收到的数据。线程中的这些零星“滞后”发生在所有线程中,但 DB 和接口中的滞后没有问题,只有当它们发生在 UPP 或 DSP 线程中时。

我们检查所有可以尝试在我们的代码中找出问题所在但没有​​成功的地方 - 大多数情况下,系统运行时没有任何延迟。不过,我们注意到了一些模式:

  • 当界面运行时显示最“重”的小部件之一时,更容易出现滞后。
  • 然而,所需处理的增加似乎不是原因:用一些“垃圾处理”对系统施加压力,并且打开界面并没有增加延迟的发生。
  • 这可能与界面和特定小部件没有直接关系;它的所有处理在时间上都是相似的(所以任何错误都可能以随机结束,但事实并非如此)

我们开始认为这与 Linux 有关。通常,在 PC 的日常使用中,鼠标或应用程序确实会出现一些滞后现象,Linux 可能正在对我们这样做。我们还考虑使用 RAM 内存,在主 Omap L138 处理器和 DSP 处理器之间共享,但一些测试为该假设提供了负面证据。

你有什么建议吗? Linux 真的是问题的根源吗?我们怎么知道,又该如何解决?

任何帮助将不胜感激。

P.s.:同this

【问题讨论】:

  • 如果您需要帮助,请显示您的源代码。你straceoprofile 你的申请了吗? “Linux 是问题的根源”没有多大意义。
  • topps auxwfree 对您的整个系统有何评价?
  • @BasileStarynkevitch 这个问题涉及的源代码巨大,这里无法复制和粘贴=T 我没有使用strace 也没有oprofile,但我正在考虑使用那些简而言之时间。
  • @BasileStarynkevitch top 没有显示太多,因为滞后非常快。我不知道看到ps auxw 应该期待什么,因为它只显示正在运行的进程(一切正常)。关于free,一般记忆还可以。

标签: c++ linux multithreading performance lag


【解决方案1】:

这可能有点太基本了,但它是我过去处理与时序和设计相关的错误时考虑过的事情清单。

指定可接受的延迟时间

对于时间敏感的应用程序,过早的优化可能会非常昂贵,请确保您了解您的滞后要求(有硬性数字),衡量您所观察的内容,并不断改进,直到达到目标。

选择合适的硬件

确保如果您有 n 个线程,并且需要合理的时间安排,那么您有大约 n 个内核。这使得证明您的进程正在利用 CPU 变得非常容易。即使您无法在生产环境中执行此操作,在测试期间执行此操作也可以帮助排除某些类型的错误。

确保您的应用程序不会使用交换空间 - 确保您有足够的 RAM 用于所有可能的用例和运行时。使用valgrind 之类的工具来确保您没有泄漏内存。

选择合适的嵌入式 Linux

您的应用程序对时序的要求越高,您就越有可能需要一个能够提供时序保证的操作系统。在真正的硬实时操作系统上运行与在只是一个精简的桌面 linux 上运行会产生非常不同的结果。了解并理解您选择的嵌入式 linux 的含义。

为您的应用选择适当的优先级

如果您看到零星的滞后,请确保您的系统上没有运行任何其他可能导致问题的东西。我在桌面 Linux 变体上看到了一些可能导致问题的奇怪东西,包括音频驱动程序。

至少在测试期间将您的优先级提高到比其他后台进程高得多(低值)。您可以使用nice 来执行此操作。

了解内核调用发生的位置

正如 cmets 中所述,使用像 strace 这样的工具来识别正在执行哪些内核调用是一个非常好的主意。同样,了解哪些类型的functions / operations 会触发系统调用会很有帮助(例如,在可能的情况下,重用缓冲区而不是触发频繁的分配和释放)。

这也有助于理解和最小化您的应用程序正在执行的锁定。这包括一些显而易见的事情,例如以一致的顺序获取锁,最大限度地减少使用锁所花费的时间,以及采用最轻量且有意义的同步原语(您可以使用原子而不是互斥锁吗?)。

选择适当的调度程序和线程优先级

如果您的任务比内核多,请考虑您使用的是哪个调度程序。

通用调度程序(在大多数情况下)不适合性能关键型应用程序。您的 linux 发行版将提供一些机制来更改 scheduler(尽管这可能需要提升权限)。

循环调度 (SCHED_RR) 是一个良好的开端,因为它使 CPU 利用率的数学计算变得非常容易(至少给出一个大概的估计)。确保具有最严格时序要求的线程具有最高优先级。请注意,更改优先级可能会导致一些细微的错误 (priority inversion)

将性能关键线程锁定到特定内核

您可以使用操作系统(或特定平台)调用来设置线程亲和性(需要停留在特定内核上)sched_affinity。在某些情况下,这有助于确保一致的缓存性能

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-05
    • 1970-01-01
    • 1970-01-01
    • 2016-08-28
    相关资源
    最近更新 更多