mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-02 22:47:37 +01:00
Wrote a performance test generation utility
Not yet finished, does not yet generate all necessary data for tests. It would be a good idea to store this data in SQLite files and then import those to MySQL if necessary when running performance tests. Idea is to allow generating multiple different scenarios and then measure the performance of different endpoints to estimate time complexity and find bottlenecks.
This commit is contained in:
parent
d4b4aacd69
commit
2240b7094e
@ -0,0 +1,122 @@
|
||||
package utilities;
|
||||
|
||||
import com.djrapitops.plan.gathering.domain.BaseUser;
|
||||
import com.djrapitops.plan.gathering.domain.FinishedSession;
|
||||
import com.djrapitops.plan.identification.Server;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import com.djrapitops.plan.storage.database.DaggerDatabaseTestComponent;
|
||||
import com.djrapitops.plan.storage.database.Database;
|
||||
import com.djrapitops.plan.storage.database.DatabaseTestComponent;
|
||||
import com.djrapitops.plan.storage.database.transactions.StoreServerInformationTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.PlayerServerRegisterTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.StoreJoinAddressTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.StoreSessionTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.WorldNameStoreTransaction;
|
||||
import net.playeranalytics.plugin.scheduling.TimeAmount;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class PerformanceTestDataGenerator {
|
||||
|
||||
public static Path tempDir;
|
||||
private static Database database;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
tempDir = createTempDir();
|
||||
|
||||
DatabaseTestComponent component = DaggerDatabaseTestComponent.builder()
|
||||
.bindTemporaryDirectory(tempDir)
|
||||
.build();
|
||||
|
||||
DBPreparer dbPreparer = new DBPreparer(component, RandomData.randomNonPrivilegedPort());
|
||||
database = dbPreparer.prepareMySQL()
|
||||
.orElseThrow(() -> new IllegalStateException("Could not initialize database"));
|
||||
|
||||
int numberOfServers = 1;
|
||||
int worldsPerServer = 1;
|
||||
int numberOfJoinAddresses = 50;
|
||||
int numberOfPlayers = 1000;
|
||||
int sessionsPerDay = 100;
|
||||
|
||||
long timespan = TimeAmount.MONTH.toMillis(2);
|
||||
long earliestDate = System.currentTimeMillis() - timespan;
|
||||
|
||||
long numberOfSessions = sessionsPerDay * TimeUnit.MILLISECONDS.toDays(timespan);
|
||||
long numberOfTPSEntries = TimeUnit.MILLISECONDS.toMinutes(timespan);
|
||||
long numberOfPingEntries = TimeUnit.MILLISECONDS.toMinutes(timespan) * sessionsPerDay / 20;
|
||||
|
||||
List<ServerUUID> serverUUIDs = RandomData.pickMultiple(numberOfServers, ServerUUID::randomUUID);
|
||||
Map<ServerUUID, String[]> allWorlds = new HashMap<>();
|
||||
for (ServerUUID serverUUID : serverUUIDs) {
|
||||
Server server = RandomData.randomServer(serverUUID);
|
||||
database.executeTransaction(new StoreServerInformationTransaction(server));
|
||||
|
||||
List<String> worlds = RandomData.pickMultiple(worldsPerServer, () -> RandomData.randomString(30));
|
||||
allWorlds.put(serverUUID, worlds.toArray(new String[0]));
|
||||
for (String world : worlds) {
|
||||
database.executeTransaction(new WorldNameStoreTransaction(serverUUID, world));
|
||||
}
|
||||
}
|
||||
|
||||
List<String> joinAddresses = RandomData.pickMultiple(numberOfJoinAddresses, () -> RandomData.randomString(255));
|
||||
for (String joinAddress : joinAddresses) {
|
||||
database.executeTransaction(new StoreJoinAddressTransaction(joinAddress));
|
||||
}
|
||||
|
||||
|
||||
List<BaseUser> players = RandomData.pickMultiple(numberOfPlayers, () -> RandomData.randomBaseUser(earliestDate));
|
||||
Map<UUID, BaseUser> playerLookup = players.stream()
|
||||
.collect(Collectors.toMap(BaseUser::getUuid, Function.identity()));
|
||||
|
||||
List<FinishedSession> sessions = RandomData.pickMultiple(numberOfSessions, () -> {
|
||||
ServerUUID server = RandomData.pickAtRandom(serverUUIDs);
|
||||
UUID[] playerUUIDs = RandomData.pickMultiple(RandomData.randomInt(1, 8), () -> RandomData.pickAtRandom(players))
|
||||
.stream()
|
||||
.map(BaseUser::getUuid)
|
||||
.distinct()
|
||||
.toArray(UUID[]::new);
|
||||
|
||||
return RandomData.randomSession(
|
||||
server,
|
||||
allWorlds.get(server),
|
||||
playerUUIDs
|
||||
);
|
||||
});
|
||||
|
||||
Map<ServerUUID, Set<BaseUser>> playersToRegister = new HashMap<>();
|
||||
for (FinishedSession session : sessions) {
|
||||
UUID playerUUID = session.getPlayerUUID();
|
||||
ServerUUID serverUUID = session.getServerUUID();
|
||||
|
||||
Set<BaseUser> usersOfServer = playersToRegister.computeIfAbsent(serverUUID, k -> new HashSet<>());
|
||||
usersOfServer.add(playerLookup.get(playerUUID));
|
||||
}
|
||||
|
||||
for (var usersOfServer : playersToRegister.entrySet()) {
|
||||
ServerUUID serverUUID = usersOfServer.getKey();
|
||||
for (BaseUser baseUser : usersOfServer.getValue()) {
|
||||
database.executeTransaction(new PlayerServerRegisterTransaction(
|
||||
baseUser.getUuid(),
|
||||
baseUser::getRegistered,
|
||||
baseUser.getName(),
|
||||
serverUUID,
|
||||
() -> RandomData.pickAtRandom(joinAddresses)));
|
||||
}
|
||||
}
|
||||
|
||||
for (FinishedSession session : sessions) {
|
||||
database.executeTransaction(new StoreSessionTransaction(session));
|
||||
}
|
||||
}
|
||||
|
||||
private static Path createTempDir() throws IOException {
|
||||
return Files.createTempDirectory("plan-performance-test-data-generator");
|
||||
}
|
||||
|
||||
}
|
@ -21,6 +21,7 @@ import com.djrapitops.plan.delivery.domain.Nickname;
|
||||
import com.djrapitops.plan.delivery.rendering.json.graphs.line.Point;
|
||||
import com.djrapitops.plan.gathering.domain.*;
|
||||
import com.djrapitops.plan.gathering.domain.event.JoinAddress;
|
||||
import com.djrapitops.plan.identification.Server;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.KillsTable;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
@ -47,6 +48,11 @@ public class RandomData {
|
||||
return ThreadLocalRandom.current().nextInt(rangeStart, rangeEnd);
|
||||
}
|
||||
|
||||
public static int randomNonPrivilegedPort() {
|
||||
return ThreadLocalRandom.current()
|
||||
.nextInt(65535 - 1024) + 1024;
|
||||
}
|
||||
|
||||
public static long randomTime() {
|
||||
return randomTimeAfter(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60L));
|
||||
}
|
||||
@ -99,7 +105,11 @@ public class RandomData {
|
||||
return from[randomInt(0, from.length)];
|
||||
}
|
||||
|
||||
public static <T> List<T> pickMultiple(int howMany, Supplier<T> supplier) {
|
||||
public static <T> T pickAtRandom(List<T> from) {
|
||||
return from.get(randomInt(0, from.size()));
|
||||
}
|
||||
|
||||
public static <T> List<T> pickMultiple(long howMany, Supplier<T> supplier) {
|
||||
List<T> picked = new ArrayList<>();
|
||||
for (int i = 0; i < howMany; i++) {
|
||||
picked.add(supplier.get());
|
||||
@ -112,9 +122,13 @@ public class RandomData {
|
||||
}
|
||||
|
||||
public static FinishedSession randomSession(ServerUUID serverUUID, String[] worlds, UUID... uuids) {
|
||||
return randomSession(RandomData.randomTime(), serverUUID, worlds, uuids);
|
||||
}
|
||||
|
||||
public static FinishedSession randomSession(long after, ServerUUID serverUUID, String[] worlds, UUID... uuids) {
|
||||
DataMap extraData = new DataMap();
|
||||
extraData.put(WorldTimes.class, RandomData.randomWorldTimes(worlds));
|
||||
long start = RandomData.randomTime();
|
||||
long start = RandomData.randomTimeAfter(after);
|
||||
long end = RandomData.randomTimeAfter(start);
|
||||
|
||||
if (uuids.length >= 2) {
|
||||
@ -210,4 +224,30 @@ public class RandomData {
|
||||
.map(JoinAddress::new)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static Server randomServer(ServerUUID serverUUID) {
|
||||
return new Server(
|
||||
serverUUID,
|
||||
RandomData.randomString(16),
|
||||
"http://localhost",
|
||||
RandomData.randomVersion()
|
||||
);
|
||||
}
|
||||
|
||||
private static String randomVersion() {
|
||||
return RandomData.randomInt(1, 20)
|
||||
+ "." +
|
||||
RandomData.randomInt(0, 200)
|
||||
+ " build " +
|
||||
RandomData.randomInt(0, 100000);
|
||||
}
|
||||
|
||||
public static BaseUser randomBaseUser(long earliestDate) {
|
||||
return new BaseUser(
|
||||
UUID.randomUUID(),
|
||||
RandomData.randomString(20),
|
||||
RandomData.randomLong(earliestDate, System.currentTimeMillis()),
|
||||
RandomData.randomInt(0, 100)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -22,11 +22,11 @@ import com.djrapitops.plan.settings.config.paths.WebserverSettings;
|
||||
import com.djrapitops.plan.storage.database.SQLDB;
|
||||
import com.djrapitops.plan.utilities.logging.PluginErrorLogger;
|
||||
import net.playeranalytics.plugin.PlatformAbstractionLayer;
|
||||
import utilities.RandomData;
|
||||
import utilities.dagger.DaggerPlanPluginComponent;
|
||||
import utilities.dagger.PlanPluginComponent;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* Test utility for creating a dagger PlanComponent using a mocked Plan.
|
||||
@ -58,8 +58,7 @@ public class PluginMockComponent {
|
||||
public PlanSystem getPlanSystem() throws Exception {
|
||||
initComponent();
|
||||
PlanSystem system = component.system();
|
||||
system.getConfigSystem().getConfig().set(WebserverSettings.PORT, ThreadLocalRandom.current()
|
||||
.nextInt(65535 - 1024) + 1024); // Random non-privileged port
|
||||
system.getConfigSystem().getConfig().set(WebserverSettings.PORT, RandomData.randomNonPrivilegedPort());
|
||||
return system;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user