Skip to content

Commit 802778d

Browse files
committed
perf(runtime): cache scheduler reflection capabilities
1 parent 6283522 commit 802778d

2 files changed

Lines changed: 402 additions & 29 deletions

File tree

src/main/java/top/ellan/mahjong/runtime/ServerScheduler.java

Lines changed: 92 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,38 @@ public boolean isCancelled() {
2222
}
2323
};
2424

25+
private static final ClassValue<ServerCapabilities> SERVER_CAPABILITIES = new ClassValue<>() {
26+
@Override
27+
protected ServerCapabilities computeValue(Class<?> type) {
28+
return new ServerCapabilities(
29+
findMethod(type, "getGlobalRegionScheduler"),
30+
findMethod(type, "getRegionScheduler")
31+
);
32+
}
33+
};
34+
private static final ClassValue<EntityCapabilities> ENTITY_CAPABILITIES = new ClassValue<>() {
35+
@Override
36+
protected EntityCapabilities computeValue(Class<?> type) {
37+
return new EntityCapabilities(
38+
findMethod(type, "getScheduler")
39+
);
40+
}
41+
};
42+
private static final ClassValue<SchedulerCapabilities> SCHEDULER_CAPABILITIES = new ClassValue<>() {
43+
@Override
44+
protected SchedulerCapabilities computeValue(Class<?> type) {
45+
return new SchedulerCapabilities(
46+
findMethod(type, "run", Plugin.class, Consumer.class),
47+
findMethod(type, "runDelayed", Plugin.class, Consumer.class, long.class),
48+
findMethod(type, "runAtFixedRate", Plugin.class, Consumer.class, long.class, long.class),
49+
findMethod(type, "run", Plugin.class, Location.class, Consumer.class),
50+
findMethod(type, "runDelayed", Plugin.class, Location.class, Consumer.class, long.class),
51+
findMethod(type, "runAtFixedRate", Plugin.class, Location.class, Consumer.class, long.class, long.class),
52+
findMethod(type, "run", Plugin.class, Consumer.class, Runnable.class),
53+
findMethod(type, "runDelayed", Plugin.class, Consumer.class, Runnable.class, long.class)
54+
);
55+
}
56+
};
2557
private final Plugin plugin;
2658

2759
public ServerScheduler(Plugin plugin) {
@@ -34,10 +66,10 @@ public PluginTask runGlobal(Runnable runnable) {
3466
}
3567
Object scheduler = this.globalRegionScheduler();
3668
if (scheduler != null) {
69+
Method method = SCHEDULER_CAPABILITIES.get(scheduler.getClass()).globalRun();
3770
PluginTask task = this.invokeSchedulerTask(
3871
scheduler,
39-
"run",
40-
new Class<?>[] {Plugin.class, Consumer.class},
72+
method,
4173
this.plugin,
4274
taskConsumer(runnable)
4375
);
@@ -54,10 +86,10 @@ public PluginTask runGlobalDelayed(Runnable runnable, long delayTicks) {
5486
}
5587
Object scheduler = this.globalRegionScheduler();
5688
if (scheduler != null) {
89+
Method method = SCHEDULER_CAPABILITIES.get(scheduler.getClass()).globalDelayed();
5790
PluginTask task = this.invokeSchedulerTask(
5891
scheduler,
59-
"runDelayed",
60-
new Class<?>[] {Plugin.class, Consumer.class, long.class},
92+
method,
6193
this.plugin,
6294
taskConsumer(runnable),
6395
delayTicks
@@ -75,10 +107,10 @@ public PluginTask runGlobalTimer(Runnable runnable, long delayTicks, long period
75107
}
76108
Object scheduler = this.globalRegionScheduler();
77109
if (scheduler != null) {
110+
Method method = SCHEDULER_CAPABILITIES.get(scheduler.getClass()).globalTimer();
78111
PluginTask task = this.invokeSchedulerTask(
79112
scheduler,
80-
"runAtFixedRate",
81-
new Class<?>[] {Plugin.class, Consumer.class, long.class, long.class},
113+
method,
82114
this.plugin,
83115
taskConsumer(runnable),
84116
delayTicks,
@@ -97,10 +129,10 @@ public PluginTask runRegion(Location location, Runnable runnable) {
97129
}
98130
Object scheduler = this.regionScheduler();
99131
if (scheduler != null) {
132+
Method method = SCHEDULER_CAPABILITIES.get(scheduler.getClass()).regionRun();
100133
PluginTask task = this.invokeSchedulerTask(
101134
scheduler,
102-
"run",
103-
new Class<?>[] {Plugin.class, Location.class, Consumer.class},
135+
method,
104136
this.plugin,
105137
location,
106138
taskConsumer(runnable)
@@ -118,10 +150,10 @@ public PluginTask runRegionDelayed(Location location, Runnable runnable, long de
118150
}
119151
Object scheduler = this.regionScheduler();
120152
if (scheduler != null) {
153+
Method method = SCHEDULER_CAPABILITIES.get(scheduler.getClass()).regionDelayed();
121154
PluginTask task = this.invokeSchedulerTask(
122155
scheduler,
123-
"runDelayed",
124-
new Class<?>[] {Plugin.class, Location.class, Consumer.class, long.class},
156+
method,
125157
this.plugin,
126158
location,
127159
taskConsumer(runnable),
@@ -140,10 +172,10 @@ public PluginTask runRegionTimer(Location location, Runnable runnable, long dela
140172
}
141173
Object scheduler = this.regionScheduler();
142174
if (scheduler != null) {
175+
Method method = SCHEDULER_CAPABILITIES.get(scheduler.getClass()).regionTimer();
143176
PluginTask task = this.invokeSchedulerTask(
144177
scheduler,
145-
"runAtFixedRate",
146-
new Class<?>[] {Plugin.class, Location.class, Consumer.class, long.class, long.class},
178+
method,
147179
this.plugin,
148180
location,
149181
taskConsumer(runnable),
@@ -163,10 +195,10 @@ public PluginTask runEntity(Entity entity, Runnable runnable) {
163195
}
164196
Object scheduler = this.entityScheduler(entity);
165197
if (scheduler != null) {
198+
Method method = SCHEDULER_CAPABILITIES.get(scheduler.getClass()).entityRun();
166199
PluginTask task = this.invokeSchedulerTask(
167200
scheduler,
168-
"run",
169-
new Class<?>[] {Plugin.class, Consumer.class, Runnable.class},
201+
method,
170202
this.plugin,
171203
taskConsumer(runnable),
172204
NO_OP_RUNNABLE
@@ -184,10 +216,10 @@ public PluginTask runEntityDelayed(Entity entity, Runnable runnable, long delayT
184216
}
185217
Object scheduler = this.entityScheduler(entity);
186218
if (scheduler != null) {
219+
Method method = SCHEDULER_CAPABILITIES.get(scheduler.getClass()).entityDelayed();
187220
PluginTask task = this.invokeSchedulerTask(
188221
scheduler,
189-
"runDelayed",
190-
new Class<?>[] {Plugin.class, Consumer.class, Runnable.class, long.class},
222+
method,
191223
this.plugin,
192224
taskConsumer(runnable),
193225
NO_OP_RUNNABLE,
@@ -246,40 +278,44 @@ public PluginTask removeEntity(Entity entity, long delayTicks) {
246278
}
247279

248280
private Object globalRegionScheduler() {
249-
return this.invokeNoArgs(this.plugin.getServer(), "getGlobalRegionScheduler");
281+
Object server = this.plugin.getServer();
282+
Method method = server == null ? null : SERVER_CAPABILITIES.get(server.getClass()).globalRegionScheduler();
283+
return this.invokeNoArgs(server, method);
250284
}
251285

252286
private Object regionScheduler() {
253-
return this.invokeNoArgs(this.plugin.getServer(), "getRegionScheduler");
287+
Object server = this.plugin.getServer();
288+
Method method = server == null ? null : SERVER_CAPABILITIES.get(server.getClass()).regionScheduler();
289+
return this.invokeNoArgs(server, method);
254290
}
255291

256292
private Object entityScheduler(Entity entity) {
257-
return this.invokeNoArgs(entity, "getScheduler");
293+
Method method = entity == null ? null : ENTITY_CAPABILITIES.get(entity.getClass()).scheduler();
294+
return this.invokeNoArgs(entity, method);
258295
}
259296

260297
private boolean isPluginEnabled() {
261298
return this.plugin.isEnabled();
262299
}
263300

264-
private Object invokeNoArgs(Object target, String methodName) {
265-
if (target == null) {
301+
private Object invokeNoArgs(Object target, Method method) {
302+
if (target == null || method == null) {
266303
return null;
267304
}
268305
try {
269-
Method method = target.getClass().getMethod(methodName);
270-
method.setAccessible(true);
271306
return method.invoke(target);
272-
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | RuntimeException exception) {
307+
} catch (IllegalAccessException | InvocationTargetException | RuntimeException exception) {
273308
return null;
274309
}
275310
}
276311

277-
private PluginTask invokeSchedulerTask(Object scheduler, String methodName, Class<?>[] parameterTypes, Object... args) {
312+
private PluginTask invokeSchedulerTask(Object scheduler, Method method, Object... args) {
313+
if (method == null) {
314+
return null;
315+
}
278316
try {
279-
Method method = scheduler.getClass().getMethod(methodName, parameterTypes);
280-
method.setAccessible(true);
281317
return wrap(method.invoke(scheduler, args));
282-
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | RuntimeException exception) {
318+
} catch (IllegalAccessException | InvocationTargetException | RuntimeException exception) {
283319
return null;
284320
}
285321
}
@@ -334,7 +370,34 @@ private static Object invokeTaskMethod(Object task, String methodName) {
334370
}
335371
}
336372

373+
private static Method findMethod(Class<?> type, String methodName, Class<?>... parameterTypes) {
374+
try {
375+
Method method = type.getMethod(methodName, parameterTypes);
376+
method.setAccessible(true);
377+
return method;
378+
} catch (NoSuchMethodException | RuntimeException exception) {
379+
return null;
380+
}
381+
}
382+
383+
private record ServerCapabilities(Method globalRegionScheduler, Method regionScheduler) {
384+
}
385+
386+
private record EntityCapabilities(Method scheduler) {
387+
}
388+
389+
private record SchedulerCapabilities(
390+
Method globalRun,
391+
Method globalDelayed,
392+
Method globalTimer,
393+
Method regionRun,
394+
Method regionDelayed,
395+
Method regionTimer,
396+
Method entityRun,
397+
Method entityDelayed
398+
) {
399+
}
400+
337401
private static final Runnable NO_OP_RUNNABLE = () -> {
338402
};
339403
}
340-

0 commit comments

Comments
 (0)