Optimise network reading - only need to move memory after all pending packets are processed, not after each field.

This commit is contained in:
UnknownShadow200 2016-02-29 14:43:31 +11:00
parent 04ade22693
commit d16ba9bfc6
5 changed files with 54 additions and 58 deletions

View File

@ -469,16 +469,15 @@ namespace ClassicalSharp {
int count = reader.ReadUInt8() + 1; int count = reader.ReadUInt8() + 1;
if( game.Map.IsNotLoaded ) { if( game.Map.IsNotLoaded ) {
Utils.LogDebug( "Server tried to update a block while still sending us the map!" ); Utils.LogDebug( "Server tried to update a block while still sending us the map!" );
reader.Remove( bulkCount * (sizeof(int) + 1) ); reader.Skip( bulkCount * (sizeof(int) + 1) );
return; return;
} }
int* indices = stackalloc int[bulkCount]; int* indices = stackalloc int[bulkCount];
for( int i = 0; i < count; i++ ) for( int i = 0; i < count; i++ )
indices[i] = ReadInt32( reader.buffer, i * 4 ); indices[i] = reader.ReadInt32();
for( int i = 0; i < count; i++ ) { for( int i = 0; i < count; i++ ) {
byte block = reader.buffer[i + bulkCount * sizeof(int)]; byte block = reader.ReadUInt8();
Vector3I coords = game.Map.GetCoords( indices[i] ); Vector3I coords = game.Map.GetCoords( indices[i] );
if( coords.X < 0 ) { if( coords.X < 0 ) {
@ -487,12 +486,6 @@ namespace ClassicalSharp {
} }
game.UpdateBlock( coords.X, coords.Y, coords.Z, block ); game.UpdateBlock( coords.X, coords.Y, coords.Z, block );
} }
reader.Remove( bulkCount * (sizeof(int) + 1) );
}
static int ReadInt32( byte[] buffer, int offset ) {
return buffer[offset + 0] << 24 | buffer[offset + 1] << 16
| buffer[offset + 2] << 8 | buffer[offset + 3];
} }
void HandleSetTextColor() { void HandleSetTextColor() {

View File

@ -124,6 +124,7 @@ namespace ClassicalSharp {
HandleLevelInit(); HandleLevelInit();
int usedLength = reader.ReadInt16(); int usedLength = reader.ReadInt16();
gzippedMap.Position = 0; gzippedMap.Position = 0;
gzippedMap.Offset = reader.index;
gzippedMap.SetLength( usedLength ); gzippedMap.SetLength( usedLength );
if( gzipHeader.done || gzipHeader.ReadHeader( gzippedMap ) ) { if( gzipHeader.done || gzipHeader.ReadHeader( gzippedMap ) ) {
@ -140,7 +141,7 @@ namespace ClassicalSharp {
} }
} }
reader.Remove( 1024 ); reader.Skip( 1024 );
byte progress = reader.ReadUInt8(); byte progress = reader.ReadUInt8();
game.MapEvents.RaiseMapLoading( progress ); game.MapEvents.RaiseMapLoading( progress );
} }

View File

@ -77,11 +77,11 @@ namespace ClassicalSharp {
throw; throw;
} }
while( reader.size > 0 ) { while( (reader.size - reader.index) > 0 ) {
byte opcode = reader.buffer[0]; byte opcode = reader.buffer[reader.index];
// Workaround for older D3 servers which wrote one byte too many for HackControl packets. // Workaround for older D3 servers which wrote one byte too many for HackControl packets.
if( opcode == 0xFF && lastOpcode == PacketId.CpeHackControl ) { if( opcode == 0xFF && lastOpcode == PacketId.CpeHackControl ) {
reader.Remove( 1 ); reader.Skip( 1 );
game.LocalPlayer.jumpVel = 0.42f; // assume default jump height game.LocalPlayer.jumpVel = 0.42f; // assume default jump height
game.LocalPlayer.serverJumpVel = game.LocalPlayer.jumpVel; game.LocalPlayer.serverJumpVel = game.LocalPlayer.jumpVel;
continue; continue;
@ -90,13 +90,14 @@ namespace ClassicalSharp {
if( opcode >= maxHandledPacket ) { if( opcode >= maxHandledPacket ) {
ErrorHandler.LogError( "NetworkProcessor.Tick", ErrorHandler.LogError( "NetworkProcessor.Tick",
"received an invalid opcode of " + opcode ); "received an invalid opcode of " + opcode );
reader.Remove( 1 ); reader.Skip( 1 );
continue; continue;
} }
if( reader.size < packetSizes[opcode] ) break; if( (reader.size - reader.index) < packetSizes[opcode] ) break;
ReadPacket( opcode ); ReadPacket( opcode );
} }
reader.RemoveRead();
Player player = game.LocalPlayer; Player player = game.LocalPlayer;
if( receivedFirstPosition ) { if( receivedFirstPosition ) {
@ -134,7 +135,7 @@ namespace ClassicalSharp {
PacketId lastOpcode; PacketId lastOpcode;
void ReadPacket( byte opcode ) { void ReadPacket( byte opcode ) {
reader.Remove( 1 ); // remove opcode reader.Skip( 1 ); // remove opcode
lastOpcode = (PacketId)opcode; lastOpcode = (PacketId)opcode;
Action handler = handlers[opcode]; Action handler = handlers[opcode];
lastPacket = DateTime.UtcNow; lastPacket = DateTime.UtcNow;
@ -145,7 +146,7 @@ namespace ClassicalSharp {
} }
void SkipPacketData( PacketId opcode ) { void SkipPacketData( PacketId opcode ) {
reader.Remove( packetSizes[(byte)opcode] - 1 ); reader.Skip( packetSizes[(byte)opcode] - 1 );
} }
Action[] handlers; Action[] handlers;

View File

@ -8,23 +8,16 @@ namespace ClassicalSharp {
internal class FixedBufferStream : Stream { internal class FixedBufferStream : Stream {
public byte[] _buffer; public byte[] _buffer;
int _position, _length; int _position, _length;
public int Offset;
public override bool CanRead { public override bool CanRead { get { return true; } }
get { return true; }
}
public override bool CanSeek { public override bool CanSeek { get { return false; } }
get { return false; }
}
public override bool CanWrite { public override bool CanWrite { get { return false; } }
get { return false; }
}
public override long Length { public override long Length { get { return _length; } }
get { return _length; }
}
public override long Position { public override long Position {
get { return _position; } get { return _position; }
@ -35,22 +28,23 @@ namespace ClassicalSharp {
_buffer = buffer; _buffer = buffer;
} }
public override void Flush() { public override void Flush() { }
}
public override int Read( byte[] buffer, int offset, int count ) { public override int Read( byte[] buffer, int offset, int count ) {
int numBytes = _length - _position; int numBytes = _length - _position;
if( numBytes > count ) numBytes = count; if( numBytes > count ) numBytes = count;
if( numBytes <= 0 ) return 0; if( numBytes <= 0 ) return 0;
Buffer.BlockCopy( _buffer, _position, buffer, offset, numBytes ); Buffer.BlockCopy( _buffer, Offset + _position, buffer, offset, numBytes );
_position += numBytes; _position += numBytes;
return numBytes; return numBytes;
} }
public override int ReadByte() { public override int ReadByte() {
if( _position >= _length ) return -1; if( _position >= _length ) return -1;
return _buffer[_position++]; byte value = _buffer[Offset + _position];
_position++;
return value;
} }
public override long Seek( long offset, SeekOrigin origin ) { public override long Seek( long offset, SeekOrigin origin ) {

View File

@ -6,7 +6,7 @@ namespace ClassicalSharp {
internal class NetReader { internal class NetReader {
public byte[] buffer = new byte[4096 * 5]; public byte[] buffer = new byte[4096 * 5];
public int size = 0; public int index = 0, size = 0;
public NetworkStream Stream; public NetworkStream Stream;
public NetReader( NetworkStream stream ) { public NetReader( NetworkStream stream ) {
@ -21,52 +21,59 @@ namespace ClassicalSharp {
size += received; size += received;
} }
public void Remove( int byteCount ) { public void Skip( int byteCount ) {
size -= byteCount; index += byteCount;
Buffer.BlockCopy( buffer, byteCount, buffer, 0, size ); }
public void RemoveProcessed() {
size -= index;
if( size > 0 ) // only copy left over bytes
Buffer.BlockCopy( buffer, index, buffer, 0, size );
index = 0;
// We don't need to zero the old bytes, since they will be overwritten when ReadData() is called. // We don't need to zero the old bytes, since they will be overwritten when ReadData() is called.
} }
public int ReadInt32() { public int ReadInt32() {
int value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3]; int value = buffer[index] << 24 | buffer[index + 1] << 16 |
Remove( 4 ); buffer[index + 2] << 8 | buffer[index + 3];
index += 4;
return value; return value;
} }
public short ReadInt16() { public short ReadInt16() {
short value = (short)( buffer[0] << 8 | buffer[1] ); short value = (short)(buffer[index] << 8 | buffer[index + 1]);
Remove( 2 ); index += 2;
return value; return value;
} }
public sbyte ReadInt8() { public sbyte ReadInt8() {
sbyte value = (sbyte)buffer[0]; sbyte value = (sbyte)buffer[index];
Remove( 1 ); index++;
return value; return value;
} }
public byte ReadUInt8() { public byte ReadUInt8() {
byte value = buffer[0]; byte value = buffer[index];
Remove( 1 ); index++;
return value; return value;
} }
public byte[] ReadBytes( int length ) { public byte[] ReadBytes( int length ) {
byte[] data = new byte[length]; byte[] data = new byte[length];
Buffer.BlockCopy( buffer, 0, data, 0, length ); Buffer.BlockCopy( buffer, index, data, 0, length );
Remove( length ); index += length;
return data; return data;
} }
public string ReadCp437String() { public string ReadCp437String() {
int length = GetString( buffer, false ); int length = GetString( false );
Remove( 64 ); index += 64;
return new String( characters, 0, length ); return new String( characters, 0, length );
} }
public string ReadAsciiString() { public string ReadAsciiString() {
int length = GetString( buffer, true ); int length = GetString( true );
Remove( 64 ); index += 64;
return new String( characters, 0, length ); return new String( characters, 0, length );
} }
@ -75,8 +82,8 @@ namespace ClassicalSharp {
return ReadCp437String(); return ReadCp437String();
messageType = (byte)MessageType.Normal; messageType = (byte)MessageType.Normal;
int length = GetString( buffer, false ); int length = GetString( false );
Remove( 64 ); index += 64;
int offset = 0; int offset = 0;
if( length >= womDetail.Length && IsWomDetailString() ) { if( length >= womDetail.Length && IsWomDetailString() ) {
@ -97,10 +104,10 @@ namespace ClassicalSharp {
return true; return true;
} }
static int GetString( byte[] data, bool ascii ) { int GetString( bool ascii ) {
int length = 0; int length = 0;
for( int i = 63; i >= 0; i-- ) { for( int i = 63; i >= 0; i-- ) {
byte code = data[i]; byte code = buffer[index + i];
if( length == 0 && !( code == 0 || code == 0x20 ) ) if( length == 0 && !( code == 0 || code == 0x20 ) )
length = i + 1; length = i + 1;