简体   繁体   English

.NET core 3.0 System.IO.Ports SerialPort 在 RPI 上一直使用 5-10% 的 CPU

[英].NET core 3.0 System.IO.Ports SerialPort uses 5-10% CPU on RPI all the time

When I try to read from a serial port (uart) in Linux on an RaspberryPi I always get a CPU load of 5-10% when in a loop.当我尝试从 RaspberryPi 上的 Linux 中的串行端口 (uart) 读取数据时,我总是在循环中获得 5-10% 的 CPU 负载。 As SerialPorts should be blocking, this shouldn't use that much cpu load, or am I wrong?由于 SerialPorts 应该被阻塞,这不应该使用那么多的 CPU 负载,还是我错了?

I tried two codes:我尝试了两个代码:

Simple Code简单代码

var port = new SerialPort("/dev/ttyUSB0", 57600);
port.Open();
while (true)
{
    if (port.BytesToRead > 0)
    {
    while (port.BytesToRead > 0)
        Console.Write($"{port.ReadByte().ToString("X2")} ");
    Console.WriteLine("");
    }
    Thread.Sleep(100);
}

Advanced Code高级代码

static int blockLimit = 100;
static void Main(string[] args)
{
    var port = new SerialPort("/dev/ttyUSB0", 57600);
    port.Open();
    byte[] buffer = new byte[blockLimit];
    Action kickoffRead = null;
    kickoffRead = delegate
    {
        port.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar)
        {
        try
        {
            int actualLength = port.BaseStream.EndRead(ar);
            byte[] received = new byte[actualLength];
            Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
            raiseAppSerialDataEvent(received);
        }
        catch (IOException exc)
        {
            handleAppSerialError(exc);
        }
        kickoffRead();
        }, null);
    };
    kickoffRead();

    while (true)
        Thread.Sleep(1000);
}

private static void handleAppSerialError(IOException exc)
{
    throw new NotImplementedException();
}

private static void raiseAppSerialDataEvent(byte[] received)
{
    Console.WriteLine(BitConverter.ToString(received));
}

Both with the same result: Two processes which uses together 5% to 10% cpu load两者都具有相同的结果:两个进程一起使用 5% 到 10% 的 CPU 负载htop cpu%

Using .NET Core 3.0 Preview 2 and System.IO.Ports 4.6.0-preview-19073.11 on a RaspberryPi 3b+ running with HypriotOS 1.10.0在运行HypriotOS 1.10.0RaspberryPi 3b+上使用.NET Core 3.0 Preview 2System.IO.Ports 4.6.0-preview-19073.11

As for now (NET Core 3.1) SerialPort implementation is very CPU intensive.至于现在(NET Core 3.1)SerialPort 实现是非常占用 CPU 的。 I've ported Mono SerialPort to Net Standard library according to dima117 response here .NET Core - Use System.IO.Ports.SerialPort in visual studio code我已经根据这里的 dima117 响应将 Mono SerialPort 移植到 Net Standard 库。NET Core - Use System.IO.Ports.SerialPort in Visual Studio Code

I've published it to github:我已将其发布到 github:

https://github.com/michaldobrodenka/System.IO.Ports.Mono https://github.com/michaldobrodenka/System.IO.Ports.Mono

With this SerialPort implementation, CPU usage dropped from 25% to 5% on my allwinner h3 hw使用这个 SerialPort 实现,我的 allwinner h3 hw 的 CPU 使用率从 25% 下降到 5%

I've had the same problem and did some profiling using Jetbrains's dotTrace.我遇到了同样的问题,并使用 Jetbrains 的 dotTrace 进行了一些分析。 I got the following info:我得到以下信息:

7.71%   Poll  •  25,862/25,862 ms  •  Interop+Serial.Poll(SafeHandle, PollEvents, Int32, out PollEvents)
  7.71%   PollEvents  •  System.IO.Ports.SerialStream.PollEvents(Int32, Boolean, Boolean, out Nullable)
    7.71%   IOLoop  •  System.IO.Ports.SerialStream.IOLoop
      7.71%   InnerInvoke  •  System.Threading.Tasks.Task.InnerInvoke
         Thread #8

7 procent was about the same as I saw when running top -d 1 . 7 procent 与我在运行top -d 1时看到的大致相同。

Looking at the called methods I assume that polling is used, which is not very efficient.查看被调用的方法,我假设使用了轮询,这不是很有效。 Especially if the polling interval is very short.特别是如果轮询间隔很短。 So i took a look at the dotnet source code on GitHub and noticed that the interval is hard-coded to 1 ms (line 845).所以我查看了GitHub 上的 dotnet 源代码,注意到间隔被硬编码为 1 毫秒(第 845 行)。

Interop.PollEvents events = PollEvents(
    1,
    pollReadEvents: hasPendingReads,
    pollWriteEvents: hasPendingWrites,
    out Interop.ErrorInfo? error);

I'll see if I can create an issue at the GitHub repo.我会看看我是否可以在 GitHub 存储库中创建一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM