L'applicazione che sto scrivendo mostra segni di stress quando è sotto carico da diverse interfacce di comunicazione seriale. Quindi sto cercando modi per migliorare le prestazioni. Ho realizzato una versione semplificata del modo tipico in cui ho implementato la lettura del gestore di porta seriale. Ci sono miglioramenti che potrei fare che potrebbero produrre qualche miglioramento?
In particolare, sto esaminando i problemi di prestazioni quando istanziamo gli oggetti e li butto via tutto il tempo, esemplificato qui con il metodo Logger.Trace()
che usa BitConverter.ToString()
, che a sua volta ha bisogno di un array di byte. Quindi ho bisogno di convertire ogni messaggio ricevuto in un array di byte usando ToArray()
. Si tratta di un problema di prestazioni o va bene?
Lo stesso vale se ho una classe che rappresenta un messaggio ricevuto (lunghezza, payload (id di comando, parametri di comando), checksum ecc.) che viene istanziata ogni volta che viene ricevuto un nuovo messaggio e lasciata a essere rilevata da il garbage collector una volta che il messaggio ricevuto è stato analizzato.
public class SerialPortHandler : IDisposable
{
private SerialPort _serialPort;
private BlockingCollection<byte> _rxBuffer;
private bool _close;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public SerialPortHandler()
{
_serialPort = new SerialPort("COM1", 19200, Parity.None, 8, StopBits.One);
_serialPort.DataReceived += SerialPort_DataReceived;
_serialPort.Open();
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var sp = (SerialPort)sender;
var bytes = new byte[sp.BytesToRead];
sp.Read(bytes, 0, bytes.Length);
foreach (byte b in bytes)
{
_rxBuffer.Add(b);
}
}
private void RxBufferConsumer()
{
var rxMessage = new List<byte>();
while (!_close)
{
CheckRxBuffer(ref rxMessage);
}
}
private void CheckRxBuffer(ref List<byte> rxMessage)
{
byte rxByte;
bool messageReceived;
if (_rxBuffer.TryTake(out rxByte, 100))
{
// See if received byte fits into expected message protocol format,
// and if so add to rxMessage buffer.
messageReceived = ReadReceivedByte(rxByte, ref rxMessage);
// Parse received message.
if (messageReceived)
{
ParseReceivedMessage(rxMessage);
}
}
}
private bool ReadReceivedByte(byte rxByte, ref List<byte> rxMessage)
{
// Do stuff, and return true if a complete message has been received.
return true;
}
private void ParseReceivedMessage(List<byte> rxMessage)
{
// Do stuff with the received message.
_logger.Trace("{0} RX: {1}", _serialPort.PortName,
BitConverter.ToString(rxMessage.ToArray()));
}
public void Dispose()
{
_close = true;
_serialPort.Close();
_serialPort.Dispose();
}
}