mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-11-15 15:16:59 +01:00
Created a benchmark utility
This commit is contained in:
parent
ef0ba83412
commit
ead1b401bc
@ -63,17 +63,15 @@ public class ServerUptimeCalculator {
|
||||
long dataGapThreshold = TimeUnit.MINUTES.toMillis(3);
|
||||
Database database = dbSystem.getDatabase();
|
||||
Optional<Long> latestDataDate = database.query(TPSQueries.fetchLatestTPSEntryForServer(serverUUID)).map(TPS::getDate);
|
||||
Optional<Long> dataBlockStartDate = database.query(TPSQueries.fetchLatestServerStartTime(serverUUID, dataGapThreshold));
|
||||
|
||||
if (latestDataDate.isEmpty() || dataBlockStartDate.isEmpty()) {
|
||||
if (latestDataDate.isEmpty() // No tps data
|
||||
|| System.currentTimeMillis() - latestDataDate.get() > dataGapThreshold // Server has been offline for a while
|
||||
) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (System.currentTimeMillis() - latestDataDate.get() > dataGapThreshold) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return Optional.of(System.currentTimeMillis() - dataBlockStartDate.get());
|
||||
Optional<Long> serverStartDate = database.query(TPSQueries.fetchLatestServerStartTime(serverUUID, dataGapThreshold));
|
||||
return serverStartDate
|
||||
.map(serverStarted -> System.currentTimeMillis() - serverStarted);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.SessionsTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
|
||||
import com.djrapitops.plan.utilities.Benchmark;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
@ -74,6 +75,7 @@ public class ActivityIndexQueries {
|
||||
// Static method class
|
||||
}
|
||||
|
||||
@Benchmark.Slow("407ms")
|
||||
public static Query<Integer> fetchRegularPlayerCount(long date, ServerUUID serverUUID, long playtimeThreshold) {
|
||||
return fetchActivityGroupCount(date, serverUUID, playtimeThreshold, ActivityIndex.REGULAR, 5.1);
|
||||
}
|
||||
@ -120,16 +122,13 @@ public class ActivityIndexQueries {
|
||||
public static Query<Integer> fetchActivityGroupCount(long date, ServerUUID serverUUID, long playtimeThreshold, double above, double below) {
|
||||
String selectActivityIndex = selectActivityIndexSQL();
|
||||
|
||||
String selectIndexes = SELECT + "COALESCE(activity_index, 0) as activity_index" +
|
||||
String selectCount = SELECT + "COUNT(1) as count, COALESCE(activity_index, 0) as activity_index" +
|
||||
FROM + UserInfoTable.TABLE_NAME + " u" +
|
||||
LEFT_JOIN + '(' + selectActivityIndex + ") q2 on q2." + SessionsTable.USER_ID + "=u." + UserInfoTable.USER_ID +
|
||||
WHERE + "u." + UserInfoTable.SERVER_ID + "=" + ServerTable.SELECT_SERVER_ID +
|
||||
AND + "u." + UserInfoTable.REGISTERED + "<=?";
|
||||
|
||||
String selectCount = SELECT + "COUNT(1) as count" +
|
||||
FROM + '(' + selectIndexes + ") i" +
|
||||
WHERE + "i.activity_index>=?" +
|
||||
AND + "i.activity_index<?";
|
||||
AND + "u." + UserInfoTable.REGISTERED + "<=?" +
|
||||
AND + "activity_index>=?" +
|
||||
AND + "activity_index<?";
|
||||
|
||||
return new QueryStatement<>(selectCount) {
|
||||
@Override
|
||||
|
@ -23,6 +23,7 @@ import com.djrapitops.plan.identification.ServerUUID;
|
||||
import com.djrapitops.plan.storage.database.queries.Query;
|
||||
import com.djrapitops.plan.storage.database.queries.QueryStatement;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
|
||||
import com.djrapitops.plan.utilities.Benchmark;
|
||||
import com.djrapitops.plan.utilities.java.Lists;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
@ -247,6 +248,7 @@ public class TPSQueries {
|
||||
};
|
||||
}
|
||||
|
||||
@Benchmark.Slow("1s")
|
||||
public static Query<Optional<DateObj<Integer>>> fetchAllTimePeakPlayerCount(ServerUUID serverUUID) {
|
||||
return fetchPeakPlayerCount(serverUUID, 0);
|
||||
}
|
||||
@ -476,6 +478,7 @@ public class TPSQueries {
|
||||
};
|
||||
}
|
||||
|
||||
@Benchmark.Slow("1s")
|
||||
public static Query<Optional<Long>> fetchLatestServerStartTime(ServerUUID serverUUID, long dataGapThreshold) {
|
||||
String selectPreviousRowNumber = SELECT +
|
||||
"-1+ROW_NUMBER() over (ORDER BY " + DATE + ") AS previous_rn, " +
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This file is part of Player Analytics (Plan).
|
||||
*
|
||||
* Plan is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License v3 as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Plan is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.djrapitops.plan.utilities;
|
||||
|
||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* @author AuroraLS3
|
||||
*/
|
||||
public class Benchmark {
|
||||
|
||||
private static final Formatter<Long> FORMATTER = new BenchmarkFormatter();
|
||||
|
||||
private Benchmark() {
|
||||
/* Only used for in-development benchmarks. */
|
||||
}
|
||||
|
||||
public static void bench(Runnable runnable) {
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
runnable.run();
|
||||
} finally {
|
||||
long end = System.nanoTime();
|
||||
long durationNanos = end - start;
|
||||
|
||||
printResult(durationNanos);
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T bench(Supplier<T> supplier) {
|
||||
long start = System.nanoTime();
|
||||
try {
|
||||
return supplier.get();
|
||||
} finally {
|
||||
long end = System.nanoTime();
|
||||
long durationNanos = end - start;
|
||||
|
||||
printResult(durationNanos);
|
||||
}
|
||||
}
|
||||
|
||||
private static void printResult(long durationNanos) {
|
||||
String timeTaken = FORMATTER.apply(durationNanos);
|
||||
|
||||
StackTraceElement caller = Thread.currentThread().getStackTrace()[3];
|
||||
String calledFrom = caller.getClassName() + "#" + caller.getMethodName() + ":" + caller.getLineNumber();
|
||||
|
||||
StringBuilder builder = new StringBuilder(timeTaken);
|
||||
while (builder.length() < 16) {
|
||||
builder.append(' ');
|
||||
}
|
||||
builder.append(" - ").append(calledFrom);
|
||||
|
||||
System.out.print(builder.toString());
|
||||
}
|
||||
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
public static @interface Slow {
|
||||
String value(); // How long the benchmark took when done (look at git blame for date)
|
||||
}
|
||||
|
||||
private static class BenchmarkFormatter implements Formatter<Long> {
|
||||
@Override
|
||||
public String apply(Long benchLengthNanos) {
|
||||
long nanos = benchLengthNanos % TimeUnit.MILLISECONDS.toNanos(1L);
|
||||
long millis = TimeUnit.NANOSECONDS.toMillis(benchLengthNanos) % TimeUnit.SECONDS.toMillis(1L);
|
||||
long seconds = TimeUnit.NANOSECONDS.toSeconds(benchLengthNanos);
|
||||
|
||||
String subSeconds = millis <= 0 ? "woah (" + nanos + "ns)" : "fast (" + millis + "ms)";
|
||||
return seconds <= 0 ? subSeconds : "slow (" + seconds + "s)";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -247,4 +247,21 @@ public interface ActivityIndexQueriesTest extends DatabaseTestPreparer {
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
@RepeatedTest(25)
|
||||
default void countRegularPlayers() {
|
||||
storeSessions(session -> true);
|
||||
long playtimeThreshold = TimeUnit.SECONDS.toMillis(1L);
|
||||
Integer expected = 1; // All players are very active
|
||||
Integer result = db().query(ActivityIndexQueries.fetchRegularPlayerCount(System.currentTimeMillis(), serverUUID(), playtimeThreshold));
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
default void noRegularPlayers() {
|
||||
storeSessions(session -> true);
|
||||
long playtimeThreshold = System.currentTimeMillis(); // Threshold is so high it's impossible to be regular
|
||||
Integer expected = 0;
|
||||
Integer result = db().query(ActivityIndexQueries.fetchRegularPlayerCount(System.currentTimeMillis(), serverUUID(), playtimeThreshold));
|
||||
assertEquals(expected, result);
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ import com.djrapitops.plan.storage.database.transactions.commands.RemoveEverythi
|
||||
import com.djrapitops.plan.storage.database.transactions.events.TPSStoreTransaction;
|
||||
import com.djrapitops.plan.utilities.comparators.TPSComparator;
|
||||
import com.djrapitops.plan.utilities.java.Lists;
|
||||
import org.junit.jupiter.api.RepeatedTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import utilities.RandomData;
|
||||
|
||||
@ -59,7 +60,7 @@ public interface TPSQueriesTest extends DatabaseTestPreparer {
|
||||
assertTrue(db().query(TPSQueries.fetchTPSDataOfAllServersBut(0, System.currentTimeMillis(), ServerUUID.randomUUID())).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@RepeatedTest(100)
|
||||
default void playerMaxPeakIsCorrect() {
|
||||
List<TPS> tpsData = RandomData.randomTPS();
|
||||
|
||||
|
@ -73,7 +73,7 @@ public class RandomData {
|
||||
|
||||
public static List<TPS> randomTPS() {
|
||||
List<TPS> test = new ArrayList<>();
|
||||
for (int i = 0; i < randomInt(5, 100); i++) {
|
||||
for (int i = 0; i < randomInt(5, 1000000); i++) {
|
||||
int randInt = r.nextInt();
|
||||
long randLong = Math.abs(r.nextLong());
|
||||
test.add(new TPS(randLong, randLong, randInt, randLong, randLong, randInt, randInt, randLong));
|
||||
|
Loading…
Reference in New Issue
Block a user