草庐IT

ARM 上的 Linux "top"实用程序报告我们已验证错误的数字。为什么?

coder 2023-06-21 原文

我们有一个运行 Linux 2.6.32.20 的基于 ARM9 的嵌入式板。该设备是一个摄像机,其相关的捕获/压缩硬件将数据放入 ARM 内存中的输入 fifo,然后 ARM 从用户空间访问该 fifo。我们还有一个用于此编码器的驱动程序,用于高级控制。

应用程序级代码中的线程检查此用户空间 fifo,当有数据时,它通过套接字将其发送出去。为了避免该线程需要轮询用户空间 fifo 以获取数据的开销,我们对驱动程序进行了一个非常简单的 read() 调用,实际上它只是挂起,直到 fifo 中有任何数据(没有真正“读”到read() 调用中提供的缓冲区)。这个 read() 调用然后返回,线程继续从 fifo 读取数据直到它为空,然后通过调用伪造的 read() 调用再次挂起。

根据在检测到帧丢失之前可以传输多少网络流来衡量,该系统非常高效。但我们已经确定,使用伪造的 read() 调用会导致 Linux“top”实用程序报告我们的应用程序使用大量 CPU。

我们已经构建了 2 个版本的应用程序 - 一个运行方式如上,另一个相同,只是它从不调用假的 read() 而是通过中间的 usleep() 调用轮询 fifo。当我们查看“top”报告的 2 种情况下的 CPU 使用情况时,每种情况都发送 5 个流,我们得到:

1) read() 版本:CPU 12%
2) usleep() 版本:CPU 4%

当然,现实中的轮询效率较低,如果我们忽略“top”的意思,而只是测量在我们看到帧丢失之前这两个版本可以同时传输多少网络流,那么上面的版本 1 获胜。

我们已经验证上面的 read() 调用运行正常。如果一些错误导致 read() 调用立即返回,即使 fifo 中没有数据,那么线程最终将进行昂贵的连续轮询。但这种情况并非如此; read() 调用导致线程每秒准确运行 30 次。

我们认为我们的“top”玩具 busybox 版本可能采取了一些捷径 - 但这些结果不在 top 用来计算其显示数字的/proc//stat 中的原始数字中。

这个问题一定是 Linux 内核本身如何收集/proc//stat 中显示的数字的一些限制。

如果有人明白为什么会这样,请为我指明正确的方向。 谢谢!

最佳答案

我可以保证 top 没有骗你。如果它说您的进程使用了​​ 12% 的 CPU,那么它使用了 12% 的 CPU。没有两种方法可以解决这个问题。

显然,调用 usleep 不会花费太多时间,因为它会导致进程进入休眠状态(至少)达到请求的时间量。每次 sleep 调用可能有 100 个周期。 Read 做的远不止于此,所以我并不惊讶它需要更多的 CPU 时间来做这件事——尤其是当你经常这样做的时候。

阅读遗嘱:

  1. 检查您的句柄是否有效。
  2. 检查您的缓冲区指针和长度是否有效。
  3. 将长度从用户空间复制到内核空间。
  4. 将读取的数据插入合适的数据结构。
  5. 查找相关句柄以及向哪个驱动程序发出请求。
  6. 向您的驱动程序发出读取请求。
  7. 驱动程序休眠进程[假定没有可用数据]。
  8. 驱动程序唤醒进程[当有可用数据时]。
  9. 将读取的长度数据复制到用户空间。
  10. 返回调用者。

与 usleep 比较:

  1. 去 sleep 吧。
  2. 醒来。
  3. 返回给用户。

当然,“去 sleep ”不是一个简单的函数,唤醒也不是简单的函数。但它们是相同的操作,并且在 sleep 期间,进程不使用 CPU。

您可以通过从/dev/zero 读取并在两者之间休眠来轻松计算出读取中有多少开销。 /dev/zero 是一种设备,它会立即返回一个充满零的缓冲区。

或者,您可以尝试使用 oprofile 之类的工具来进行性能分析,看看时间花在了哪里。

但我很确定你的 top 没有说谎。

关于ARM 上的 Linux "top"实用程序报告我们已验证错误的数字。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14266888/

有关ARM 上的 Linux "top"实用程序报告我们已验证错误的数字。为什么?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  5. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  6. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  7. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  8. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  9. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  10. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

随机推荐