Skip to content

Commit

Permalink
Optimize MapValue decoding and internal mapper loops
Browse files Browse the repository at this point in the history
Use ArrayList in converter maps to utilize sequential loops over
the internal array instead of creating an iterator instance every time
which adds additional GC pressure.

Also improve maps encoding by creating an immediate zero-copy structure.
  • Loading branch information
akudiyar committed Jan 5, 2024
1 parent a64753f commit b89828d
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
Expand Down Expand Up @@ -78,8 +77,8 @@ private <V extends Value, O> Optional<ValueConverter<V, O>> getValueConverter(V
ValueConverter<V, O> converter;
List<ConverterWrapper<ValueConverter<? extends Value, ?>>> wrappers =
valueConverters.getOrDefault(valueType, Collections.emptyList());
for (ConverterWrapper<ValueConverter<? extends Value, ?>> wrapper : wrappers) {
converter = (ValueConverter<V, O>) wrapper.getConverter();
for (int i = 0; i < wrappers.size(); i++) {
converter = (ValueConverter<V, O>) wrappers.get(i).getConverter();
if (converter.canConvertValue(v)) {
return Optional.of(converter);
}
Expand All @@ -103,7 +102,9 @@ private <V extends Value, O> Optional<ValueConverter<V, O>> getValueConverter(
ValueConverter<V, O> converter;
List<ConverterWrapper<ValueConverter<? extends Value, ?>>> wrappers =
valueConverters.getOrDefault(valueType, Collections.emptyList());
for (ConverterWrapper<ValueConverter<? extends Value, ?>> wrapper : wrappers) {
ConverterWrapper<ValueConverter<? extends Value, ?>> wrapper;
for (int i = 0; i < wrappers.size(); i++) {
wrapper = wrappers.get(i);
if (checkConverterByTargetType(wrapper.getTargetClass(), targetClass)) {
converter = (ValueConverter<V, O>) wrapper.getConverter();
if (converter.canConvertValue(v)) {
Expand All @@ -126,7 +127,9 @@ private <V extends Value, O> Optional<ValueConverter<V, O>> getValueConverterByT
ValueType valueType, Class<? extends O> targetClass) {
List<ConverterWrapper<ValueConverter<? extends Value, ?>>> wrappers =
valueConverters.getOrDefault(valueType, Collections.emptyList());
for (ConverterWrapper<ValueConverter<? extends Value, ?>> wrapper : wrappers) {
ConverterWrapper<ValueConverter<? extends Value, ?>> wrapper;
for (int i = 0; i < wrappers.size(); i++) {
wrapper = wrappers.get(i);
if (checkConverterByTargetType(wrapper.getTargetClass(), targetClass)) {
return Optional.of((ValueConverter<V, O>) wrapper.getConverter());
}
Expand Down Expand Up @@ -169,15 +172,15 @@ public <V extends Value, O> void registerValueConverter(
Class<? extends O> objectClass,
ValueConverter<V, ? extends O> converter) {
List<ConverterWrapper<ValueConverter<? extends Value, ?>>> converters =
valueConverters.computeIfAbsent(valueType, k -> new LinkedList<>());
valueConverters.computeIfAbsent(valueType, k -> new ArrayList<>());
converters.add(0, new ConverterWrapper<>(converter, objectClass));
}

public <V extends Value, O> void registerValueConverterWithoutTargetClass(
ValueType valueType,
ValueConverter<V, ? extends O> converter) {
List<ConverterWrapper<ValueConverter<? extends Value, ?>>> converters =
valueConverters.computeIfAbsent(valueType, k -> new LinkedList<>());
valueConverters.computeIfAbsent(valueType, k -> new ArrayList<>());
converters.add(0, new ConverterWrapper<>(converter, Object.class));
}

Expand All @@ -204,8 +207,8 @@ private <V extends Value, O> Optional<ObjectConverter<O, V>> getObjectConverter(
ObjectConverter<O, V> converter;
List<ConverterWrapper<ObjectConverter<?, ? extends Value>>> wrappers =
objectConverters.getOrDefault(typeName, Collections.emptyList());
for (ConverterWrapper<ObjectConverter<?, ? extends Value>> wrapper : wrappers) {
converter = (ObjectConverter<O, V>) wrapper.getConverter();
for (int i = 0; i < wrappers.size(); i++) {
converter = (ObjectConverter<O, V>) wrappers.get(i).getConverter();
if (converter.canConvertObject(o)) {
return Optional.of(converter);
}
Expand Down Expand Up @@ -234,7 +237,9 @@ private <V extends Value, O> Optional<ObjectConverter<O, V>> getObjectConverterB
String typeName, Class<? extends V> valueClass) {
List<ConverterWrapper<ObjectConverter<?, ? extends Value>>> wrappers =
objectConverters.getOrDefault(typeName, Collections.emptyList());
for (ConverterWrapper<ObjectConverter<?, ? extends Value>> wrapper : wrappers) {
ConverterWrapper<ObjectConverter<?, ? extends Value>> wrapper;
for (int i = 0; i < wrappers.size(); i++) {
wrapper = wrappers.get(i);
if (checkConverterByTargetType(wrapper.getTargetClass(), valueClass)) {
return Optional.of((ObjectConverter<O, V>) wrapper.getConverter());
}
Expand Down Expand Up @@ -314,7 +319,7 @@ public <V extends Value, O> void registerObjectConverter(
Class<V> valueClass,
ObjectConverter<O, V> converter) {
List<ConverterWrapper<ObjectConverter<?, ? extends Value>>> converters =
objectConverters.computeIfAbsent(objectClass.getTypeName(), k -> new LinkedList<>());
objectConverters.computeIfAbsent(objectClass.getTypeName(), k -> new ArrayList<>());
converters.add(0, new ConverterWrapper<>(converter, valueClass));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,12 @@ public DefaultMapToMapValueConverter(MessagePackObjectMapper mapper) {

@Override
public MapValue toValue(Map<?, ?> object) {
Map<Value, Value> values = object.entrySet().stream()
.collect(Collectors.toMap(e -> mapper.toValue(e.getKey()), e -> mapper.toValue(e.getValue())));
return ValueFactory.newMap(values);
Value[] values = new Value[object.size() * 2];
int i = 0;
for (Object key : object) {
values[i++] = mapper.toValue(key);
values[i++] = mapper.toValue(object.get(key));
}
return ValueFactory.newMap(values, true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public void setTimestamp(Double timestamp) {
* @return MessagePack representation of the header
*/
public Value toMessagePackValue(MessagePackObjectMapper mapper) {
Map<IntegerValue, IntegerValue> values = new HashMap<>();
Map<IntegerValue, IntegerValue> values = new HashMap<>(3, 1);
values.put(ValueFactory.newInteger(IPROTO_REQUEST_TYPE), ValueFactory.newInteger(code));
values.put(ValueFactory.newInteger(IPROTO_SYNC), ValueFactory.newInteger(sync));
if (schemaVersion != null) {
Expand Down

0 comments on commit b89828d

Please sign in to comment.