From 367e02261c6bee9bce37cb6942bd6cbf743fb67c Mon Sep 17 00:00:00 2001 From: csharptest Date: Thu, 9 Jun 2011 12:47:46 -0500 Subject: Performance tweek for reading entire unpacked array --- src/ProtocolBuffers/CodedInputStream.cs | 108 +++++++++++++++++++++++++++----- 1 file changed, 92 insertions(+), 16 deletions(-) (limited to 'src/ProtocolBuffers/CodedInputStream.cs') diff --git a/src/ProtocolBuffers/CodedInputStream.cs b/src/ProtocolBuffers/CodedInputStream.cs index 000065bd..1fea7346 100644 --- a/src/ProtocolBuffers/CodedInputStream.cs +++ b/src/ProtocolBuffers/CodedInputStream.cs @@ -67,6 +67,9 @@ namespace Google.ProtocolBuffers private readonly Stream input; private uint lastTag = 0; + private uint nextTag = 0; + private bool hasNextTag = false; + internal const int DefaultRecursionLimit = 64; internal const int DefaultSizeLimit = 64 << 20; // 64MB public const int BufferSize = 4096; @@ -163,6 +166,26 @@ namespace Google.ProtocolBuffers #region Reading of tags etc + /// + /// Attempt to peek at the next field tag. + /// + [CLSCompliant(false)] + public bool PeekNextTag(out uint fieldTag, out string fieldName) + { + if (hasNextTag) + { + fieldName = null; + fieldTag = nextTag; + return true; + } + + uint savedLast = lastTag; + hasNextTag = ReadTag(out nextTag, out fieldName); + lastTag = savedLast; + fieldTag = nextTag; + return hasNextTag; + } + /// /// Attempt to read a field tag, returning false if we have reached the end /// of the input data. @@ -183,6 +206,13 @@ namespace Google.ProtocolBuffers { fieldName = null; + if (hasNextTag) + { + lastTag = fieldTag = nextTag; + hasNextTag = false; + return true; + } + if (IsAtEnd) { lastTag = fieldTag = 0; @@ -483,6 +513,24 @@ namespace Google.ProtocolBuffers return true; } + /// + /// Returns true if the next tag is also part of the same unpacked array + /// + private bool ContinueArray(uint currentTag) + { + string ignore; + uint next; + if (PeekNextTag(out next, out ignore)) + { + if (next == currentTag) + { + hasNextTag = false; + return true; + } + } + return false; + } + [CLSCompliant(false)] public void ReadPrimitiveArray(FieldType fieldType, uint fieldTag, string fieldName, ICollection list) { @@ -505,8 +553,12 @@ namespace Google.ProtocolBuffers else { Object value = null; - if (ReadPrimitiveField(fieldType, ref value)) - list.Add((T)value); + do + { + if (ReadPrimitiveField(fieldType, ref value)) + list.Add((T)value); + } + while (ContinueArray(fieldTag)); } } @@ -538,10 +590,18 @@ namespace Google.ProtocolBuffers } else { - if (ReadEnum(ref value, out unkval, mapping)) - list.Add(value); - else - unknown = new object[] { unkval }; + do + { + if (ReadEnum(ref value, out unkval, mapping)) + list.Add(value); + else + { + if (unknown == null) + unknown = new List(); + unknown.Add(unkval); + } + } + while (ContinueArray(fieldTag)); } } @@ -574,27 +634,43 @@ namespace Google.ProtocolBuffers } else { - if (ReadEnum(ref value, out unkval)) - list.Add(value); - else - unknown = new object[] { unkval }; + do + { + if (ReadEnum(ref value, out unkval)) + list.Add(value); + else + { + if (unknown == null) + unknown = new List(); + unknown.Add(unkval); + } + } + while (ContinueArray(fieldTag)); } } [CLSCompliant(false)] public void ReadMessageArray(uint fieldTag, string fieldName, ICollection list, T messageType, ExtensionRegistry registry) where T : IMessageLite { - IBuilderLite builder = messageType.WeakCreateBuilderForType(); - ReadMessage(builder, registry); - list.Add((T)builder.WeakBuildPartial()); + do + { + IBuilderLite builder = messageType.WeakCreateBuilderForType(); + ReadMessage(builder, registry); + list.Add((T)builder.WeakBuildPartial()); + } + while (ContinueArray(fieldTag)); } [CLSCompliant(false)] public void ReadGroupArray(uint fieldTag, string fieldName, ICollection list, T messageType, ExtensionRegistry registry) where T : IMessageLite { - IBuilderLite builder = messageType.WeakCreateBuilderForType(); - ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry); - list.Add((T)builder.WeakBuildPartial()); + do + { + IBuilderLite builder = messageType.WeakCreateBuilderForType(); + ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry); + list.Add((T)builder.WeakBuildPartial()); + } + while (ContinueArray(fieldTag)); } /// -- cgit v1.2.3