前情回顾

相信很多读者都没有读完前面一篇关于轮询调度器的文章,也没有太多人注意到每一张原创图里的那些小细节。没关系,师父曾经说过“生亦何哀,死亦何苦,等你明白了舍生取义,你自然会回来跟我唱这首歌的……”(闻道有先后,术业有专攻,等你明白了 Niagara 的精妙,你自然会回来寻找文中那些牛x闪闪的小亮点,随后点赞、投币加关注,一键三连。)我们继续。本文中,如果遇到公式不想看,可以快速跳过,收藏好,等需要的时候再来查好了;“京A说”的部分应该很好理解。

在深挖了轮询调度器的工作原理后,本文来介绍如何分析轮询调度器的基础“体检报告”。本文的讲解很多还要基于前面轮询调度器那篇文章中的例子,需要随时移步:Niagara中的数据同步方式 —— 深挖!轮询调度器


Poll Service Statistics 轮询统计数据详解

前文我们讲过,轮询调度器(Poll Scheduler)每10秒会检查一下是否有轮询配置更新。如果有一个被轮询对象的配置改变了,比如从慢(slow) 变为快(fast),最多10秒之后就会生效。在这个时间点,轮询调度器同时也会做轮询相关的统计数据更新。所以,本文讲解的这个“体检报告”也是每10秒钟刷新一次。

本文仍以 BACnet 驱动为例进行介绍,BACnet 的这个报告和其他大部分驱动不太相同,因为它每个接口下面有一个报告。比如,BACnet IP 的报告在 Bacnet Comm > Network > MstpPort > Poll Service。


统计参数释义

Poll Enabled 启用/停止轮询

[可配置][开关量]

设置为 true 的时候,轮询调度器会对当前网络下所有对象开始进行轮询。设为 false 的时候,轮询操作中止,统计数据更新暂停。

Fast/Normal/Slow Rate 三个轮询列表的目标周期

[可配置][时间]

默认配置分别是1秒,5秒和10秒。这三个配置决定了轮询策略(Tuning Policy) 定义中,选择轮询周期(Poll Frequency)时,对应的时间。

Statistics Start 统计数据的起始时间

[只读][时间]

它是一个时间标签,默认情况下是站点启动(并稳定运行)之后的那个时间点。但实际使用中,轮询开始的时间很可能是滞后于这个时间的。这个时候就可以通过 Reset Statistics Action 来重置这个时间(Poll Service 上右键,选择 Action,再选择 Reset Statistics)。

Average Poll 平均轮询时间

[只读][时间] 每次轮询操作(读取+应答)的平均时间。

计算方法:T = Σ t / n

  • 分子部分,是多次轮询操作执行时间的总和,记为 Σt。
  • 分母部分,是轮询次数 n。
  • 每一次轮询是指任何一次读取远程设备数据。这个平均时间是指n次轮询所用时间的平均值。需要特别指出的一点是,这里的轮询对象不是针对哪一个轮询组(DIDB, Fast, Normal, Slow)的,它是基于所有四个组的。换句话说,所有被轮询到的对象都被考虑在内。
  • 前文的例子中,为了简化,我们假定了这个时间是 10ms。但如果计算实际值的话,这样计算:
    第一轮中,只有一个对象F1,第二轮有2个对象F1和N1,第三轮则有三个对象F1,N1和S1……

参数意义:

  • 该参数表示的是,调度器每次执行轮询操作的平均时间,是读取一次的平均速度,即轮询操作本身耗时多少。这个“一次”并不一定是针对一个通讯点的轮询。比如 BACnet 协议中通过 ReadPropertyMultiple,就可以一次读取多个属性。在一次应答能够允许传输的最大信息量之内,读取多个属性和读取一个属性的时间几乎是相同的。
  • 这个时间有点向两地之间快递物流的时间。第一,正常情况下,从较长时间内的平均值来看,两地之间物流的速度几乎是固定的。但是如果遇到恶劣天气或者特殊管制的时候,时间就会变长。第二,如果你发的是普通的少量小件货物,物流时间几乎是与货物件数没有关系的。但如果你发的是大件货,或者数量特别多,可能就要走特殊物流渠道,或者分批发送,那么时间肯定就会变长。
  • 对应到轮询时间,如果数值越大,表示耗时越多。意味着,要么该对象所含信息量真的很大(需要分包),要么该协议读取操作速度较慢(特殊物流通道)。比如,分别通过 BACnet IP 和 BACnet MS/TP 轮询设备,MS/TP网络上的 Average Poll 就要长。

Busy Time 轮询繁忙度

[只读][%]

    • 显示格式为:x% (Σ t / T over n threads)。
    • 轮询线程工作时间占总时间的比率。

计算方法:x% = Σ t / T

  • 分子部分,是多次轮询操作执行时间的总和,记为 Σt。
  • 分母部分,T 是系统累计运行时间。
  • n 是线程数 (以后说,先考虑单线程)

参数意义:

  • 这个数值表示轮询时间占总时间的百分比,也就是任务调度器工作时间的占比。这个数值越大,说明它越忙。
  • 由于从一个轮询组切换到另一个轮询组需要少量时间,轮询组内轮询对象平均分配时间后也有少许时间间隙,所以,该参数理论上无法达到100%。但是如果该参数如果达到了95%,就说明该线程已经几乎完全饱和了,所有时间都用于轮询对象了(工作太忙,没有时间吃饭和休息)。

京A说 —— 来,算算繁忙度

  • 一般来说,这个数值越大,老板越高兴。
  • 福报企业,福气满满进入公司的应届生,从第一天开始,按照996的节奏,姑且法定假日全休(一年可以休息52天周日和11天法定假日)的繁忙度:
  • 再看看,另一个朝九晚五的繁忙度:


看到差距了吧,去福报企业,工资加倍基本上都算没涨薪啊~


Total Polls 轮询总数

[只读][数值]

    • 显示格式为:n over Σt seconds。
    • 轮询次数和所花时间。

计算方法:n 和 Σt

  • 一个是时长,也就是 Σt ,是多次轮询操作执行时间的总和
  • 另一个是该段时间内,轮询总次数 n
  • 由此也可知,其实前面的 AveragePoll 就是 TotalPolls 取反
  • 在一定时间内(10s)执行的轮询次数。
  • 基于前面的例子, T1到T7这段时间内 TotalPolls:
    n =((10+3) + 1 + 2 + 1 + 1 + 2 + (2+1)) = 23
    Σt = 23 * 10ms = 230ms

参数意义:

  • 当前网络下,每个统计周期(10秒)中,轮询多个对象用时多少。这反映的是一段时间内,轮询调度器完成的任务个数。
  • 干了多少活儿,用了多长时间。
  • 某段时间内的轮询总数由两部分组成,一部分是固定要轮询的对象,这部分在连续的多个周期中都会存在,也就是3个轮询队列中的对象,轮询它们是个相对固定的值(除非新添加了代理点)—— 固定薪资部分
  • 另外一部分是由于临时关注产生的订阅,也就是 Dibs 栈中的对象,这部分是波动的 —— 加班补贴部分
  • 当产生了大量临时订阅的统计周期中,Σt 和 n 都会增大。

Dibs/Fast/Normal/Slow Polls 各篮子中对象数量占比

[只读][%]

    • 显示格式为:current = n;average = m。
    • 哪个篮子装得多,哪个篮子装得少。

计算方法:n 和 m

  • n 是指当前篮子(Dibs/Fast/Normal/Slow之一)中对象的个数
  • m 是每个统计周期中,篮子中对象个数的平均值。
    m = Σn / 统计次数

参数意义:

  • 某个篮子中,当前对象个数和历史上平均对象个数。通过这两个数的对比,可以反映出当前篮子中对象个数的水平。
  • 比如,当前某地区人口数,和历次统计该地区平均人口数,从两者可看出当地人口是流入了(经济是发展了),还是流出了(衰退了)。

Fast/Normal/Slow Cycle Time 列表中相邻2次轮询的间隔

[只读][数值]

    • 显示格式为:average = x 。
    • 哪个篮子里装得瓷实,哪个篮子装得稀松。

计算方法:运行时间/轮询次数

  • 对同一队列,相邻两次轮询之间的时间间隔。
  • 对于 Fast 列表来说,就是 T1 和 T2 之间的间隔;对于 Normal 列表来说,就是T1和T3之间的间隔。

参数意义:

  • 这个参数能反映出某个列表中的“拥挤”程度。如果这个时间很短,证明该列表中元素密集,也就是几乎被“装满了”。

Point/Object/Virtual Count “关注”的对象数量

[只读][数值]

三个属性分别表示:当前“关注”的点、设备以及虚拟点的个数。

  • 这些数值不是随着统计数据的10秒钟周期而更新的。
  • 它们在产生订阅的时候增加,取消订阅的时候删除。
  • 所有被“关注”的对象都会进入到 Dibs 栈,但并不都会进入到三个轮询列表之一;前文我们说过,代理点肯定是会进入轮询列表的。
  • 这里的“虚拟点”并不是来自 BACnet 的概念,而是 Niagara 用来表示那些“偶尔”需要进行数据同步的非代理点,后面我们会单独讲虚拟点。

#注意

这里的对象数量和三个篮子中轮询次数并非是对应的,因为不同协议中有可能存在一次轮询读取多个对象的情况。所以说,在其他条件都一样的情况下,两个设备中,点数多的设备,通讯状况并不一定比点数少的设备差,或者差很多。

Number of Threads “关注”的对象数量

[只读][数值]

  • 只读,默认值为2。但是在 BACnet AWS / OWS 网络中,链路层为 Ethernet 时,这个线程数是可配置的,默认值也是2;
  • BACnet 驱动中有好几个跟通讯相关的线程,既有作为客户端(client)使用的,也有作为服务器(Server)使用的;
  • 从任务的角度看,BACnet 驱动中有好几个跟通讯相关的线程,包括处理COV 的,处理写操作的,处理应答消息的等等;
  • 可以通过 BACnet 模块中的 worker pool 扩展线程,以达到提高系统通讯性能的目的,尤其是在作为服务器给大量客户端提供服务的时候。

京A说 —— 多线程能提升数据同步性能吗?

今天,我先不具体回答这个问题,后面会有专文来详细解释,这里先介绍一个大原则:

首先,要弄清楚系统的性能瓶颈在哪里;其次,去找解决/缓解瓶颈的办法;再次,找到之后,尤为重要的是,要弄清楚为此付出的代价是什么(trade-off);最后,看是否值得,再决定干不干。

设备也好,系统也好,人也好,社会也好,上帝的任何馈赠,都或明或暗的标好了价格。对于工程师而言,一定要弄清标价,因为暗中的价格更可怕。

但凡你遇到这样的推销场景 ——“我们的产品跟市面上所有竞品比,都要好看,都要好用,而且便宜/免费”…… 遇到这种情况,能报警就报警,没到报警的程度,就赶紧远离。你先掂量掂量自己,何德何能,可以配得上这么好的东西。一方面是大多数人内心都有颗占便宜(bp)的种子,另一方面,也总有能洞悉这一人性弱点,并利用它的聪明人。而你我——是鱼肉,不是聪明人。记住,真正的好东西一定不容易得到! 否则,它就不是真的好!

#讲个笑话

给大家介绍一个一眼就能判断出公司/产品好坏的秘诀——看它的愿景/口号……

我们先按这个思路看几个街上的标语,以便掌握技巧:

    • 绿水青山就是金山银山 —— 生态环境有问题
    • 幸福都是奋斗出来的 —— 加班的状态(暂时)改变不了
    • 不忘初心 砥砺前行 —— 有段路走歪了
    • 江山就是人民 人民就是江山 —— …… 这个就有点儿难了,解释不了……

正题开始,看公司和产品:

    • 那些喊:“自主创新”,“科技驱动”的 —— 之前一直抄作业,现在不好抄了;
    • 那些喊:“共创美好明天”,“改变未来”的 —— 今天还过得去,但对明天有着深深的忧虑;
    • 那些喊: “为这个服务”,“为那个创造价值”的 —— 今天还没吃饱呢;
    • 那些喊:“诚信为本,质量第一”的 —— ……珍爱生命,远离骗子!

真正可以颠覆世界的公司,哪有时间想 Slogan。


结束语

✦ Poll Service 中的诸多参数,可以很好地反映轮询调度器的工作状态,是诊断数据同步入门级问题的理想工具。

✦ 美中不足的是,统计暂停之后,它无法像 Wireshark 一样,将这段时间内的统计数据做另存或者导出处理,以便于多个周期内的对比分析。