Reputation: 177
Im currently trying to optimize my code that i use for at program that talks with a serialport and display it on other devices.
In that context i have a "server module" that creates a TcpListener and receive data and calls a function to send and receive Serial data. and send it back to the client.
So i currently do a lot of conversions in my code, a request are in the in the moment as follow.
Becouse its a modbus program i tend to do all my stuff in HEX/Bytes value to control whats what.
Therefore i do convert alot between bytes and strings.
I want to eliminate some of this and i started from the buttom. starting not to convert from byte at the serialport to strings and send back bytes only thats saves me to conversions and a third of bytes to send.
I came up with this code: Is there a smarter way than using Array.Resize, i tried with List but i cant not get it to work properly it stays empty.
while (TcpService_Listen)
{
if (TcpListener.Pending())
{
try
{
TcpClient TcpClient = TcpListener.AcceptTcpClient();
NetworkStream TcpStream = TcpClient.GetStream();
if (TcpStream.CanRead)
{
//List<byte> list = new List<byte>(4096);
//Console.Write(list.Count);
byte[] TcpReceiveBytes = new byte[TcpClient.ReceiveBufferSize];
int TcpNumBytes = TcpStream.Read(TcpReceiveBytes, 0, TcpClient.ReceiveBufferSize);
Array.Resize(ref TcpReceiveBytes, TcpNumBytes);
Console.WriteLine("TcpReceiveBytes: " + BitConverter.ToString(TcpReceiveBytes));
byte[] TcpResponseBytes = new byte[0];
SendReceive(TcpReceiveBytes, ref TcpResponseBytes);
TcpStream.Write(TcpResponseBytes, 0, TcpResponseBytes.Length);
Console.WriteLine("TcpResponseBytes: " + BitConverter.ToString(TcpResponseBytes));
}
TcpStream.Close();
TcpClient.Close();
}
catch (Exception ex)
{
Console.Write("ERROR:TCPDATA:" + ex.Message);
}
}
}
private static void SendReceive(byte[] byteRequest, ref byte[] byteResponse)
{ //blabla send and receive stuff on serialPort ... }
Upvotes: 1
Views: 993
Reputation: 954
The best way to optimize this kind of logic is to not store everything in memory, but get rid of the chunks of data as soon as you receive them. It's not quite clear to me why you need to store everything in memory, but if you dont, just send it of, either to another serial device, or file or network channel.
If you still need to receive everything before sending it, for instance if it is an xml file that you need to alter and validate before you store it to disk you could store the chunks in a List until you have everything. Then you can make a new byte[] and copy everything over to that. Rule of thumb is that fewer memory allocations will improve performance.
Below is a sample of how to collect the data in a list and then putting it all together in a byte[] afterwords. I'm missing some of your code, so I used a similar example as foundation, but it shouldn't be to hard to adapt to your serial port code. The main part here is the List which holds all your buffers and how many bytes are used of each. Afterwards they are all copied over into a new byte[] which has space to hold all bytes. I haven't had the chance to test the running code so do some testing before you put into production.
class Program
{
class Chunk
{
public int Size { get; set; }
public byte[] Data { get; set; }
}
static void Main(string[] args)
{
try
{
int buffersize = 1024;
TcpListener server = new TcpListener(IPAddress.Any, 13000);
server.Start();
var chunks = new List<Chunk>();
while (true)
{
byte[] bytes = new byte[buffersize];
TcpClient client = server.AcceptTcpClient();
NetworkStream stream = client.GetStream();
int i;
i = stream.Read(bytes, 0, bytes.Length);
chunks.Add(new Chunk{Size = i, Data = bytes});
while (i != 0)
{
byte[] leBytes = new byte[buffersize];
i = stream.Read(leBytes, 0, leBytes.Length);
chunks.Add(new Chunk{Size = i, Data = bytes});
}
client.Close();
int totalSize = chunks.Select(x => x.Size).Sum();
var allData = new byte[totalSize];
int offset = 0;
foreach(var chunk in chunks)
{
Buffer.BlockCopy(chunk.Data,0,allData,offset,chunk.Size);
offset += chunk.Size;
}
}
}
catch (SocketException e)
{
}
}
}
Upvotes: 1