From c671a4b317fbc77dab57a18d64a67a11d0558378 Mon Sep 17 00:00:00 2001 From: csharptest Date: Wed, 8 Jun 2011 11:51:24 -0500 Subject: A few performance tweaks of the ICodedOutputStream interface/implementation --- src/ProtocolBuffers/CodedOutputStream.cs | 395 ++++++++++++++++++++++++------- 1 file changed, 311 insertions(+), 84 deletions(-) (limited to 'src/ProtocolBuffers/CodedOutputStream.cs') diff --git a/src/ProtocolBuffers/CodedOutputStream.cs b/src/ProtocolBuffers/CodedOutputStream.cs index 39523c96..31032058 100644 --- a/src/ProtocolBuffers/CodedOutputStream.cs +++ b/src/ProtocolBuffers/CodedOutputStream.cs @@ -35,6 +35,7 @@ #endregion using System; +using System.Collections.Generic; using System.Globalization; using System.IO; using System.Text; @@ -315,23 +316,103 @@ namespace Google.ProtocolBuffers WriteBytes(WireFormat.MessageSetField.Message, "message", value); WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup); } - + public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, System.Collections.IEnumerable list) { foreach (object element in list) WriteField(fieldType, fieldNumber, fieldName, element); } + public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, System.Collections.Generic.IEnumerable list) + { + switch (fieldType) + { + case FieldType.String: + foreach (string value in ((IEnumerable)list)) + WriteString(fieldNumber, fieldName, value); + break; + case FieldType.Message: + foreach (T value in list) + WriteMessage(fieldNumber, fieldName, (IMessageLite)value); + break; + case FieldType.Group: + foreach (T value in list) + WriteGroup(fieldNumber, fieldName, (IMessageLite)value); + break; + case FieldType.Bytes: + foreach (ByteString value in ((IEnumerable)list)) + WriteBytes(fieldNumber, fieldName, value); + break; + case FieldType.Bool: + foreach (bool value in ((IEnumerable)list)) + WriteBool(fieldNumber, fieldName, value); + break; + case FieldType.Enum: + foreach (T value in list) + { + if (value is System.Enum) + WriteEnum(fieldNumber, fieldName, ((IConvertible)value).ToInt32(CultureInfo.InvariantCulture), null/*not used*/); + else + WriteEnum(fieldNumber, fieldName, ((IEnumLite)value).Number, null/*not used*/); + } + break; + case FieldType.Int32: + foreach (int value in ((IEnumerable)list)) + WriteInt32(fieldNumber, fieldName, value); + break; + case FieldType.Int64: + foreach (long value in ((IEnumerable)list)) + WriteInt64(fieldNumber, fieldName, value); + break; + case FieldType.UInt32: + foreach (uint value in ((IEnumerable)list)) + WriteUInt32(fieldNumber, fieldName, value); + break; + case FieldType.UInt64: + foreach (ulong value in ((IEnumerable)list)) + WriteUInt64(fieldNumber, fieldName, value); + break; + case FieldType.SInt32: + foreach (int value in ((IEnumerable)list)) + WriteSInt32(fieldNumber, fieldName, value); + break; + case FieldType.SInt64: + foreach (long value in ((IEnumerable)list)) + WriteSInt64(fieldNumber, fieldName, value); + break; + case FieldType.Fixed32: + foreach (uint value in ((IEnumerable)list)) + WriteFixed32(fieldNumber, fieldName, value); + break; + case FieldType.Fixed64: + foreach (ulong value in ((IEnumerable)list)) + WriteFixed64(fieldNumber, fieldName, value); + break; + case FieldType.SFixed32: + foreach (int value in ((IEnumerable)list)) + WriteSFixed32(fieldNumber, fieldName, value); + break; + case FieldType.SFixed64: + foreach (long value in ((IEnumerable)list)) + WriteSFixed64(fieldNumber, fieldName, value); + break; + case FieldType.Double: + foreach (double value in ((IEnumerable)list)) + WriteDouble(fieldNumber, fieldName, value); + break; + case FieldType.Float: + foreach (float value in ((IEnumerable)list)) + WriteFloat(fieldNumber, fieldName, value); + break; + } + } + public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, System.Collections.IEnumerable list) { int calculatedSize = 0; foreach (object element in list) calculatedSize += CodedOutputStream.ComputeFieldSizeNoTag(fieldType, element); - WritePackedArray(fieldType, fieldNumber, fieldName, calculatedSize, list); - } - - public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, int calculatedSize, System.Collections.IEnumerable list) - { + WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); WriteRawVarint32((uint)calculatedSize); @@ -339,66 +420,153 @@ namespace Google.ProtocolBuffers WriteFieldNoTag(fieldType, element); } - public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value) + public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, int calculatedSize, System.Collections.Generic.IEnumerable list) { + WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); + WriteRawVarint32((uint)calculatedSize); + switch (fieldType) { - case FieldType.Double: - WriteDouble(fieldNumber, fieldName, (double) value); + case FieldType.String: + foreach (string value in ((IEnumerable)list)) + WriteStringNoTag(value); break; - case FieldType.Float: - WriteFloat(fieldNumber, fieldName, (float) value); + case FieldType.Message: + foreach (T value in list) + WriteMessageNoTag((IMessageLite)value); + break; + case FieldType.Group: + foreach (T value in list) + WriteGroupNoTag((IMessageLite)value); + break; + case FieldType.Bytes: + foreach (ByteString value in ((IEnumerable)list)) + WriteBytesNoTag(value); + break; + case FieldType.Bool: + foreach (bool value in ((IEnumerable)list)) + WriteBoolNoTag(value); + break; + case FieldType.Enum: + foreach (T value in list) + { + if (value is System.Enum) + WriteEnumNoTag(((IConvertible)value).ToInt32(CultureInfo.InvariantCulture)); + else + WriteEnumNoTag(((IEnumLite)value).Number); + } + break; + case FieldType.Int32: + foreach (int value in ((IEnumerable)list)) + WriteInt32NoTag(value); break; case FieldType.Int64: - WriteInt64(fieldNumber, fieldName, (long) value); + foreach (long value in ((IEnumerable)list)) + WriteInt64NoTag(value); + break; + case FieldType.UInt32: + foreach (uint value in ((IEnumerable)list)) + WriteUInt32NoTag(value); break; case FieldType.UInt64: - WriteUInt64(fieldNumber, fieldName, (ulong) value); + foreach (ulong value in ((IEnumerable)list)) + WriteUInt64NoTag(value); break; - case FieldType.Int32: - WriteInt32(fieldNumber, fieldName, (int) value); + case FieldType.SInt32: + foreach (int value in ((IEnumerable)list)) + WriteSInt32NoTag(value); break; - case FieldType.Fixed64: - WriteFixed64(fieldNumber, fieldName, (ulong) value); + case FieldType.SInt64: + foreach (long value in ((IEnumerable)list)) + WriteSInt64NoTag(value); break; case FieldType.Fixed32: - WriteFixed32(fieldNumber, fieldName, (uint) value); + foreach (uint value in ((IEnumerable)list)) + WriteFixed32NoTag(value); break; - case FieldType.Bool: - WriteBool(fieldNumber, fieldName, (bool) value); + case FieldType.Fixed64: + foreach (ulong value in ((IEnumerable)list)) + WriteFixed64NoTag(value); break; - case FieldType.String: - WriteString(fieldNumber, fieldName, (string) value); + case FieldType.SFixed32: + foreach (int value in ((IEnumerable)list)) + WriteSFixed32NoTag(value); break; - case FieldType.Group: - WriteGroup(fieldNumber, fieldName, (IMessageLite) value); + case FieldType.SFixed64: + foreach (long value in ((IEnumerable)list)) + WriteSFixed64NoTag(value); + break; + case FieldType.Double: + foreach (double value in ((IEnumerable)list)) + WriteDoubleNoTag(value); + break; + case FieldType.Float: + foreach (float value in ((IEnumerable)list)) + WriteFloatNoTag(value); + break; + } + } + + public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value) + { + switch (fieldType) + { + case FieldType.String: + WriteString(fieldNumber, fieldName, (string)value); break; case FieldType.Message: - WriteMessage(fieldNumber, fieldName, (IMessageLite) value); + WriteMessage(fieldNumber, fieldName, (IMessageLite)value); + break; + case FieldType.Group: + WriteGroup(fieldNumber, fieldName, (IMessageLite)value); break; case FieldType.Bytes: - WriteBytes(fieldNumber, fieldName, (ByteString) value); + WriteBytes(fieldNumber, fieldName, (ByteString)value); + break; + case FieldType.Bool: + WriteBool(fieldNumber, fieldName, (bool)value); + break; + case FieldType.Enum: + if (value is System.Enum) + WriteEnum(fieldNumber, fieldName, ((IConvertible)value).ToInt32(CultureInfo.InvariantCulture), null/*not used*/); + else + WriteEnum(fieldNumber, fieldName, ((IEnumLite)value).Number, null/*not used*/); + break; + case FieldType.Int32: + WriteInt32(fieldNumber, fieldName, (int) value); + break; + case FieldType.Int64: + WriteInt64(fieldNumber, fieldName, (long) value); break; case FieldType.UInt32: WriteUInt32(fieldNumber, fieldName, (uint) value); break; + case FieldType.UInt64: + WriteUInt64(fieldNumber, fieldName, (ulong) value); + break; + case FieldType.SInt32: + WriteSInt32(fieldNumber, fieldName, (int)value); + break; + case FieldType.SInt64: + WriteSInt64(fieldNumber, fieldName, (long)value); + break; + case FieldType.Fixed32: + WriteFixed32(fieldNumber, fieldName, (uint) value); + break; + case FieldType.Fixed64: + WriteFixed64(fieldNumber, fieldName, (ulong) value); + break; case FieldType.SFixed32: WriteSFixed32(fieldNumber, fieldName, (int) value); break; case FieldType.SFixed64: WriteSFixed64(fieldNumber, fieldName, (long) value); break; - case FieldType.SInt32: - WriteSInt32(fieldNumber, fieldName, (int) value); - break; - case FieldType.SInt64: - WriteSInt64(fieldNumber, fieldName, (long) value); + case FieldType.Double: + WriteDouble(fieldNumber, fieldName, (double)value); break; - case FieldType.Enum: - if(value is System.Enum) - WriteEnum(fieldNumber, fieldName, ((IConvertible)value).ToInt32(CultureInfo.InvariantCulture), null/*not used*/); - else - WriteEnum(fieldNumber, fieldName, ((IEnumLite) value).Number, null/*not used*/); + case FieldType.Float: + WriteFloat(fieldNumber, fieldName, (float)value); break; } } @@ -407,44 +575,50 @@ namespace Google.ProtocolBuffers { switch (fieldType) { - case FieldType.Double: - WriteDoubleNoTag((double) value); + case FieldType.String: + WriteStringNoTag((string)value); break; - case FieldType.Float: - WriteFloatNoTag((float) value); + case FieldType.Message: + WriteMessageNoTag((IMessageLite)value); break; - case FieldType.Int64: - WriteInt64NoTag((long) value); + case FieldType.Group: + WriteGroupNoTag((IMessageLite)value); break; - case FieldType.UInt64: - WriteUInt64NoTag((ulong) value); + case FieldType.Bytes: + WriteBytesNoTag((ByteString)value); + break; + case FieldType.Bool: + WriteBoolNoTag((bool)value); + break; + case FieldType.Enum: + if (value is System.Enum) + WriteEnumNoTag(((IConvertible)value).ToInt32(CultureInfo.InvariantCulture)); + else + WriteEnumNoTag(((IEnumLite)value).Number); break; case FieldType.Int32: WriteInt32NoTag((int) value); break; - case FieldType.Fixed64: - WriteFixed64NoTag((ulong) value); - break; - case FieldType.Fixed32: - WriteFixed32NoTag((uint) value); + case FieldType.Int64: + WriteInt64NoTag((long) value); break; - case FieldType.Bool: - WriteBoolNoTag((bool) value); + case FieldType.UInt32: + WriteUInt32NoTag((uint) value); break; - case FieldType.String: - WriteStringNoTag((string) value); + case FieldType.UInt64: + WriteUInt64NoTag((ulong) value); break; - case FieldType.Group: - WriteGroupNoTag((IMessageLite) value); + case FieldType.SInt32: + WriteSInt32NoTag((int) value); break; - case FieldType.Message: - WriteMessageNoTag((IMessageLite) value); + case FieldType.SInt64: + WriteSInt64NoTag((long) value); break; - case FieldType.Bytes: - WriteBytesNoTag((ByteString) value); + case FieldType.Fixed32: + WriteFixed32NoTag((uint) value); break; - case FieldType.UInt32: - WriteUInt32NoTag((uint) value); + case FieldType.Fixed64: + WriteFixed64NoTag((ulong) value); break; case FieldType.SFixed32: WriteSFixed32NoTag((int) value); @@ -452,17 +626,11 @@ namespace Google.ProtocolBuffers case FieldType.SFixed64: WriteSFixed64NoTag((long) value); break; - case FieldType.SInt32: - WriteSInt32NoTag((int) value); - break; - case FieldType.SInt64: - WriteSInt64NoTag((long) value); + case FieldType.Double: + WriteDoubleNoTag((double)value); break; - case FieldType.Enum: - if (value is System.Enum) - WriteEnumNoTag(((IConvertible)value).ToInt32(CultureInfo.InvariantCulture)); - else - WriteEnumNoTag(((IEnumLite) value).Number); + case FieldType.Float: + WriteFloatNoTag((float)value); break; } } @@ -641,6 +809,7 @@ namespace Google.ProtocolBuffers WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type)); } +#if false private void SlowWriteRawVarint32(uint value) { while (true) @@ -657,7 +826,7 @@ namespace Google.ProtocolBuffers } } } - +#endif /// /// Writes a 32 bit value as a varint. The fast route is taken when /// there's enough buffer space left to whizz through without checking @@ -666,6 +835,22 @@ namespace Google.ProtocolBuffers [CLSCompliant(false)] public void WriteRawVarint32(uint value) { +#if true + while (value > 127 && position < limit) + { + buffer[position++] = (byte)((value & 0x7F) | 0x80); + value >>= 7; + } + while (value > 127) + { + WriteRawByte((byte)((value & 0x7F) | 0x80)); + value >>= 7; + } + if(position < limit) + buffer[position++] = (byte)value; + else + WriteRawByte((byte)value); +#else if (position + 5 > limit) { SlowWriteRawVarint32(value); @@ -685,11 +870,28 @@ namespace Google.ProtocolBuffers value >>= 7; } } +#endif } [CLSCompliant(false)] public void WriteRawVarint64(ulong value) { +#if true + while (value > 127 && position < limit) + { + buffer[position++] = (byte)((value & 0x7F) | 0x80); + value >>= 7; + } + while (value > 127) + { + WriteRawByte((byte)((value & 0x7F) | 0x80)); + value >>= 7; + } + if(position < limit) + buffer[position++] = (byte)value; + else + WriteRawByte((byte)value); +#else while (true) { if ((value & ~0x7FUL) == 0) @@ -703,28 +905,53 @@ namespace Google.ProtocolBuffers value >>= 7; } } +#endif } [CLSCompliant(false)] public void WriteRawLittleEndian32(uint value) { - WriteRawByte((byte) value); - WriteRawByte((byte) (value >> 8)); - WriteRawByte((byte) (value >> 16)); - WriteRawByte((byte) (value >> 24)); + if (position + 4 > limit) + { + WriteRawByte((byte) value); + WriteRawByte((byte) (value >> 8)); + WriteRawByte((byte) (value >> 16)); + WriteRawByte((byte) (value >> 24)); + } + else + { + buffer[position++] = ((byte)value); + buffer[position++] = ((byte)(value >> 8)); + buffer[position++] = ((byte)(value >> 16)); + buffer[position++] = ((byte)(value >> 24)); + } } [CLSCompliant(false)] public void WriteRawLittleEndian64(ulong value) { - WriteRawByte((byte) value); - WriteRawByte((byte) (value >> 8)); - WriteRawByte((byte) (value >> 16)); - WriteRawByte((byte) (value >> 24)); - WriteRawByte((byte) (value >> 32)); - WriteRawByte((byte) (value >> 40)); - WriteRawByte((byte) (value >> 48)); - WriteRawByte((byte) (value >> 56)); + if (position + 8 > limit) + { + WriteRawByte((byte) value); + WriteRawByte((byte) (value >> 8)); + WriteRawByte((byte) (value >> 16)); + WriteRawByte((byte) (value >> 24)); + WriteRawByte((byte) (value >> 32)); + WriteRawByte((byte) (value >> 40)); + WriteRawByte((byte) (value >> 48)); + WriteRawByte((byte) (value >> 56)); + } + else + { + buffer[position++] = ((byte)value); + buffer[position++] = ((byte)(value >> 8)); + buffer[position++] = ((byte)(value >> 16)); + buffer[position++] = ((byte)(value >> 24)); + buffer[position++] = ((byte)(value >> 32)); + buffer[position++] = ((byte)(value >> 40)); + buffer[position++] = ((byte)(value >> 48)); + buffer[position++] = ((byte)(value >> 56)); + } } public void WriteRawByte(byte value) -- cgit v1.2.3