Skip to content

Commit

Permalink
fixup: make mergemap mutate
Browse files Browse the repository at this point in the history
Signed-off-by: Todd Baert <[email protected]>
  • Loading branch information
toddbaert committed Oct 23, 2024
1 parent 5cd181f commit bddf7f2
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 70 deletions.
96 changes: 48 additions & 48 deletions benchmark.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ Audit done.
processing is enabled explicitly (-proc:only, -proc:full).
Use -Xlint:-options to suppress this message.
Use -proc:none to disable annotation processing.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/EventDetails.java:[9,1] Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/ImmutableStructure.java:[22,1] Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/MutableStructure.java:[19,1] Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/ImmutableStructure.java:[22,1] Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/EventDetails.java:[9,1] Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.
[WARNING] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/Value.java:[27,26] finalize() in java.lang.Object has been deprecated and marked for removal
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/NoOpProvider.java: Some input files use or override a deprecated API.
[INFO] /home/todd/git/java-sdk/src/main/java/dev/openfeature/sdk/NoOpProvider.java: Recompile with -Xlint:deprecation for details.
Expand Down Expand Up @@ -129,41 +129,41 @@ Audit done.
[0.001s][warning][gc,init] Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups
Iteration 1: num #instances #bytes class name (module)
-------------------------------------------------------
1: 559671 26864208 java.util.HashMap ([email protected])
2: 352017 11264544 java.util.HashMap$Node ([email protected])
3: 210497 11170088 [Ljava.util.HashMap$Node; ([email protected])
4: 47815 9732672 [B ([email protected])
5: 279526 8944832 java.util.HashMap$EntryIterator ([email protected])
6: 305991 8105872 [Ljava.lang.Object; ([email protected])
7: 445455 7127280 java.util.Optional ([email protected])
8: 199209 6374688 java.util.Collections$UnmodifiableMap ([email protected])
9: 154 4368416 [Ljdk.internal.vm.FillerElement; ([email protected])
10: 100000 4000000 dev.openfeature.sdk.HookContext
11: 100000 4000000 dev.openfeature.sdk.HookContext$HookContextBuilder
12: 230006 3680096 dev.openfeature.sdk.Value
13: 210062 3360992 java.util.HashMap$EntrySet ([email protected])
14: 139788 3354912 java.util.ArrayList ([email protected])
15: 199210 3187360 dev.openfeature.sdk.ImmutableStructure
16: 130219 3125256 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$1 ([email protected])
17: 189210 3027360 dev.openfeature.sdk.ImmutableContext
18: 177267 2836272 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry ([email protected])
19: 82425 2637600 java.util.ArrayList$Itr ([email protected])
20: 149207 2387312 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet ([email protected])
21: 50000 2000000 dev.openfeature.sdk.FlagEvaluationDetails
22: 50000 2000000 dev.openfeature.sdk.ProviderEvaluation
23: 34652 1663296 dev.openfeature.sdk.FlagEvaluationDetails$FlagEvaluationDetailsBuilder
24: 100001 1600016 dev.openfeature.sdk.NoOpProvider$$Lambda/0x00007bf8a002fa78
25: 50000 1600000 [Ldev.openfeature.sdk.EvaluationContext;
26: 50000 1600000 [Ljava.util.List; ([email protected])
27: 100000 1600000 dev.openfeature.sdk.ImmutableMetadata
28: 100000 1600000 dev.openfeature.sdk.ImmutableMetadata$ImmutableMetadataBuilder
29: 100000 1600000 dev.openfeature.sdk.OpenFeatureClient$$Lambda/0x00007bf8a0082800
30: 50000 1200000 dev.openfeature.sdk.FlagEvaluationOptions
31: 44836 1076064 dev.openfeature.sdk.FlagEvaluationOptions$FlagEvaluationOptionsBuilder
32: 26278 1051120 dev.openfeature.sdk.ProviderEvaluation$ProviderEvaluationBuilder
33: 40785 978840 dev.openfeature.sdk.HookSupport$$Lambda/0x00007bf8a0081da8
34: 40423 970152 dev.openfeature.sdk.HookSupport$$Lambda/0x00007bf8a0081b78
35: 54212 867392 dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock$$Lambda/0x00007bf8a002eae8
1: 480234 23051232 java.util.HashMap ([email protected])
2: 150497 12050088 [Ljava.util.HashMap$Node; ([email protected])
3: 332017 10624544 java.util.HashMap$Node ([email protected])
4: 47815 9732480 [B ([email protected])
5: 305991 8105872 [Ljava.lang.Object; ([email protected])
6: 366682 5866912 java.util.Optional ([email protected])
7: 183332 5866624 java.util.HashMap$EntryIterator ([email protected])
8: 172970 5535040 java.util.Collections$UnmodifiableMap ([email protected])
9: 100000 4000000 dev.openfeature.sdk.HookContext
10: 100000 4000000 dev.openfeature.sdk.HookContext$HookContextBuilder
11: 230006 3680096 dev.openfeature.sdk.Value
12: 200062 3200992 java.util.HashMap$EntrySet ([email protected])
13: 132870 3188880 java.util.ArrayList ([email protected])
14: 192292 3076672 dev.openfeature.sdk.ImmutableStructure
15: 182292 2916672 dev.openfeature.sdk.ImmutableContext
16: 50000 2000000 dev.openfeature.sdk.FlagEvaluationDetails
17: 50000 2000000 dev.openfeature.sdk.ProviderEvaluation
18: 122968 1967488 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet ([email protected])
19: 149 1884376 [Ljdk.internal.vm.FillerElement; ([email protected])
20: 56476 1807232 java.util.ArrayList$Itr ([email protected])
21: 37481 1799088 dev.openfeature.sdk.FlagEvaluationDetails$FlagEvaluationDetailsBuilder
22: 100001 1600016 dev.openfeature.sdk.NoOpProvider$$Lambda/0x000076e79c02fa78
23: 50000 1600000 [Ldev.openfeature.sdk.EvaluationContext;
24: 50000 1600000 [Ljava.util.List; ([email protected])
25: 100000 1600000 dev.openfeature.sdk.OpenFeatureClient$$Lambda/0x000076e79c082800
26: 36720 1468800 dev.openfeature.sdk.ProviderEvaluation$ProviderEvaluationBuilder
27: 87481 1399696 dev.openfeature.sdk.ImmutableMetadata
28: 50000 1200000 dev.openfeature.sdk.FlagEvaluationOptions
29: 74201 1187216 dev.openfeature.sdk.ImmutableMetadata$ImmutableMetadataBuilder
30: 73235 1171760 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$UnmodifiableEntry ([email protected])
31: 45869 1100856 java.util.Collections$UnmodifiableMap$UnmodifiableEntrySet$1 ([email protected])
32: 43776 1050624 dev.openfeature.sdk.FlagEvaluationOptions$FlagEvaluationOptionsBuilder
33: 40016 960384 dev.openfeature.sdk.HookSupport$$Lambda/0x000076e79c081b78
34: 39967 959208 dev.openfeature.sdk.HookSupport$$Lambda/0x000076e79c081da8
35: 57783 924528 dev.openfeature.sdk.internal.AutoCloseableReentrantReadWriteLock$$Lambda/0x000076e79c02eae8
36: 4490 721440 [I ([email protected])
37: 26594 638256 java.lang.String ([email protected])
38: 1461 390008 [J ([email protected])
Expand Down Expand Up @@ -248,20 +248,20 @@ Iteration 1: num #instances #bytes class name (module)
117: 65 5200 java.net.URI ([email protected])
118: 215 5104 [Ljdk.internal.org.objectweb.asm.Type; ([email protected])
truncated...
Total 5107873 156138304
Total 4452140 139359040

0.187 s/op
+totalAllocatedBytes: 156138304.000 bytes
+totalAllocatedInstances: 5107873.000 instances
0.186 s/op
+totalAllocatedBytes: 139359040.000 bytes
+totalAllocatedInstances: 4452140.000 instances
+totalHeap: 521412608.000 bytes



Secondary result "dev.openfeature.sdk.benchmark.AllocationBenchmark.run:+totalAllocatedBytes":
156138304.000 bytes
139359040.000 bytes

Secondary result "dev.openfeature.sdk.benchmark.AllocationBenchmark.run:+totalAllocatedInstances":
5107873.000 instances
4452140.000 instances

Secondary result "dev.openfeature.sdk.benchmark.AllocationBenchmark.run:+totalHeap":
521412608.000 bytes
Expand All @@ -282,13 +282,13 @@ different JVMs are already problematic, the performance difference caused by dif
modes can be very significant. Please make sure you use the consistent Blackhole mode for comparisons.

Benchmark Mode Cnt Score Error Units
AllocationBenchmark.run ss 0.187 s/op
AllocationBenchmark.run:+totalAllocatedBytes ss 156138304.000 bytes
AllocationBenchmark.run:+totalAllocatedInstances ss 5107873.000 instances
AllocationBenchmark.run ss 0.186 s/op
AllocationBenchmark.run:+totalAllocatedBytes ss 139359040.000 bytes
AllocationBenchmark.run:+totalAllocatedInstances ss 4452140.000 instances
AllocationBenchmark.run:+totalHeap ss 521412608.000 bytes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.226 s
[INFO] Finished at: 2024-10-23T12:36:22-04:00
[INFO] Total time: 8.280 s
[INFO] Finished at: 2024-10-23T12:37:24-04:00
[INFO] ------------------------------------------------------------------------
29 changes: 14 additions & 15 deletions src/main/java/dev/openfeature/sdk/EvaluationContext.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package dev.openfeature.sdk;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Function;
Expand All @@ -26,38 +25,38 @@ public interface EvaluationContext extends Structure {
EvaluationContext merge(EvaluationContext overridingContext);

/**
* Recursively merges the base Value map with the overriding map.
* Recursively merges the overriding map into the base Value map.
* The base map is mutated, the overriding map is not.
* Null maps will cause no-op.
*
* @param <T> Structure type
* @param newStructure function to create the right structure(s) for Values
* @param base base map to merge
* @param overriding overriding map to merge
* @return resulting merged map
*/
static <T extends Structure> Map<String, Value> mergeMaps(Function<Map<String, Value>, Structure> newStructure,
static void mergeMaps(Function<Map<String, Value>, Structure> newStructure,
Map<String, Value> base,
Map<String, Value> overriding) {

if (base == null || base.isEmpty()) {
return overriding;
if (base == null) {
return;
}
if (overriding == null || overriding.isEmpty()) {
return base;
return;
}

final Map<String, Value> merged = new HashMap<>(base);
for (Entry<String, Value> overridingEntry : overriding.entrySet()) {
String key = overridingEntry.getKey();
if (overridingEntry.getValue().isStructure() && merged.containsKey(key) && merged.get(key).isStructure()) {
Structure mergedValue = merged.get(key).asStructure();
if (overridingEntry.getValue().isStructure() && base.containsKey(key) && base.get(key).isStructure()) {
Structure mergedValue = base.get(key).asStructure();
Structure overridingValue = overridingEntry.getValue().asStructure();
Map<String, Value> newMap = mergeMaps(newStructure, mergedValue.asUnmodifiableMap(),
Map<String, Value> newMap = mergedValue.asMap();
mergeMaps(newStructure, newMap,
overridingValue.asUnmodifiableMap());
merged.put(key, new Value(newStructure.apply(newMap)));
base.put(key, new Value(newStructure.apply(newMap)));
} else {
merged.put(key, overridingEntry.getValue());
base.put(key, overridingEntry.getValue());
}
}
return merged;
return;
}
}
7 changes: 4 additions & 3 deletions src/main/java/dev/openfeature/sdk/ImmutableContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,10 @@ public EvaluationContext merge(EvaluationContext overridingContext) {
return new ImmutableContext(overridingContext.asUnmodifiableMap());
}

return new ImmutableContext(
EvaluationContext.mergeMaps(ImmutableStructure::new, this.asUnmodifiableMap(),
overridingContext.asUnmodifiableMap()));
Map<String, Value> attributes = this.asMap();
EvaluationContext.mergeMaps(ImmutableStructure::new, attributes,
overridingContext.asUnmodifiableMap());
return new ImmutableContext(attributes);
}

@SuppressWarnings("all")
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/dev/openfeature/sdk/MutableContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@ public EvaluationContext merge(EvaluationContext overridingContext) {
return overridingContext;
}

Map<String, Value> merged = EvaluationContext.mergeMaps(
MutableStructure::new, this.asUnmodifiableMap(), overridingContext.asUnmodifiableMap());
return new MutableContext(merged);
Map<String, Value> attributes = this.asMap();
EvaluationContext.mergeMaps(
MutableStructure::new, attributes, overridingContext.asUnmodifiableMap());
return new MutableContext(attributes);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/dev/openfeature/sdk/OpenFeatureClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ private EvaluationContext mergeContextMaps(EvaluationContext... contexts) {
Map merged = new HashMap<>();
for (EvaluationContext evaluationContext : contexts) {
if (evaluationContext != null && !evaluationContext.isEmpty()) {
merged = EvaluationContext.mergeMaps(ImmutableStructure::new, merged,
EvaluationContext.mergeMaps(ImmutableStructure::new, merged,
evaluationContext.asUnmodifiableMap());
}
}
Expand Down

0 comments on commit bddf7f2

Please sign in to comment.