Java full runtime: Avoid allocating iterator if UnknownFieldSet's TreeMap is empty

I also considered using Collections.emptyNavigableMap(), which I thought might
use a specialized allocation free empty iterator, but it allocates, and its
clone() method isn't nicely exposed.

PiperOrigin-RevId: 630234849
pull/16695/head
Mark Hansen 7 months ago committed by Copybara-Service
parent cc79f776dc
commit 4f12891b87
  1. 26
      java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java

@ -102,6 +102,10 @@ public final class UnknownFieldSet implements MessageLite {
/** Serializes the set and writes it to {@code output}. */ /** Serializes the set and writes it to {@code output}. */
@Override @Override
public void writeTo(CodedOutputStream output) throws IOException { public void writeTo(CodedOutputStream output) throws IOException {
if (fields.isEmpty()) {
// Avoid allocating an iterator.
return;
}
for (Map.Entry<Integer, Field> entry : fields.entrySet()) { for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
Field field = entry.getValue(); Field field = entry.getValue();
field.writeTo(entry.getKey(), output); field.writeTo(entry.getKey(), output);
@ -174,16 +178,22 @@ public final class UnknownFieldSet implements MessageLite {
@Override @Override
public int getSerializedSize() { public int getSerializedSize() {
int result = 0; int result = 0;
if (!fields.isEmpty()) { if (fields.isEmpty()) {
// Avoid allocating an iterator.
return result;
}
for (Map.Entry<Integer, Field> entry : fields.entrySet()) { for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
result += entry.getValue().getSerializedSize(entry.getKey()); result += entry.getValue().getSerializedSize(entry.getKey());
} }
}
return result; return result;
} }
/** Serializes the set and writes it to {@code output} using {@code MessageSet} wire format. */ /** Serializes the set and writes it to {@code output} using {@code MessageSet} wire format. */
public void writeAsMessageSetTo(CodedOutputStream output) throws IOException { public void writeAsMessageSetTo(CodedOutputStream output) throws IOException {
if (fields.isEmpty()) {
// Avoid allocating an iterator.
return;
}
for (Map.Entry<Integer, Field> entry : fields.entrySet()) { for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), output); entry.getValue().writeAsMessageSetExtensionTo(entry.getKey(), output);
} }
@ -191,6 +201,10 @@ public final class UnknownFieldSet implements MessageLite {
/** Serializes the set and writes it to {@code writer}. */ /** Serializes the set and writes it to {@code writer}. */
void writeTo(Writer writer) throws IOException { void writeTo(Writer writer) throws IOException {
if (fields.isEmpty()) {
// Avoid allocating an iterator.
return;
}
if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) {
// Write fields in descending order. // Write fields in descending order.
for (Map.Entry<Integer, Field> entry : fields.descendingMap().entrySet()) { for (Map.Entry<Integer, Field> entry : fields.descendingMap().entrySet()) {
@ -206,6 +220,10 @@ public final class UnknownFieldSet implements MessageLite {
/** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */ /** Serializes the set and writes it to {@code writer} using {@code MessageSet} wire format. */
void writeAsMessageSetTo(Writer writer) throws IOException { void writeAsMessageSetTo(Writer writer) throws IOException {
if (fields.isEmpty()) {
// Avoid allocating an iterator.
return;
}
if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) { if (writer.fieldOrder() == Writer.FieldOrder.DESCENDING) {
// Write fields in descending order. // Write fields in descending order.
for (Map.Entry<Integer, Field> entry : fields.descendingMap().entrySet()) { for (Map.Entry<Integer, Field> entry : fields.descendingMap().entrySet()) {
@ -222,6 +240,10 @@ public final class UnknownFieldSet implements MessageLite {
/** Get the number of bytes required to encode this set using {@code MessageSet} wire format. */ /** Get the number of bytes required to encode this set using {@code MessageSet} wire format. */
public int getSerializedSizeAsMessageSet() { public int getSerializedSizeAsMessageSet() {
int result = 0; int result = 0;
if (fields.isEmpty()) {
// Avoid allocating an iterator.
return result;
}
for (Map.Entry<Integer, Field> entry : fields.entrySet()) { for (Map.Entry<Integer, Field> entry : fields.entrySet()) {
result += entry.getValue().getSerializedSizeAsMessageSetExtension(entry.getKey()); result += entry.getValue().getSerializedSizeAsMessageSetExtension(entry.getKey());
} }

Loading…
Cancel
Save