diff options
author | Jon Skeet <skeet@pobox.com> | 2015-06-17 14:59:10 +0100 |
---|---|---|
committer | Jon Skeet <skeet@pobox.com> | 2015-06-17 14:59:10 +0100 |
commit | 828b7e61d0443832d99002fbda12a359e5f9f221 (patch) | |
tree | 1f271cdb345b968dba08947b9319ba7d738f3476 /src | |
parent | fb1547b3884ace3be6acf9e947686d627ff90179 (diff) | |
download | protobuf-828b7e61d0443832d99002fbda12a359e5f9f221.tar.gz protobuf-828b7e61d0443832d99002fbda12a359e5f9f221.tar.bz2 protobuf-828b7e61d0443832d99002fbda12a359e5f9f221.zip |
Use the fact that we know the tag size and bytes at codegen time to optimize.
Diffstat (limited to 'src')
8 files changed, 77 insertions, 30 deletions
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 19fd50cf..af34f50c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -61,7 +61,8 @@ void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, (int) $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteEnum((int) $property_name$);\n" "}\n"); } @@ -69,7 +70,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n" "}\n"); } @@ -93,7 +94,8 @@ void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, (int) $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteEnum((int) $property_name$);\n" "}\n"); } @@ -101,7 +103,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeEnumSize((int) $property_name$);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index ec0d51ca..54f281ee 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -35,6 +35,7 @@ #include <google/protobuf/compiler/plugin.h> #include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.pb.h> +#include <google/protobuf/io/coded_stream.h> #include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream.h> #include <google/protobuf/stubs/strutil.h> @@ -55,8 +56,18 @@ void FieldGeneratorBase::SetCommonFieldVariables( // Note: this will be valid even though the tag emitted for packed and unpacked versions of // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which // never effects the tag size. - int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); - (*variables)["tag_size"] = SimpleItoa(tagSize); + int tag_size = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + uint tag = internal::WireFormat::MakeTag(descriptor_); + uint8 tag_array[5]; + io::CodedOutputStream::WriteTagToArray(tag, tag_array); + string tag_bytes = SimpleItoa(tag_array[0]); + for (int i = 1; i < tag_size; i++) { + tag_bytes += ", " + SimpleItoa(tag_array[i]); + } + + (*variables)["tag_size"] = SimpleItoa(tag_size); + (*variables)["tag_bytes"] = tag_bytes; + (*variables)["property_name"] = property_name(); (*variables)["type_name"] = type_name(); (*variables)["name"] = name(); diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 804a5ae2..bd67aa0f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -92,11 +92,11 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { } void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { - // TODO(jonskeet): Why are we using array access instead of a literal here? printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteMessage($number$, $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.WriteMessage($property_name$);\n" "}\n"); } @@ -104,7 +104,7 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeMessageSize($number$, $property_name$);\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeMessageSize($property_name$);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index 0164cdca..5820eb37 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -105,16 +105,29 @@ void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.Write$capitalized_type_name$($number$, $property_name$);\n" + " output.WriteRawTag($tag_bytes$);\n" + " output.Write$capitalized_type_name$($property_name$);\n" "}\n"); } void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.Compute$capitalized_type_name$Size($number$, $property_name$);\n" - "}\n"); + "if ($has_property_check$) {\n"); + printer->Indent(); + int fixedSize = GetFixedSize(descriptor_->type()); + if (fixedSize == -1) { + printer->Print( + variables_, + "size += $tag_size$ + pb::CodedOutputStream.Compute$capitalized_type_name$Size($property_name$);\n"); + } else { + printer->Print( + "size += $tag_size$ + $fixed_size$;\n", + "fixed_size", SimpleItoa(fixedSize), + "tag_size", variables_["tag_size"]); + } + printer->Outdent(); + printer->Print("}\n"); } void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { @@ -173,7 +186,7 @@ void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$property_name$ = input.Read$capitalized_type_name$()\n;"); + "$property_name$ = input.Read$capitalized_type_name$();\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index 22dec710..c78aaef6 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -82,9 +82,20 @@ void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, - "if ($name$_.Count > 0) {\n" - " output.Write$packed$EnumArray($number$, $name$_);\n" - "}\n"); + "if ($name$_.Count > 0) {\n"); + printer->Indent(); + if (descriptor_->is_packed()) { + printer->Print( + variables_, + "output.WriteRawTag($tag_bytes$);\n" + "output.WritePackedEnumArray($name$_);\n"); + } else { + printer->Print( + variables_, + "output.Write$capitalized_type_name$Array($number$, $name$_);\n"); + } + printer->Outdent(); + printer->Print("}\n"); } void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { @@ -97,14 +108,13 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer printer->Print( variables_, "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" + " dataSize += pb::CodedOutputStream.ComputeEnumSize((int) element);\n" "}\n" "size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); if (descriptor_->is_packed()) { printer->Print( - "size += $tag_size$;\n" - "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n", + "size += $tag_size$ + pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n", "tag_size", SimpleItoa(tagSize)); } else { printer->Print( diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 4b570d3b..3553fe12 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -79,8 +79,8 @@ void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { - // TODO(jonskeet): Originally, this checked for Count > 0 first. - // The Write* call should make that cheap though - no need to generate it every time. + // TODO(jonskeet): Bake the foreach loop into the generated code? We lose the + // advantage of knowing the tag bytes this way :( printer->Print( variables_, "if ($name$_.Count > 0) {\n" @@ -89,13 +89,13 @@ void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* print } void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { - // TODO(jonskeet): Put this into CodedOutputStream. printer->Print( variables_, "if ($name$_.Count > 0) {\n" " foreach ($type_name$ element in $name$_) {\n" - " size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n" + " size += pb::CodedOutputStream.ComputeMessageSize(element);\n" " }\n" + " size += $tag_size$ * $name$_.Count;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index a5457785..fe8a4364 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -82,9 +82,20 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( io::Printer* printer) { printer->Print( variables_, - "if ($name$_.Count > 0) {\n" - " output.Write$packed$$capitalized_type_name$Array($number$, $name$_);\n" - "}\n"); + "if ($name$_.Count > 0) {\n"); + printer->Indent(); + if (descriptor_->is_packed()) { + printer->Print( + variables_, + "output.WriteRawTag($tag_bytes$);\n" + "output.WritePacked$capitalized_type_name$Array($name$_);\n"); + } else { + printer->Print( + variables_, + "output.Write$capitalized_type_name$Array($number$, $name$_);\n"); + } + printer->Outdent(); + printer->Print("}\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( @@ -100,7 +111,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( printer->Print( variables_, "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n" + " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$Size(element);\n" "}\n"); } else { printer->Print( @@ -111,7 +122,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); if (descriptor_->is_packed()) { printer->Print( - "size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n", + "size += $tag_size$ + pb::CodedOutputStream.ComputeInt32Size(dataSize);\n", "tag_size", SimpleItoa(tagSize)); } else { printer->Print( diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index 8de491a6..84270fee 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h @@ -290,7 +290,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper { inline WireFormatLite::WireType WireFormat::WireTypeForField( const FieldDescriptor* field) { - if (field->options().packed()) { + if (field->is_packed()) { return WireFormatLite::WIRETYPE_LENGTH_DELIMITED; } else { return WireTypeForFieldType(field->type()); |