简体   繁体   中英

.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. As SerialPorts should be blocking, this shouldn't use that much cpu load, or am I wrong?

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 loadhtop 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

As for now (NET Core 3.1) SerialPort implementation is very CPU intensive. 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

I've published it to github:

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

With this SerialPort implementation, CPU usage dropped from 25% to 5% on my allwinner h3 hw

I've had the same problem and did some profiling using Jetbrains's 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 .

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).

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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