From 20de647c47ccf13bd84a67da6b601d1f8c56b4ee Mon Sep 17 00:00:00 2001 From: gonzalociocca Date: Wed, 7 Dec 2016 12:16:36 -0300 Subject: [PATCH] Lagless Threaded Queue Hope to see this implemented, mcmmo has caused tons of lag on my factions having 150+ players connected at the same time, the time of each save from the users took 100ms each causing a huge lag spike of 5-10seconds on my server every 10 minutes. The queue is tested, and thread safe, if the server is stopped the queue would be stopped also. (dunno if it can thrown an exception? when the server is closed of course.) --- .../nossr50/runnables/SaveTimerTask.java | 52 +++++++++++++++---- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/gmail/nossr50/runnables/SaveTimerTask.java b/src/main/java/com/gmail/nossr50/runnables/SaveTimerTask.java index 9e60d1da4..1b2fc411e 100644 --- a/src/main/java/com/gmail/nossr50/runnables/SaveTimerTask.java +++ b/src/main/java/com/gmail/nossr50/runnables/SaveTimerTask.java @@ -1,24 +1,56 @@ package com.gmail.nossr50.runnables; +import com.gmail.nossr50.datatypes.player.PlayerProfile; +import com.google.common.collect.Lists; import org.bukkit.scheduler.BukkitRunnable; - -import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.party.PartyManager; -import com.gmail.nossr50.runnables.player.PlayerProfileSaveTask; import com.gmail.nossr50.util.player.UserManager; +import java.util.LinkedList; public class SaveTimerTask extends BukkitRunnable { + LinkedList profilelist = Lists.newLinkedList(); + int tasknamecount = 0; + /** + * Example Calculations + * Save took 100ms + pause of 50ms = 150ms + * Default Save Period = 600Seconds + * 600.000/150ms = 4000 Players saved + * 1 Minute = 400 Players Saved (Less than 30 seconds could cause ConcurrentModificationExceptions sometimes.) + * Advantages: Prevent High CPU Usage Spikes, + * Prevent Stopping the ServerThread due to synchronization on the .save() method, + * Smooth Synchronized Saving. + * AVG Save Time on my server(100players): (15000ms)(new Threaded Queue - +50ms/per delay) vs (10100ms)(mcMMO default - +1ms/per delay) + * My point of view: Creating too many runnables on a synchronized method when the others arent finished isnt wise, so i replaced it with one thread.*/ @Override public void run() { - // All player data will be saved periodically through this - int count = 1; - + tasknamecount++; for (McMMOPlayer mcMMOPlayer : UserManager.getPlayers()) { - new PlayerProfileSaveTask(mcMMOPlayer.getProfile()).runTaskLaterAsynchronously(mcMMO.p, count); - count++; + profilelist.add(mcMMOPlayer.getProfile()); } - - PartyManager.saveParties(); + Thread tr = new Thread(new Runnable() { + @Override + public void run() { + /*The thread stops itself when profilelist is empty, and after saving the parties. + you could re-use the thread, but for that you need to make more changes to other classes, there isnt + much difference about it.*/ + while (!profilelist.isEmpty()) { + PlayerProfile pp = profilelist.poll(); + //Check for a nullpointer?, i simply dont trust the UserManager. + if(pp!=null){pp.save();} + try { + Thread.sleep(50L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + //Save parties after finishing saving the players. + PartyManager.saveParties(); + } + }); + tr.setName("mcMMO Saving Task #"+tasknamecount); + tr.setDaemon(false); + tr.start(); } + }