Git Product home page Git Product logo

Comments (6)

stevecookdev avatar stevecookdev commented on August 19, 2024 7

I also experienced this issue and looked into it a little. The reader code uses the sp_wait call to block waiting for rx bytes to be available. This 'should' block the isolate until bytes are received. However, I found this call was always returning immediately even if no bytes have been received. This results in the isolate running in a loop hence the 100% cpu usage of a single core.

I did not have time to investigate the reason for the non-blocking call to sp_wait but I found that it was relatively simple to write an alternative version of SerialPortReader that replaces the sp_wait() call with a blocking call to read() to wait for a single byte to be received. Obviously, you must send that received byte to the send port as it is valid data but then the rest of the code is largely the same.

This will give you the correct low CPU behaviour and low latency.

Here's my alternative version of _waitRead. The rest of the code is pretty much the same with some simplifications to remove the event code which is no longer used. I am not sure how this will behave if there are serial port errors so use with caution. However, in my limited testing it has performed fine.

static void _waitRead(_SerialPortReaderArgs args) {
    SerialPort port = SerialPort.fromAddress(args.address);
    while (port.isOpen) {
      // Read a single byte. This is a blocking call which will timeout after args.timeout ms.
      var first = port.read(1, timeout: args.timeout);
      if (first.isNotEmpty) {
        // Send the single byte
        args.sendPort.send(first);
        // Read the rest of the data available.
        var toRead = port.bytesAvailable;
        if (toRead > 0) {
          var remaining = port.read(toRead);
          if (remaining.isNotEmpty) {
            args.sendPort.send(remaining);
          }
        }
      }
    }
  }

from flutter_libserialport.

boganiLuca avatar boganiLuca commented on August 19, 2024 1

Same issue here, worsened by the fact that my program could have more than one serial port to read from, each greatly increasing the CPU load. I solved by using a timer as suggested above (the 20ms latency is not a problem in my case), but this needs some fixing. Like an option to use either the event system or the first byte workaround.

from flutter_libserialport.

ali80 avatar ali80 commented on August 19, 2024

I have the same high CPU usage issue, narrowed it down to listening on SerialPortReader.stream

final reader = SerialPortReader(_sp);
_sub = reader.stream.listen((data) {
  /* final List<int> values = [];
  for (final v in data) {
    values.add(v);
  }
  _sc.add(values); */
}); 

if I don't listen on reader, the cpu usage goes back to normal, if I listen to it, even with an empty listener as shown, the CPU usage goes bad again
Temporary fix:
If I use a timer instead of SerialPortReader the problem can be avoided

_t = Timer.periodic(Duration(milliseconds: 40), (timer) {
  final data = _sp.read(400);
  final List<int> values = [];
  for (final v in data) {
    values.add(v);
  }
  if (values.isNotEmpty) _sc.add(values);
});

from flutter_libserialport.

alex-bluetrain avatar alex-bluetrain commented on August 19, 2024

I'm experiencing the same issue here, the SerialPortReader uses 100% of 1 cpu when you listen to its stream.
Timer.periodic is many orders of magnitudes more efficient, even with 1 millisecond interval.

from flutter_libserialport.

moodstubos avatar moodstubos commented on August 19, 2024

@stevecookdev
Thanks a lot for your workaround. I am using it and it works perfectly.

from flutter_libserialport.

dkozenkov avatar dkozenkov commented on August 19, 2024

@stevecookdev
Thank for your example code. You mentioned: "I am not sure how this will behave if there are serial port errors so use with caution". And you were right: this code snippet doesn't handle error situations like disconnecting an UART-device, etc.
I added the necessary processing:

static void _waitRead(_SerialPortReaderArgs args) {
    final fport = ffi.Pointer<sp_port>.fromAddress(args.address);
    final events = _createEvents(fport, _kReadEvents);
    SerialPort port = SerialPort.fromAddress(args.address);
    while (port.isOpen) {
      // Read a single byte. This is a blocking call which will timeout after args.timeout ms.
      Uint8List first;
      try {
        first = port.read(1, timeout: args.timeout);
      } catch (e) {
        args.sendPort.send(SerialPort.lastError);
        break;
      }
      if (first.isNotEmpty) {
        // Send the single byte
        args.sendPort.send(first);
        // Read the rest of the data available.
        var toRead = port.bytesAvailable;
        if (toRead > 0) {
          var remaining = port.read(toRead);
          if (remaining.isNotEmpty) {
            args.sendPort.send(remaining);
          }
        }
      }
    }
    _releaseEvents(events);
  }

from flutter_libserialport.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.