This code is a Extension to just be able to read a line quickly and efficiently with support for SslStream
.
What i'm looking to achieve:
- Lower CPU usage by improving how it stores bytes for being converted to string later
- Lower CPU usage by possibly not reading per-byte some how. In my debug tests its using up the most CPU by far. 33%/55% of samples are the ReadByte
So your probably asking why im using a Queue as a buffer?
Basically the Queue allows me to more efficiently store bytes in an array format.
byte[]
is un-acceptable due to the fact its size can't be changed dynamically (you would have to make a new byte, move over the old data, add the new, replace the old byte[]
, in-efficient)
queue however (or Stack if you .Reverse()
it with linq) lets you add bytes whenever you want and then .ToArray
when you need it as a byte[]
Same thing can be done with List<byte>
but I dont feel like it's the best tool for the job in this case.
Another thing I could do here is just convert with Encoding.GetString
on every byte and StringBuilder
it but that seems to use more CPU and a lot more memory.
Any suggestions?
public static string ReadLine(this Stream stream, ref int bodySize, Encoding encoding) {
bool bodySizeWasSpecified = bodySize > 0;
byte b = 0;
Queue<byte> Buffer = new Queue<byte>();
while (true) {
#region Try Get 1 Byte from Stream
try {
int i = stream.ReadByte();
if (i == -1) {
break;//stream ended/closed
}
b = (byte)i;
} catch {
return null;//timeout //not authenticated context
}
#endregion
#region If there's a body size specified, decrement back 1
if (bodySizeWasSpecified) {
bodySize--;
}
#endregion
#region If Byte is \n or \r
if (b == 10 || b == 13) {
#region If ByteArray is Empty and the byte is \n reloop so we dont start with a leading \n
if (Buffer.Count == 0 && b == 10) {
continue;
}
#endregion
#region We hit a newline, lets finish the reads here.
break;
#endregion
}
#endregion
#region Add the read byte to the Byte Array
Buffer.Enqueue(b);
#endregion
#region Break if bodysize was greater than 0 but now its 0
if (bodySizeWasSpecified && bodySize == 0) {
break;
}
#endregion
}
return encoding.GetString(Buffer.ToArray());
}