-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathDisplayEntitiesSpawnAllBenchmark.java
More file actions
97 lines (86 loc) · 3.38 KB
/
Copy pathDisplayEntitiesSpawnAllBenchmark.java
File metadata and controls
97 lines (86 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
package top.ellan.mahjong.perf;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import top.ellan.mahjong.render.display.DisplayEntities;
import top.ellan.mahjong.render.display.DisplayEntityRuntime;
/** Measures the one-entity region shape used by hand, discard, meld and wall tiles. */
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class DisplayEntitiesSpawnAllBenchmark {
private static final int REPRESENTATIVE_SINGLETON_REGION_COUNT = 268;
private Entity entity;
private DisplayEntityRuntime runtime;
private List<DisplayEntities.EntitySpec> singletonSpec;
@Setup(Level.Trial)
public void setUp() {
Plugin plugin = proxy(Plugin.class);
this.entity = proxy(Entity.class);
this.runtime = new EmptyViewerRuntime(plugin);
this.singletonSpec = List.of(new ConstantEntitySpec(this.entity));
this.verifyContract();
}
@Benchmark
public int spawnRepresentativeTableRegions() {
int spawned = 0;
for (int region = 0; region < REPRESENTATIVE_SINGLETON_REGION_COUNT; region++) {
spawned += DisplayEntities.spawnAll(this.runtime, this.singletonSpec).size();
}
return spawned;
}
private void verifyContract() {
List<Entity> spawned = DisplayEntities.spawnAll(this.runtime, this.singletonSpec);
if (spawned.size() != 1 || spawned.get(0) != this.entity) {
throw new IllegalStateException("Singleton spawn contract changed");
}
try {
spawned.add(this.entity);
throw new IllegalStateException("spawnAll must return an immutable list");
} catch (UnsupportedOperationException expected) {
// Expected contract.
}
}
@SuppressWarnings("unchecked")
private static <T> T proxy(Class<T> type) {
return (T) Proxy.newProxyInstance(
type.getClassLoader(),
new Class<?>[] {type},
(instance, method, arguments) -> {
throw new UnsupportedOperationException(method.toString());
}
);
}
private record EmptyViewerRuntime(Plugin bukkitPlugin) implements DisplayEntityRuntime {
@Override
public Collection<? extends Player> onlinePlayers() {
return List.of();
}
}
private record ConstantEntitySpec(Entity entity) implements DisplayEntities.EntitySpec {
@Override
public Entity spawn(DisplayEntityRuntime runtime) {
return this.entity;
}
@Override
public boolean canReuse(DisplayEntityRuntime runtime, Entity candidate) {
return candidate == this.entity;
}
@Override
public void apply(DisplayEntityRuntime runtime, Entity candidate) {
throw new UnsupportedOperationException("Benchmark does not reconcile entities");
}
}
}