diff options
author | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2010-02-01 17:41:59 +0000 |
---|---|---|
committer | kenton@google.com <kenton@google.com@630680e5-0e50-0410-840e-4b1c322b438d> | 2010-02-01 17:41:59 +0000 |
commit | daee05168eb0f2cf102b7ef80c0af87c80729612 (patch) | |
tree | 9315d4071b5a7c9dc8501efb8ddb1f1d0bf09b3b /src | |
parent | ab6950d75d6bae6a1574726ee1e7060e001ed23a (diff) | |
download | protobuf-daee05168eb0f2cf102b7ef80c0af87c80729612.tar.gz protobuf-daee05168eb0f2cf102b7ef80c0af87c80729612.tar.bz2 protobuf-daee05168eb0f2cf102b7ef80c0af87c80729612.zip |
Optimize Java string serialization. Patch from Evan Jones.
Diffstat (limited to 'src')
-rw-r--r-- | src/google/protobuf/compiler/java/java_primitive_field.cc | 58 | ||||
-rw-r--r-- | src/google/protobuf/compiler/java/java_primitive_field.h | 2 |
2 files changed, 51 insertions, 9 deletions
diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index f6179bfa..d0fd081f 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -199,6 +199,14 @@ GenerateMembers(io::Printer* printer) const { "private $type$ $name$_ = $default$;\n" "public boolean has$capitalized_name$() { return has$capitalized_name$; }\n" "public $type$ get$capitalized_name$() { return $name$_; }\n"); + // Avoid double encoding for Java strings + // This field does not need to be volatile because ByteString is immutable. + // http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#finalRight + // However, it seems better to be safe than sorry. + if (ShouldUseStringEncodingCache()) { + printer->Print(variables_, + "private volatile com.google.protobuf.ByteString $name$EncodedCache_;\n"); + } } void PrimitiveFieldGenerator:: @@ -259,25 +267,57 @@ GenerateParsingCode(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { - printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " output.write$capitalized_type$($number$, get$capitalized_name$());\n" - "}\n"); + if (ShouldUseStringEncodingCache()) { + // Pass the cached serialized version, then forget it. + // The cached version could be null if we didn't compute the size first, + // or if there are two threads attempting to serialize simultaneously. + // CodedOutputStream.writeStringCached handles this for us. + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " output.write$capitalized_type$Cached($number$,\n" + " get$capitalized_name$(),\n" + " $name$EncodedCache_);\n" + " $name$EncodedCache_ = null;\n" + "}\n"); + } else { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " output.write$capitalized_type$($number$, get$capitalized_name$());\n" + "}\n"); + } } void PrimitiveFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { - printer->Print(variables_, - "if (has$capitalized_name$()) {\n" - " size += com.google.protobuf.CodedOutputStream\n" - " .compute$capitalized_type$Size($number$, get$capitalized_name$());\n" - "}\n"); + // Avoid double encoding for strings: serialize the string here + if (ShouldUseStringEncodingCache()) { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " com.google.protobuf.ByteString serialized = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " get$capitalized_name$());\n" + " $name$EncodedCache_ = serialized;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSize($number$, serialized);\n" + "}\n"); + } else { + printer->Print(variables_, + "if (has$capitalized_name$()) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$Size($number$, get$capitalized_name$());\n" + "}\n"); + } } string PrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } +bool PrimitiveFieldGenerator::ShouldUseStringEncodingCache() const { + return GetType(descriptor_) == FieldDescriptor::TYPE_STRING && + descriptor_->file()->options().optimize_for() == FileOptions::SPEED; +} + // =================================================================== RepeatedPrimitiveFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h index 4e482a05..9d6c3d5f 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.h +++ b/src/google/protobuf/compiler/java/java_primitive_field.h @@ -62,6 +62,8 @@ class PrimitiveFieldGenerator : public FieldGenerator { string GetBoxedType() const; private: + bool ShouldUseStringEncodingCache() const; + const FieldDescriptor* descriptor_; map<string, string> variables_; |