Skip to content

Commit

Permalink
Java Proto lite: avoid boxing Integers accessing enum lists
Browse files Browse the repository at this point in the history
Provide a specialization for ListAdapter that avoids boxing ints into Integers.

Use this for repeated enum accessors.

In practice, the ints for most enums will fit into the JDK's "boxed int cache", avoiding extra allocations. For large enum numbers, they won't fit, and would allocate. Removing the boxing should also slightly speed up code.

PiperOrigin-RevId: 629583247
  • Loading branch information
mhansen authored and copybara-github committed May 1, 2024
1 parent e1559c8 commit fb054c8
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 13 deletions.
30 changes: 30 additions & 0 deletions java/core/src/main/java/com/google/protobuf/Internal.java
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,36 @@ static Object mergeMessage(Object destination, Object source) {
return ((MessageLite) destination).toBuilder().mergeFrom((MessageLite) source).buildPartial();
}

/**
* Provides an immutable view of {@code List<T>} around an {@code IntList}.
*
* <p>Protobuf internal. Used in protobuf generated code only.
*/
public static class IntListAdapter<T> extends AbstractList<T> {
/** Convert individual elements of the List from int to T. */
public interface IntConverter<T> {
T convert(int from);
}

private final IntList fromList;
private final IntConverter<T> converter;

public IntListAdapter(IntList fromList, IntConverter<T> converter) {
this.fromList = fromList;
this.converter = converter;
}

@Override
public T get(int index) {
return converter.convert(fromList.getInt(index));
}

@Override
public int size() {
return fromList.size();
}
}

/**
* Provides an immutable view of {@code List<T>} around a {@code List<F>}.
*
Expand Down
25 changes: 12 additions & 13 deletions src/google/protobuf/compiler/java/lite/enum_field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -597,27 +597,26 @@ void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers(
variables_,
"private com.google.protobuf.Internal.IntList $name$_;\n"
"private static final "
"com.google.protobuf.Internal.ListAdapter.Converter<\n"
" java.lang.Integer, $type$> $name$_converter_ =\n"
" new com.google.protobuf.Internal.ListAdapter.Converter<\n"
" java.lang.Integer, $type$>() {\n"
"com.google.protobuf.Internal.IntListAdapter.IntConverter<\n"
" $type$> $name$_converter_ =\n"
" new com.google.protobuf.Internal.IntListAdapter.IntConverter<\n"
" $type$>() {\n"
" @java.lang.Override\n"
" public $type$ convert(java.lang.Integer from) {\n"
" public $type$ convert(int from) {\n"
" $type$ result = $type$.forNumber(from);\n"
" return result == null ? $unknown$ : result;\n"
" }\n"
" };\n");
PrintExtraFieldInfo(variables_, printer);
WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
context_->options());
printer->Print(
variables_,
"@java.lang.Override\n"
"$deprecation$public java.util.List<$type$> "
"${$get$capitalized_name$List$}$() {\n"
" return new com.google.protobuf.Internal.ListAdapter<\n"
" java.lang.Integer, $type$>($name$_, $name$_converter_);\n"
"}\n");
printer->Print(variables_,
"@java.lang.Override\n"
"$deprecation$public java.util.List<$type$> "
"${$get$capitalized_name$List$}$() {\n"
" return new com.google.protobuf.Internal.IntListAdapter<\n"
" $type$>($name$_, $name$_converter_);\n"
"}\n");
printer->Annotate("{", "}", descriptor_);
WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT,
context_->options());
Expand Down

0 comments on commit fb054c8

Please sign in to comment.