perf: keep parser state in bytes until materialization
This commit is contained in:
@@ -37,7 +37,7 @@ public readonly struct ParsedCommand
|
|||||||
|
|
||||||
public sealed class NatsParser
|
public sealed class NatsParser
|
||||||
{
|
{
|
||||||
private static readonly byte[] CrLfBytes = "\r\n"u8.ToArray();
|
private static ReadOnlySpan<byte> CrLfBytes => "\r\n"u8;
|
||||||
private ILogger? _logger;
|
private ILogger? _logger;
|
||||||
public ILogger? Logger { set => _logger = value; }
|
public ILogger? Logger { set => _logger = value; }
|
||||||
|
|
||||||
@@ -85,7 +85,7 @@ public sealed class NatsParser
|
|||||||
|
|
||||||
// Look for \r\n to find control line
|
// Look for \r\n to find control line
|
||||||
var reader = new SequenceReader<byte>(buffer);
|
var reader = new SequenceReader<byte>(buffer);
|
||||||
if (!reader.TryReadTo(out ReadOnlySequence<byte> line, CrLfBytes.AsSpan()))
|
if (!reader.TryReadTo(out ReadOnlySequence<byte> line, CrLfBytes))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Control line size check
|
// Control line size check
|
||||||
@@ -177,7 +177,7 @@ public sealed class NatsParser
|
|||||||
case (byte)'c':
|
case (byte)'c':
|
||||||
if (b1 == (byte)'o') // CONNECT
|
if (b1 == (byte)'o') // CONNECT
|
||||||
{
|
{
|
||||||
command = ParseConnect(lineSpan);
|
command = ParseConnect(line);
|
||||||
buffer = buffer.Slice(reader.Position);
|
buffer = buffer.Slice(reader.Position);
|
||||||
TraceInOp("CONNECT");
|
TraceInOp("CONNECT");
|
||||||
return true;
|
return true;
|
||||||
@@ -188,7 +188,7 @@ public sealed class NatsParser
|
|||||||
case (byte)'i':
|
case (byte)'i':
|
||||||
if (b1 == (byte)'n') // INFO
|
if (b1 == (byte)'n') // INFO
|
||||||
{
|
{
|
||||||
command = ParseInfo(lineSpan);
|
command = ParseInfo(line);
|
||||||
buffer = buffer.Slice(reader.Position);
|
buffer = buffer.Slice(reader.Position);
|
||||||
TraceInOp("INFO");
|
TraceInOp("INFO");
|
||||||
return true;
|
return true;
|
||||||
@@ -430,36 +430,34 @@ public sealed class NatsParser
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ParsedCommandView ParseConnect(Span<byte> line)
|
private static ParsedCommandView ParseConnect(ReadOnlySequence<byte> line)
|
||||||
{
|
{
|
||||||
// CONNECT {json} -- find first space after command
|
var reader = new SequenceReader<byte>(line);
|
||||||
int spaceIdx = line.IndexOf((byte)' ');
|
if (!reader.TryAdvanceTo((byte)' ', advancePastDelimiter: true))
|
||||||
if (spaceIdx < 0)
|
|
||||||
throw new ProtocolViolationException("Invalid CONNECT");
|
throw new ProtocolViolationException("Invalid CONNECT");
|
||||||
|
|
||||||
var json = line[(spaceIdx + 1)..];
|
var json = line.Slice(reader.Position);
|
||||||
return new ParsedCommandView
|
return new ParsedCommandView
|
||||||
{
|
{
|
||||||
Type = CommandType.Connect,
|
Type = CommandType.Connect,
|
||||||
Operation = "CONNECT",
|
Operation = "CONNECT",
|
||||||
Payload = new ReadOnlySequence<byte>(json.ToArray()),
|
Payload = json,
|
||||||
MaxMessages = -1,
|
MaxMessages = -1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ParsedCommandView ParseInfo(Span<byte> line)
|
private static ParsedCommandView ParseInfo(ReadOnlySequence<byte> line)
|
||||||
{
|
{
|
||||||
// INFO {json} -- find first space after command
|
var reader = new SequenceReader<byte>(line);
|
||||||
int spaceIdx = line.IndexOf((byte)' ');
|
if (!reader.TryAdvanceTo((byte)' ', advancePastDelimiter: true))
|
||||||
if (spaceIdx < 0)
|
|
||||||
throw new ProtocolViolationException("Invalid INFO");
|
throw new ProtocolViolationException("Invalid INFO");
|
||||||
|
|
||||||
var json = line[(spaceIdx + 1)..];
|
var json = line.Slice(reader.Position);
|
||||||
return new ParsedCommandView
|
return new ParsedCommandView
|
||||||
{
|
{
|
||||||
Type = CommandType.Info,
|
Type = CommandType.Info,
|
||||||
Operation = "INFO",
|
Operation = "INFO",
|
||||||
Payload = new ReadOnlySequence<byte>(json.ToArray()),
|
Payload = json,
|
||||||
MaxMessages = -1,
|
MaxMessages = -1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user