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;
if( game.Map.IsNotLoaded ) {
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;
}
}
int* indices = stackalloc int[bulkCount];
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++ ) {
byte block = reader.buffer[i + bulkCount * sizeof(int)];
byte block = reader.ReadUInt8();
Vector3I coords = game.Map.GetCoords( indices[i] );
if( coords.X < 0 ) {
@ -487,12 +486,6 @@ namespace ClassicalSharp {
}
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() {

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@ namespace ClassicalSharp {
internal class NetReader {
public byte[] buffer = new byte[4096 * 5];
public int size = 0;
public int index = 0, size = 0;
public NetworkStream Stream;
public NetReader( NetworkStream stream ) {
@ -21,52 +21,59 @@ namespace ClassicalSharp {
size += received;
}
public void Remove( int byteCount ) {
size -= byteCount;
Buffer.BlockCopy( buffer, byteCount, buffer, 0, size );
public void Skip( int byteCount ) {
index += byteCount;
}
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.
}
public int ReadInt32() {
int value = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
Remove( 4 );
int value = buffer[index] << 24 | buffer[index + 1] << 16 |
buffer[index + 2] << 8 | buffer[index + 3];
index += 4;
return value;
}
public short ReadInt16() {
short value = (short)( buffer[0] << 8 | buffer[1] );
Remove( 2 );
short value = (short)(buffer[index] << 8 | buffer[index + 1]);
index += 2;
return value;
}
public sbyte ReadInt8() {
sbyte value = (sbyte)buffer[0];
Remove( 1 );
sbyte value = (sbyte)buffer[index];
index++;
return value;
}
public byte ReadUInt8() {
byte value = buffer[0];
Remove( 1 );
byte value = buffer[index];
index++;
return value;
}
public byte[] ReadBytes( int length ) {
byte[] data = new byte[length];
Buffer.BlockCopy( buffer, 0, data, 0, length );
Remove( length );
Buffer.BlockCopy( buffer, index, data, 0, length );
index += length;
return data;
}
public string ReadCp437String() {
int length = GetString( buffer, false );
Remove( 64 );
int length = GetString( false );
index += 64;
return new String( characters, 0, length );
}
public string ReadAsciiString() {
int length = GetString( buffer, true );
Remove( 64 );
int length = GetString( true );
index += 64;
return new String( characters, 0, length );
}
@ -75,8 +82,8 @@ namespace ClassicalSharp {
return ReadCp437String();
messageType = (byte)MessageType.Normal;
int length = GetString( buffer, false );
Remove( 64 );
int length = GetString( false );
index += 64;
int offset = 0;
if( length >= womDetail.Length && IsWomDetailString() ) {
@ -97,10 +104,10 @@ namespace ClassicalSharp {
return true;
}
static int GetString( byte[] data, bool ascii ) {
int GetString( bool ascii ) {
int length = 0;
for( int i = 63; i >= 0; i-- ) {
byte code = data[i];
byte code = buffer[index + i];
if( length == 0 && !( code == 0 || code == 0x20 ) )
length = i + 1;