1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.util;
17
18 import io.netty5.microbench.util.AbstractMicrobenchmark;
19 import org.openjdk.jmh.annotations.Benchmark;
20 import org.openjdk.jmh.annotations.Level;
21 import org.openjdk.jmh.annotations.Measurement;
22 import org.openjdk.jmh.annotations.Param;
23 import org.openjdk.jmh.annotations.Scope;
24 import org.openjdk.jmh.annotations.Setup;
25 import org.openjdk.jmh.annotations.State;
26 import org.openjdk.jmh.annotations.Threads;
27 import org.openjdk.jmh.annotations.Warmup;
28 import org.openjdk.jmh.infra.Blackhole;
29
30 import java.util.IdentityHashMap;
31
32 @Warmup(iterations = 5, time = 1)
33 @Measurement(iterations = 5, time = 1)
34 @State(Scope.Benchmark)
35 public class DefaultAttributeMapBenchmark extends AbstractMicrobenchmark {
36
37 @Param({ "8", "32", "128" })
38 private int keyCount;
39 private AttributeKey<Integer>[] keys;
40 private IdentityHashMap<AttributeKey<Integer>, Attribute<Integer>> identityHashMap;
41 private DefaultAttributeMap attributes;
42
43 @State(Scope.Thread)
44 public static class KeySequence {
45
46 long nextKey;
47
48 @Setup(Level.Iteration)
49 public void reset() {
50 nextKey = 0;
51 }
52
53 public long next() {
54 return nextKey++;
55 }
56 }
57
58 @Setup
59 public void init() {
60 if (Integer.bitCount(keyCount) != 1) {
61 throw new AssertionError("keyCount should cbe a power of 2");
62 }
63 attributes = new DefaultAttributeMap();
64 keys = new AttributeKey[keyCount];
65 identityHashMap = new IdentityHashMap<>(keyCount);
66 for (int i = 0; i < keyCount; i++) {
67 final AttributeKey<Integer> key = AttributeKey.valueOf(Integer.toString(i));
68 keys[i] = key;
69 final Attribute<Integer> attribute = attributes.attr(key);
70 identityHashMap.put(key, attribute);
71 }
72 }
73
74 @Benchmark
75 @Threads(3)
76 public Attribute<Integer> nextAttributeIdentityHashMap(KeySequence sequence) {
77 long next = sequence.next();
78 AttributeKey<Integer>[] keys = this.keys;
79 AttributeKey<Integer> key = keys[(int) (next & keys.length - 1)];
80 return identityHashMap.get(key);
81 }
82
83 @Benchmark
84 @Threads(3)
85 public boolean hasAttributeIdentityHashMap(KeySequence sequence) {
86 long next = sequence.next();
87 AttributeKey<Integer>[] keys = this.keys;
88 AttributeKey<Integer> key = keys[(int) (next & keys.length - 1)];
89 return identityHashMap.containsKey(key);
90 }
91
92 @Benchmark
93 @Threads(3)
94 public void mixedAttributeIdentityHashMap(KeySequence sequence, Blackhole hole) {
95 long next = sequence.next();
96 AttributeKey<Integer>[] keys = this.keys;
97 AttributeKey<Integer> key = keys[(int) (next & keys.length - 1)];
98 if (next % 2 == 0) {
99 hole.consume(identityHashMap.get(key));
100 } else {
101 hole.consume(identityHashMap.containsKey(key));
102 }
103 }
104
105 @Benchmark
106 @Threads(3)
107 public Attribute<Integer> nextAttributeAttributeMap(KeySequence sequence) {
108 long next = sequence.next();
109 AttributeKey<Integer>[] keys = this.keys;
110 AttributeKey<Integer> key = keys[(int) (next & keys.length - 1)];
111 return attributes.attr(key);
112 }
113
114 @Benchmark
115 @Threads(3)
116 public boolean nextHasAttributeAttributeMap(KeySequence sequence) {
117 long next = sequence.next();
118 AttributeKey<Integer>[] keys = this.keys;
119 AttributeKey<Integer> key = keys[(int) (next & keys.length - 1)];
120 return attributes.hasAttr(key);
121 }
122
123 @Benchmark
124 @Threads(3)
125 public void mixedAttributeAttributeMap(KeySequence sequence, Blackhole hole) {
126 long next = sequence.next();
127 AttributeKey<Integer>[] keys = this.keys;
128 AttributeKey<Integer> key = keys[(int) (next & keys.length - 1)];
129 if (next % 2 == 0) {
130 hole.consume(attributes.attr(key));
131 } else {
132 hole.consume(attributes.hasAttr(key));
133 }
134 }
135 }