From 415376ce0899eba3573f9edff6bb93e4d30a9b40 Mon Sep 17 00:00:00 2001 From: P0nk Date: Mon, 12 Apr 2021 21:06:05 +0200 Subject: [PATCH] Load skills async on startup --- src/main/java/client/SkillFactory.java | 17 ++++++++--------- src/main/java/net/server/Server.java | 21 ++++++++++++++++----- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/main/java/client/SkillFactory.java b/src/main/java/client/SkillFactory.java index 5f337e2d36..b41f8f5657 100644 --- a/src/main/java/client/SkillFactory.java +++ b/src/main/java/client/SkillFactory.java @@ -31,33 +31,32 @@ import java.util.HashMap; import java.util.Map; public class SkillFactory { - private static Map skills = new HashMap<>(); - private static MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(MapleDataProviderFactory.fileInWZPath("Skill.wz")); + private static volatile Map skills = new HashMap<>(); + private static final MapleDataProvider datasource = MapleDataProviderFactory.getDataProvider(MapleDataProviderFactory.fileInWZPath("Skill.wz")); public static Skill getSkill(int id) { - if (!skills.isEmpty()) { - return skills.get(id); - } - return null; + return skills.get(id); } public static void loadAllSkills() { + final Map loadedSkills = new HashMap<>(); final MapleDataDirectoryEntry root = datasource.getRoot(); - int skillid; for (MapleDataFileEntry topDir : root.getFiles()) { // Loop thru jobs if (topDir.getName().length() <= 8) { for (MapleData data : datasource.getData(topDir.getName())) { // Loop thru each jobs if (data.getName().equals("skill")) { for (MapleData data2 : data) { // Loop thru each jobs if (data2 != null) { - skillid = Integer.parseInt(data2.getName()); - skills.put(skillid, loadFromData(skillid, data2)); + int skillId = Integer.parseInt(data2.getName()); + loadedSkills.put(skillId, loadFromData(skillId, data2)); } } } } } } + + skills = loadedSkills; } private static Skill loadFromData(int id, MapleData data) { diff --git a/src/main/java/net/server/Server.java b/src/main/java/net/server/Server.java index f7348572c4..f0b0e96ff1 100644 --- a/src/main/java/net/server/Server.java +++ b/src/main/java/net/server/Server.java @@ -84,6 +84,9 @@ import java.time.Duration; import java.time.Instant; import java.util.*; import java.util.Map.Entry; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; @@ -824,6 +827,7 @@ public class Server { public void init() { Instant beforeInit = Instant.now(); log.info("Cosmic v{} starting up.", ServerConstants.VERSION); + final ExecutorService initExecutor = Executors.newFixedThreadPool(10); if (YamlConfig.config.server.SHUTDOWNHOOK) { Runtime.getRuntime().addShutdownHook(new Thread(shutdown(false))); @@ -849,15 +853,13 @@ public class Server { throw new IllegalStateException(sqle); } + final List> futures = new ArrayList<>(); + futures.add(initExecutor.submit(() -> SkillFactory.loadAllSkills())); + ThreadManager.getInstance().start(); initializeTimelyTasks(); // aggregated method for timely tasks thanks to lxconan long timeToTake = System.currentTimeMillis(); - SkillFactory.loadAllSkills(); - final double skillLoadTime = (System.currentTimeMillis() - timeToTake) / 1000.0; - log.info("Skills loaded in {} seconds", skillLoadTime); - - timeToTake = System.currentTimeMillis(); CashItemFactory.getSpecialCashItems(); final double itemLoadTime = (System.currentTimeMillis() - timeToTake) / 1000.0; @@ -897,6 +899,15 @@ public class Server { log.info("Families loaded in {} seconds", familyLoadTime); } + for (Future future : futures) { + try { + future.get(); + } catch (Exception e) { + log.error("Failed to run all startup-bound loading tasks", e); + throw new IllegalStateException(e); + } + } + IoBuffer.setUseDirectBuffer(false); // join IO operations performed by lxconan IoBuffer.setAllocator(new SimpleBufferAllocator()); acceptor = new NioSocketAcceptor();