Skip to content

Commit 5eab0ae

Browse files
CEL Dev Teamcopybara-github
authored andcommitted
Fix some stream performance issues in CEL runtime
PiperOrigin-RevId: 993192558
1 parent 3c4aa1b commit 5eab0ae

3 files changed

Lines changed: 30 additions & 10 deletions

File tree

‎common/src/main/java/dev/cel/common/internal/AdaptingTypes.java‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,12 @@ public Iterator<B> iterator() {
118118

119119
@Override
120120
public Object[] toArray() {
121-
return delegate.stream().map(baseEl -> converter().convert(baseEl)).toArray();
121+
Object[] result = new Object[size()];
122+
int i = 0;
123+
for (A a : delegate) {
124+
result[i++] = converter().convert(a);
125+
}
126+
return result;
122127
}
123128

124129
@Override

‎runtime/src/main/java/dev/cel/runtime/Activation.java‎

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
package dev.cel.runtime;
1616

17-
import static com.google.common.collect.ImmutableMap.toImmutableMap;
18-
1917
import com.google.common.base.Supplier;
2018
import com.google.common.collect.ImmutableMap;
2119
import com.google.protobuf.ByteString;
@@ -109,11 +107,9 @@ public static Activation copyOf(Map<String, ?> map) {
109107
final ImmutableMap<String, Object> copy =
110108
(map instanceof ImmutableMap)
111109
? (ImmutableMap<String, Object>) map
112-
: map.entrySet().stream()
113-
// ImmutableMaps are null-hostile, but the Activation is not, so make sure that null
114-
// values and entries are skipped.
115-
.filter(entry -> entry.getKey() != null && entry.getValue() != null)
116-
.collect(toImmutableMap(Map.Entry::getKey, Map.Entry::getValue));
110+
: // ImmutableMaps are null-hostile, but the Activation is not, so make sure that null
111+
// values and entries are skipped.
112+
toImmutableMapFilteringNulls(map);
117113
return new Activation() {
118114

119115
@Override
@@ -128,6 +124,23 @@ public String toString() {
128124
};
129125
}
130126

127+
/**
128+
* Creates an {@link ImmutableMap} from the given {@link Map} filtering out null keys and values.
129+
*
130+
* <p>Used instead of the one-liner for performance reasons.
131+
*/
132+
private static ImmutableMap<String, Object> toImmutableMapFilteringNulls(Map<String, ?> map) {
133+
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builderWithExpectedSize(map.size());
134+
for (Map.Entry<String, ?> entry : map.entrySet()) {
135+
String key = entry.getKey();
136+
Object value = entry.getValue();
137+
if (key != null && value != null) {
138+
builder.put(key, value);
139+
}
140+
}
141+
return builder.buildOrThrow();
142+
}
143+
131144
/**
132145
* Extends this binder by another binder. Names will be attempted to first resolve in the other
133146
* binder, then in this binder.

‎runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
import dev.cel.common.values.CelByteString;
4949
import java.util.ArrayDeque;
5050
import java.util.ArrayList;
51-
import java.util.Arrays;
5251
import java.util.Collection;
5352
import java.util.Collections;
5453
import java.util.HashMap;
@@ -499,7 +498,10 @@ private IntermediateResult dispatchCall(
499498
return IntermediateResult.create(attr, unknowns.get());
500499
}
501500

502-
Object[] argArray = Arrays.stream(argResults).map(IntermediateResult::value).toArray();
501+
Object[] argArray = new Object[argResults.length];
502+
for (int i = 0; i < argResults.length; i++) {
503+
argArray[i] = argResults[i].value();
504+
}
503505
ImmutableList<String> overloadIds = reference.overloadIds();
504506
CelResolvedOverload overload =
505507
findOverloadOrThrow(frame, expr, callExpr.function(), overloadIds, argArray);

0 commit comments

Comments
 (0)