jcurl / RJCP.DLL.SerialPortStream

SerialPortStream is an independent implementation of System.IO.Ports.SerialPort and SerialStream for better reliability and maintainability. Default branch is 2.x and now has support for Mono with help of a C library.
Microsoft Public License
624 stars 197 forks source link

Write Buffer Size for USB CDC Device (VCOM) #49

Closed dennisai closed 6 years ago

dennisai commented 6 years ago

Hello. I have a microcontroller device that is set up as a USB CDC device, that creates a virtual COM port. I would like to write data to this device as fast as possible, and according to this StackOverflow question, I can maximize my throughput by writing 2 kB chunks in 1 ms intervals.

Is this possible using SerialPortStream? There are two questions related to this, from what I understand.

  1. Can Windows send data every 1 ms frame? Or will it be more like 10 ms?
  2. I see SerialPortStream.cs has a WriteBufferSize property. Should I be setting this to 2 kB, to match the settings of my microcontroller buffer? Or does the low-level driver need to have a buffer size of 2 kB? If so, is there any way to set this from SerialPortStream?
jcurl commented 6 years ago

There are properties DriverInQueue and DriverOutQueue to set the queue size of the driver itself for operating systems that support this (e.g. Windows only for now). You can set that to be 2kB or 8kB as you want. That's the size requested for the driver to allocate. Some drivers can handle large buffers, others not so, which is why this is configurable.

The "buffer" is a RAM backed buffer independent of the driver queue size. How fast it writes to the driver depends on the scheduler. Under windows, the scheduling can change from 8ms to 55ms depending on the OS and if multimedia services are currently active or not, as well as it's configurable I believe with an API. I don't test scheduling, but getting 1ms scheduling won't be possible from user space - that will depend on how good the USB CDC driver is written.

As the article you provided points out, write as much as you can in the buffer and let the OS deal with this.

So to answer your question:

  1. This is a Windows question. I've provided what I know above, but it's outside the scope of this project.
  2. Set the DriverOutQueue.

When the SerialPortStream writes data, it writes in chunks as big as possible, and lets the driver decide how much it should take. What it doesn't write gets sent again in the next call. This all happens in a single loop using in a single managed thread using overlapped I/O.