Lag when Loading Lots of player data.

Discussion in 'Plugin Development' started by jebbo, Mar 30, 2015.

Thread Status:
Not open for further replies.
  1. Offline

    jebbo

    So when I want to Load lots of player Data for my Ranking I get the Problem that the server
    laggs out for 1-3 Seconds or even more.

    There are around 400 Players in the file.


    This is how I sort the data:

    Code:
    public List<String> getTopKills() {
            List<String> ls = new ArrayList<String>();
            for (String s : JPC.cfg.getKeys(false)) {
                PD pd = new PD(s);
                String s1 = pd.getName() + ":" + pd.getKills();
                ls.add(s1);
            }
            Collections.sort(ls, comp);
            return ls;
        }
    And I'm using this to use the data:
    Code:
    List<String> l = getTopKills();
                                            for (String s : l) {
                                                if (i <= 10) {
                                                    i++;
                                                    PD pd = new PD(s.split(":")[0]);
                                                    p.sendMessage("§c#" + i
                                                            + " §8» §b"
                                                            + pd.getName()
                                                            + " §8| §b"
                                                            + pd.getKills()
                                                            + " §8| §b"
                                                            + pd.getDeaths()
                                                            + " §8| §b"
                                                            + pd.getKDR());
                                                }
                                            }
    When I use this, the Server laggs for about 1-3 Seconds.

    I really need to stop this lagg, I don't really know why it happens.

    Thanks for any help.
     
  2. Offline

    TGRHavoc

    @jebbo
    Sounds like you're doing to much work on the main thread. Have you tried using a separate thread for completing the "heavy duty" parts of your code.
     
  3. Offline

    KingFaris11

    This won't solve your actual problem, probably what the person above suggested would, but this is just a bonus.

    You could just use for (int i) instead of for (String s).

    Code:
    List<String> l = getTopKills();
    for (int i = 0; i < l.size(); i++) {
        if (i < 10) {
            PD pd = new PD(l.get(i).split(":")[0]);
            p.sendMessage("§c#" + i + " §8» §b" + pd.getName() + " §8| §b" + pd.getKills() + " §8| §b" + pd.getDeaths() + " §8| §b" + pd.getKDR());
        } else break;
    }
    
    This means that once i is greater than or equal to 10, exit out of the loop. In your method, it still continues to loop, doing nothing but increasing the time taken to complete running the code, regardless of the scale.
     
  4. Offline

    jebbo

    How would I use this with this for example:

    Code:
    public static List<String> getTopVotes() {
            List<String> ls = new ArrayList<String>();
            for (String s : JPC.cfg.getKeys(false)) {
                PD pd = new PD(s);
                String s1 = pd.getName() + ":" + pd.getVotes();
                ls.add(s1);
            }
            Collections.sort(ls, comp);
            return ls;
        }
    I can't really see through how I would get the List and using a seperate thread.

    Thanks!
     
  5. Offline

    mythbusterma

    @TGRHavoc

    Or don't violate the thread safety of the server by using classes that are explicitly not thread safe on multiple threads.


    @jebbo

    Show us all of your code, the snippets you posted shouldn't cause any issues as far as I can tell, and stop using static when it's not warranted.
     
  6. Offline

    caseif

    @mythbusterma The code could potentially be restructured to be threadsafe, however

    Alternatively, OP, you could split the work up across multiple ticks. i.e. only process a certain amount of data each tick.
     
  7. Offline

    mythbusterma

    @caseif

    So you would load all the data on one thread, put it in a thread safe structure, then pass it to another thread? Seems like the brunt of the work is still being done on the main thread.

    Again, my point still stands that the work he's doing should take nowhere near a noticeable amount of time.
     
  8. Offline

    caseif

    @mythbusterma
    I didn't really look into the code he was proposing, so it wouldn't necessarily be easy or efficient here, but in some cases it's a perfectly fine solution.
     
  9. Offline

    jebbo

    Thanks to all the replies!

    I came up with this:

    Code:
    BukkitScheduler scheduler =
                            Bukkit.getServer().getScheduler();
                            scheduler.runTaskLaterAsynchronously(pl, new Runnable(){
                                @Override
                                public void run() {
                                    ru.sendStatsRanking();
                                }
                            }, 1L);
    ru.sendStatsRanking(); =

    Code:
    public void sendStatsRanking() {
            p.sendMessage("§e<<>>§b=====§e<< §b§lRanking §e>>§b=====§e<<>>");
            p.sendMessage("§ePlatz §8| §eSpieler §8| §eKills §8| §eTode §8| §eKD/r");
            List<String> l = getTopKills();
            int i = 0;
            for (String s : l) {
                if (i <= 10) {
                    i++;
                    PD pd = new PD(s.split(":")[0]);
                    p.sendMessage("§c#" + i + " §8» §b" + pd.getName() + " §8| §b"
                            + pd.getKills() + " §8| §b" + pd.getDeaths()
                            + " §8| §b" + pd.getKDR());
                }
            }
            p.sendMessage("§e<<>>§b=====§e<< §b§lRanking §e>>§b=====§e<<>>");
        }
    Now it doesnt lagg once long, its slowly sending each number of the message in the loop. like with a half second delay. How can I like 'pre load' this and then send it when it's finished?

    Thanks!
     
  10. Offline

    mythbusterma

    @jebbo

    Your code is unsafe at best, and could crash the server.

    Did you not see my post? You're fixing the symptoms rather than addressing the underlying problem.
     
  11. Offline

    jebbo

    I removed the static. What's the problem that can cause the server to crash?
     
  12. Offline

    mythbusterma

    @jebbo

    Violating the thread safety of the server. There should be no issue sorting 400 records on the main thread, you must've been doing something else wrong.
     
  13. Offline

    jebbo

    I can't imagine whats wrong. Also I'd like to hear what part of my code is wrong to improve it.

    I also forgot to add the method I use to compare all the entries:

    Code:
    public Comparator<String> Clancomp = new Comparator<String>() {
            public int compare(String s1, String s2) {
                String[] sp1 = s1.split(":");
                String[] sp2 = s2.split(":");
                double i1 = Double.parseDouble(sp1[1]);
                double i2 = Double.parseDouble(sp2[1]);
                if (i1 > i2) {
                    return -1;
                }
                if (i1 < i2) {
                    return 1;
                }
                return 0;
            }
        };
    I've fixxed the total Lag, but still, its taking up to almost 10 Seconds to sort meanwhile ~600 playerdata.
     
  14. Offline

    mythbusterma

    @jebbo

    It's that method right there. That is an extremely slow comparator, and Collections.sort(...) is not a particularly fast algorithm.

    You should make a more efficient sorting system, and again, the issue with your code is violating the thread safety of the server.
     
Thread Status:
Not open for further replies.

Share This Page