THRIFT-4318 Delphi performance improvements
Client: Delphi
Patch: Jens Geyer
This closes #1348
diff --git a/lib/delphi/src/Thrift.Protocol.Compact.pas b/lib/delphi/src/Thrift.Protocol.Compact.pas
index e9944d6..5b1253a 100644
--- a/lib/delphi/src/Thrift.Protocol.Compact.pas
+++ b/lib/delphi/src/Thrift.Protocol.Compact.pas
@@ -123,7 +123,7 @@
// If we encounter a boolean field begin, save the TField here so it can
// have the value incorporated.
- private booleanField_ : IField;
+ private booleanField_ : TThriftField;
// If we Read a field header, and it's a boolean field, save the boolean
// value here so that ReadBool can use it.
@@ -148,21 +148,21 @@
private
// The workhorse of WriteFieldBegin. It has the option of doing a 'type override'
// of the type header. This is used specifically in the boolean field case.
- procedure WriteFieldBeginInternal( const field : IField; typeOverride : Byte);
+ procedure WriteFieldBeginInternal( const field : TThriftField; typeOverride : Byte);
public
- procedure WriteMessageBegin( const msg: IMessage); override;
+ procedure WriteMessageBegin( const msg: TThriftMessage); override;
procedure WriteMessageEnd; override;
- procedure WriteStructBegin( const struc: IStruct); override;
+ procedure WriteStructBegin( const struc: TThriftStruct); override;
procedure WriteStructEnd; override;
- procedure WriteFieldBegin( const field: IField); override;
+ procedure WriteFieldBegin( const field: TThriftField); override;
procedure WriteFieldEnd; override;
procedure WriteFieldStop; override;
- procedure WriteMapBegin( const map: IMap); override;
+ procedure WriteMapBegin( const map: TThriftMap); override;
procedure WriteMapEnd; override;
- procedure WriteListBegin( const list: IList); override;
+ procedure WriteListBegin( const list: TThriftList); override;
procedure WriteListEnd(); override;
- procedure WriteSetBegin( const set_: ISet ); override;
+ procedure WriteSetBegin( const set_: TThriftSet ); override;
procedure WriteSetEnd(); override;
procedure WriteBool( b: Boolean); override;
procedure WriteByte( b: ShortInt); override;
@@ -194,17 +194,17 @@
class procedure fixedLongToBytes( const n : Int64; var buf : TBytes);
public
- function ReadMessageBegin: IMessage; override;
+ function ReadMessageBegin: TThriftMessage; override;
procedure ReadMessageEnd(); override;
- function ReadStructBegin: IStruct; override;
+ function ReadStructBegin: TThriftStruct; override;
procedure ReadStructEnd; override;
- function ReadFieldBegin: IField; override;
+ function ReadFieldBegin: TThriftField; override;
procedure ReadFieldEnd(); override;
- function ReadMapBegin: IMap; override;
+ function ReadMapBegin: TThriftMap; override;
procedure ReadMapEnd(); override;
- function ReadListBegin: IList; override;
+ function ReadListBegin: TThriftList; override;
procedure ReadListEnd(); override;
- function ReadSetBegin: ISet; override;
+ function ReadSetBegin: TThriftSet; override;
procedure ReadSetEnd(); override;
function ReadBool: Boolean; override;
function ReadByte: ShortInt; override;
@@ -273,7 +273,7 @@
lastFieldId_ := 0;
lastField_ := TStack<Integer>.Create;
- booleanField_ := nil;
+ Init( booleanField_, '', TType.Stop, 0);
boolValue_ := unused;
end;
@@ -293,7 +293,7 @@
begin
lastField_.Clear();
lastFieldId_ := 0;
- booleanField_ := nil;
+ Init( booleanField_, '', TType.Stop, 0);
boolValue_ := unused;
end;
@@ -301,11 +301,8 @@
// Writes a byte without any possibility of all that field header nonsense.
// Used internally by other writing methods that know they need to Write a byte.
procedure TCompactProtocolImpl.WriteByteDirect( const b : Byte);
-var data : TBytes;
begin
- SetLength( data, 1);
- data[0] := b;
- Transport.Write( data);
+ Transport.Write( @b, SizeOf(b));
end;
@@ -344,7 +341,7 @@
// Write a message header to the wire. Compact Protocol messages contain the
// protocol version so we can migrate forwards in the future if need be.
-procedure TCompactProtocolImpl.WriteMessageBegin( const msg: IMessage);
+procedure TCompactProtocolImpl.WriteMessageBegin( const msg: TThriftMessage);
var versionAndType : Byte;
begin
Reset;
@@ -362,7 +359,7 @@
// Write a struct begin. This doesn't actually put anything on the wire. We use it as an
// opportunity to put special placeholder markers on the field stack so we can get the
// field id deltas correct.
-procedure TCompactProtocolImpl.WriteStructBegin( const struc: IStruct);
+procedure TCompactProtocolImpl.WriteStructBegin( const struc: TThriftStruct);
begin
lastField_.Push(lastFieldId_);
lastFieldId_ := 0;
@@ -380,7 +377,7 @@
// Write a field header containing the field id and field type. If the difference between the
// current field id and the last one is small (< 15), then the field id will be encoded in
// the 4 MSB as a delta. Otherwise, the field id will follow the type header as a zigzag varint.
-procedure TCompactProtocolImpl.WriteFieldBegin( const field: IField);
+procedure TCompactProtocolImpl.WriteFieldBegin( const field: TThriftField);
begin
case field.Type_ of
TType.Bool_ : booleanField_ := field; // we want to possibly include the value, so we'll wait.
@@ -392,7 +389,7 @@
// The workhorse of WriteFieldBegin. It has the option of doing a 'type override'
// of the type header. This is used specifically in the boolean field case.
-procedure TCompactProtocolImpl.WriteFieldBeginInternal( const field : IField; typeOverride : Byte);
+procedure TCompactProtocolImpl.WriteFieldBeginInternal( const field : TThriftField; typeOverride : Byte);
var typeToWrite : Byte;
begin
// if there's a type override, use that.
@@ -425,7 +422,7 @@
// Write a map header. If the map is empty, omit the key and value type
// headers, as we don't need any additional information to skip it.
-procedure TCompactProtocolImpl.WriteMapBegin( const map: IMap);
+procedure TCompactProtocolImpl.WriteMapBegin( const map: TThriftMap);
var key, val : Byte;
begin
if (map.Count = 0)
@@ -440,14 +437,14 @@
// Write a list header.
-procedure TCompactProtocolImpl.WriteListBegin( const list: IList);
+procedure TCompactProtocolImpl.WriteListBegin( const list: TThriftList);
begin
WriteCollectionBegin( list.ElementType, list.Count);
end;
// Write a set header.
-procedure TCompactProtocolImpl.WriteSetBegin( const set_: ISet );
+procedure TCompactProtocolImpl.WriteSetBegin( const set_: TThriftSet );
begin
WriteCollectionBegin( set_.ElementType, set_.Count);
end;
@@ -464,10 +461,10 @@
then bt := Types.BOOLEAN_TRUE
else bt := Types.BOOLEAN_FALSE;
- if booleanField_ <> nil then begin
+ if booleanField_.Type_ = TType.Bool_ then begin
// we haven't written the field header yet
WriteFieldBeginInternal( booleanField_, Byte(bt));
- booleanField_ := nil;
+ booleanField_.Type_ := TType.Stop;
end
else begin
// we're not part of a field, so just Write the value.
@@ -642,7 +639,7 @@
// Read a message header.
-function TCompactProtocolImpl.ReadMessageBegin : IMessage;
+function TCompactProtocolImpl.ReadMessageBegin : TThriftMessage;
var protocolId, versionAndType, version, type_ : Byte;
seqid : Integer;
msgNm : String;
@@ -663,17 +660,17 @@
type_ := Byte( (versionAndType shr TYPE_SHIFT_AMOUNT) and TYPE_BITS);
seqid := Integer( ReadVarint32);
msgNm := ReadString;
- result := TMessageImpl.Create( msgNm, TMessageType(type_), seqid);
+ Init( result, msgNm, TMessageType(type_), seqid);
end;
// Read a struct begin. There's nothing on the wire for this, but it is our
// opportunity to push a new struct begin marker onto the field stack.
-function TCompactProtocolImpl.ReadStructBegin: IStruct;
+function TCompactProtocolImpl.ReadStructBegin: TThriftStruct;
begin
lastField_.Push( lastFieldId_);
lastFieldId_ := 0;
- result := TStructImpl.Create('');
+ Init( result);
end;
@@ -687,7 +684,7 @@
// Read a field header off the wire.
-function TCompactProtocolImpl.ReadFieldBegin: IField;
+function TCompactProtocolImpl.ReadFieldBegin: TThriftField;
var type_ : Byte;
fieldId, modifier : ShortInt;
begin
@@ -695,7 +692,7 @@
// if it's a stop, then we can return immediately, as the struct is over.
if type_ = Byte(Types.STOP) then begin
- result := TFieldImpl.Create( '', TType.Stop, 0);
+ Init( result, '', TType.Stop, 0);
Exit;
end;
@@ -705,7 +702,7 @@
then fieldId := ReadI16 // not a delta. look ahead for the zigzag varint field id.
else fieldId := ShortInt( lastFieldId_ + modifier); // add the delta to the last Read field id.
- result := TFieldImpl.Create( '', getTType(Byte(type_ and $0F)), fieldId);
+ Init( result, '', getTType(Byte(type_ and $0F)), fieldId);
// if this happens to be a boolean field, the value is encoded in the type
// save the boolean value in a special instance variable.
@@ -723,7 +720,7 @@
// Read a map header off the wire. If the size is zero, skip Reading the key
// and value type. This means that 0-length maps will yield TMaps without the
// "correct" types.
-function TCompactProtocolImpl.ReadMapBegin: IMap;
+function TCompactProtocolImpl.ReadMapBegin: TThriftMap;
var size : Integer;
keyAndValueType : Byte;
key, val : TType;
@@ -735,7 +732,7 @@
key := getTType( Byte( keyAndValueType shr 4));
val := getTType( Byte( keyAndValueType and $F));
- result := TMapImpl.Create( key, val, size);
+ Init( result, key, val, size);
ASSERT( (result.KeyType = key) and (result.ValueType = val));
end;
@@ -744,7 +741,7 @@
// be packed into the element type header. If it's a longer list, the 4 MSB
// of the element type header will be $F, and a varint will follow with the
// true size.
-function TCompactProtocolImpl.ReadListBegin: IList;
+function TCompactProtocolImpl.ReadListBegin: TThriftList;
var size_and_type : Byte;
size : Integer;
type_ : TType;
@@ -756,7 +753,7 @@
then size := Integer( ReadVarint32);
type_ := getTType( size_and_type);
- result := TListImpl.Create( type_, size);
+ Init( result, type_, size);
end;
@@ -764,7 +761,7 @@
// be packed into the element type header. If it's a longer set, the 4 MSB
// of the element type header will be $F, and a varint will follow with the
// true size.
-function TCompactProtocolImpl.ReadSetBegin: ISet;
+function TCompactProtocolImpl.ReadSetBegin: TThriftSet;
var size_and_type : Byte;
size : Integer;
type_ : TType;
@@ -776,7 +773,7 @@
then size := Integer( ReadVarint32);
type_ := getTType( size_and_type);
- result := TSetImpl.Create( type_, size);
+ Init( result, type_, size);
end;
@@ -797,11 +794,8 @@
// Read a single byte off the wire. Nothing interesting here.
function TCompactProtocolImpl.ReadByte: ShortInt;
-var data : TBytes;
begin
- SetLength( data, 1);
- Transport.ReadAll( data, 0, 1);
- result := ShortInt(data[0]);
+ Transport.ReadAll( @result, SizeOf(result), 0, 1);
end;