首页 > 编程语言 >在 C# 中使用 Socket.Poll() 提高 CPU 利用率

在 C# 中使用 Socket.Poll() 提高 CPU 利用率

时间:2024-08-13 10:27:59浏览次数:7  
标签:BytesReaded Socket 工控机 C# 线程 Poll BytesRead CPU

一、背景

        最近在使用 Sharp7.cs 连接西门子 PLC 时,发现当在同一台工控机上连接多个(实际超过100)CPU 时,工控机的 CPU 占用非常大,会去到 20~30%。然而此时实际的网络流量确并不高,只有10mbps。大量 CPU 资源消耗不知道在做什么。因为此时工控机上也没有跑其他业务代码。所以基本可以定位到是 Sharp7.cs 连接 PLC 这里出了问题。那么具体问题发生在哪里呢?只能看源码来发现问题了。

二、原因

        在 Sharp7.cs 中发现了如下代码来读取 PLC 发送过来的数据,通过不断的读取是否有可用字节来判断一次数据是否传输完成。这样写的是可以保证读取要需要长度的数据,很多简单的 socket 编程上都可以见到。可以见到,由于代码中包含有 Sleep() 并且 sleep 的时间非常短,当同时有大量的线程都在读取数据的时候,大量的 CPU 资源消耗在了线程的切换上,造成 CPU 占用率高,效率严重不足。

 1 while ((BytesReaded < Size))
 2 {
 3     Thread.Sleep(2);
 4     SizeAvail = TCPSocket.Available;
 5     try
 6     {
 7         byte[] Flush = new byte[SizeAvail];
 8         int BytesRead = TCPSocket.Receive(Buffer, Start + BytesReaded, SizeAvail, SocketFlags.None);
 9         BytesReaded += BytesRead;
10     }
11     catch { }
12 }

三、办法

        C# 提供了 Poll() 方法来改善上述的问题。Poll() 将在指定的时间段内阻塞程序的执行直到 socket 可用。这样 socket 所在线程就会在有可用数据的时候被唤醒, 而不是不停的去测试是否有可读数据了,从而减少线程切换提高 CPU 的利用率。把代码修改如下,(注意 Poll() 方法中的时间单位是微秒)

 1 while (BytesReaded < Size && TCPSocket.Poll(1000 * _ReadTimeout, SelectMode.SelectRead))
 2 {
 3     int BytesRead = TCPSocket.Receive(Buffer, Start + BytesReaded, Size - BytesReaded, SocketFlags.None);
 4     if (BytesRead == 0)
 5     {
 6         LastError = S7Consts.errTCPDataReceive;
 7         Close();
 8     }
 9     BytesReaded += BytesRead;
10 }

 四、效果

        经过上面的修改,工控机从 PLC 单次读取数据的时间从 16ms 减少到 10ms,极大的提高了 CPU 的利用率。

    完。

如果你觉得这个软件对你有用还可以打赏,打赏用户将会列入打赏榜单。也接受定制服务。

标签:BytesReaded,Socket,工控机,C#,线程,Poll,BytesRead,CPU
From: https://www.cnblogs.com/flysun027/p/18356344

相关文章

  • CDQ分治
    P3810【模板】三维偏序(陌上花开)CDQ模板题,考虑先按\(a\)排序,减掉一位,然后再\(CDQ\)分治一维,用树状数组维护最后一维还有本题特殊,去重操作不要忘记点击查看代码#include<bits/stdc++.h>#definespeed()ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);#definell......
  • 【学习笔记6】论文SQLfuse: Enhancing Text-to-SQL Performance through Comprehensiv
    Abstract        Text-to-SQL转换是一项关键创新,简化了从复杂SQL语句到直观自然语言查询的转换,尤其在SQL在各类岗位中广泛应用的情况下,这一创新显得尤为重要。随着GPT-3.5和GPT-4等大型语言模型(LLMs)的兴起,这一领域得到了极大的推动,提供了更好的自然语言理解......
  • Scrapy 项目部署问题及解决方案
    部署Scrapy项目时可能会遇到一些常见问题。以下是几个常见的部署问题及其解决方案:1、依赖问题问题:部署后爬虫运行失败,通常是由于缺少依赖库。2、配置问题问题:爬虫在部署环境中无法正常运行,可能是由于配置文件错误或缺失。3、数据库连接问题问题:爬虫运行时无法连接......
  • MySQL——删除数据(三)使用关键字 TRUNCATE 删除表中数据
        在MySQL数据库中,还有一种方式可以用来删除表中所有的记录,这种方式需要用到一个关键字TRUNCATE,其语法格式如下:TEUNCATE[TABLE]表名        TRUNCATE的语法格式很简单,只需要通过“表名”指定要执行删除操作的表即可。下面通过一个案例来演示TRUN......
  • MySQL——单表查询(一)简单查询(1)SELECT语句
        MySQL从数据表中查询数据的基本语句是SELECT语句。在SELECT语句中,可以根据自己对数据的需求,使用不同的查询条件,SELECT语句的基本语法格式如下:SELECT[DISTINCT]*|字段名1,字段名2,字段名3,…FROM表名[WHERE条件表达式1][GR......
  • Java中class文件结构分析一
    一:源代码packagecom.tuling.smlz.jvm.classbyatecode;/***Createdbysmlzon2019/11/5.*/publicclassTulingByteCode{privateStringuserName;publicStringgetUserName(){returnuserName;}publicvoidsetUserName(Strin......
  • Java中class文件结构分析二
    第17个常量池:010015284C6A6176612F6C616E672F537472696E673B295601:tag位表示的是utf8类型的字面量常量0015二个字节表示的是字面量常量的长度为21接下来21个字节:284C6A6176612F6C616E672F537472696E673B2956表示字符串(......
  • Java网络编程——Cookie & Session
    cookie前面我们学习Okhttp3库可以调用API、抓取网页、下载文件。但是这些操作都是不要求登录的,如果API、网页、文件等内容要求登录才能访问,就需要学习新的cookie相关的知识了。下面以豆瓣为例,使用Java程序读取“我的豆瓣”页面内容,在此过程中熟悉运用cookie。所......
  • 阿里云Centos7搭建邮件服务器端口使用465
    1.申请一个域名指向这台服务器   2.下面是如果安装了postifx和dovecot有配置问题错误可以卸载重装                                  ......
  • [CF1172E] Nauuo and ODT
    [CF1172E]NauuoandODT首先考虑单次询问,将每个颜色拉出来,求解有多少条路径至少包含一个给定点。这就是维护所有黑色连通块的大小平方和。我们每一次删掉一个点就等价于将所有和他相连的点删掉,这样一定会T。可以使用类似CF487ETourists的套路,将其父亲—儿子化,如果一个点......