Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,31 @@ public static boolean hasClass(final @NonNull String className) {
return findClass(className) != null;
}

/**
* Gets a handle for a class method, regardless of its return type.
*
* <p>{@link #findMethod} matches on the exact {@link MethodType}, return type included, so it
* cannot look up a method whose return class is not available at compile time. Use this instead
* when only the name and parameters are known.</p>
*
* @param holderClass a class
* @param methodName a method name
* @param parameterClasses an array of method parameter classes
* @return a method handle or {@code null} if not found
*/
public static @Nullable MethodHandle findMethodAnyReturn(final @Nullable Class<?> holderClass, final String methodName, final Class<?>... parameterClasses) {
if (holderClass == null) return null;
for (final Class<?> parameterClass : parameterClasses) {
if (parameterClass == null) return null;
}

try {
return LOOKUP.unreflect(holderClass.getMethod(methodName, parameterClasses));
} catch (final NoSuchMethodException | IllegalAccessException e) {
return null;
}
}

/**
* Gets a handle for a class method.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ public FoliaTickReporter(Server server, Duration cacheTime) {
this.tps_cache = Caffeine.newBuilder().expireAfterWrite(cacheTime).build();
this.mspt_cache = Caffeine.newBuilder().expireAfterWrite(cacheTime).build();

this.getTickReport5s = ReflectionUtil.findMethod(
// Returns TickData.TickReportData, which is not on the compile classpath, so the return
// type must not be part of the lookup.
this.getTickReport5s = ReflectionUtil.findMethodAnyReturn(
TickRegionScheduler.RegionScheduleHandle.class,
"getTickReport5s",
Object.class,
long.class
);
}
Expand All @@ -49,43 +50,35 @@ public void disable() {

@Override
public double getGlobalTPS() {
if (getTickReport5s != null) {
return tps_cache.get(RegionizedServer.getGlobalTickData(), this::extractTpsValue);
}
return server.getTPS()[0];
return tps_cache.get(RegionizedServer.getGlobalTickData(), this::extractTpsValue);
}

@Override
public double getTPS() {
final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>
region = TickRegionScheduler.getCurrentRegion();
if (region == null) return getGlobalTPS();
if (getTickReport5s != null) {
return tps_cache.get(region.getData().getRegionSchedulingHandle(), this::extractTpsValue);
}
return server.getTPS()[0];
return tps_cache.get(region.getData().getRegionSchedulingHandle(), this::extractTpsValue);
}

@Override
public double getGlobalMSPT() {
if (getTickReport5s != null) {
return mspt_cache.get(RegionizedServer.getGlobalTickData(), this::extractMsptValue);
}
return server.getAverageTickTime();
return mspt_cache.get(RegionizedServer.getGlobalTickData(), this::extractMsptValue);
}

@Override
public double getMSPT() {
final ThreadedRegionizer.ThreadedRegion<TickRegions.TickRegionData, TickRegions.TickRegionSectionData>
region = TickRegionScheduler.getCurrentRegion();
if (region == null) return getGlobalMSPT();
if (getTickReport5s != null) {
return mspt_cache.get(region.getData().getRegionSchedulingHandle(), this::extractMsptValue);
}
return server.getAverageTickTime();
return mspt_cache.get(region.getData().getRegionSchedulingHandle(), this::extractMsptValue);
}

// The Server fallbacks below are resolved inside the cache loaders on purpose. Server#getTPS and
// Server#getAverageTickTime rebuild the 1m/5m/15m tick reports on every call, which sorts the
// whole tick history, so they must never be reached on an uncached path.
private double extractTpsValue(TickRegionScheduler.RegionScheduleHandle handle) {
if (getTickReport5s == null) return server.getTPS()[0];
try {
Object report = getTickReport5s.invoke(handle, System.nanoTime());
return extractAverage(report);
Expand All @@ -95,6 +88,7 @@ private double extractTpsValue(TickRegionScheduler.RegionScheduleHandle handle)
}

private double extractMsptValue(TickRegionScheduler.RegionScheduleHandle handle) {
if (getTickReport5s == null) return server.getAverageTickTime();
try {
Object report = getTickReport5s.invoke(handle, System.nanoTime());
return extractAverage(report) / 1000000.0;
Expand Down
Loading