Any idea on how to do that?
#1
I'm updating ClearLagg and I added a command that unloads chunks. It should show memory and chunk count before and after.
Code:
    elseif Split[2] == "unloadchunks" then
        Root = cRoot:Get()
        ramusage = cRoot:GetPhysicalRAMUsage() / 1024
        swapusage = cRoot:GetVirtualRAMUsage() / 1204
        totalusage = ramusage + swapusage
        local Out1 = "Num loaded chunks before: " .. cRoot:Get():GetTotalChunkCount()
        local Out2 = "Ram usage before: " .. totalusage
        Root:SaveAllChunks()
        local UnloadChunks = function(World)
            World:QueueUnloadUnusedChunks()
        end
        cRoot:Get():ForEachWorld(UnloadChunks)
        afterramusage = cRoot:GetPhysicalRAMUsage() / 1024
        afterswapusage = cRoot:GetVirtualRAMUsage() / 1204
        aftertotalusage = ramusage + swapusage
        Out3 = "Num loaded chunks after: " .. cRoot:Get():GetTotalChunkCount()
        Out4 = "Ram usage after: " .. aftertotalusage
        Player:SendMessage(Out1)
        Player:SendMessage(Out2)
        Player:SendMessage(Out3)
        Player:SendMessage(Out4)
        return true
    end
The problem is that it returns the same chunk count and ram usage before and after(probably because of QuequeUnloadUnusedChunks(), that some time ago was instant).
Any idea on how to make it work?
Reply
Thanks given by:
#2
It's most likely because the chunks are not unloaded immediately. Maybe the chunks will be unloaded in the next tick? If so you should delay getting the "after*" stuff until the next tick.

On a side note, you're dividing virtual RAM by 1204, I suppose that should be 1024?
Reply
Thanks given by:
#3
QueueUnloadUnusedChunk adds the chunk to a queue of chunks to unload during the next tick. We don't have any way you can unload instantly because commands are executed on the console thread and the tick thread assumes that other threads won't unload chunks under it.
Reply
Thanks given by:
#4
The chunks are only queued for unloading, because otherwise plugins would cause a lot of deadlocks (a plugin waiting for unloading chunks in one world, while the world is waiting for that same plugin to provide a callback value in its tick thread).

There is no way to know that the chunk unloading caused by the QueueUnloadUnusedChunks() has finished, but there are some workarounds. You can use the HOOK_UNLOADING_CHUNK to keep track of when the last chunk was unloaded, if it was more than N ticks ago (consider N = 5, for example), you can assume that the unloading has finished for that world; once it has finished for all worlds, you can send the stats.

FakeTruth's solution with waiting just one tick isn't sufficient - chunk unloading is asynchronous, it may take several ticks to unload a chunk, and each world ticks in a different thread anyway, which is yet different from the server tick thread.

To complicate matters even more, the SaveAllChunks() doesn't actually wait for the chunks to be saved, it queues a save action, so most chunks won't unload anyway, because they won't be saved yet. Therefore I dare say any plugin trying to do chunk maintenance is destined to fail.
Reply
Thanks given by:
#5
It might be worth adding a mechanism for tracking saves since this is exactly the same problem that is causing https://github.com/mc-server/MCServer/issues/609
Reply
Thanks given by:
#6
Not exactly. The issue #609 (not saving world on server stop) is caused by bad scheduling - we need to rewrite the stop function to schedule a save and schedule a stop only when it's finished for each world.
Reply
Thanks given by:
#7
But how can it wait if it doesnt know when the saves finished?
Reply
Thanks given by:
#8
It doesn't need to know - the world won't stop until the chunks queued for saving dont finish saving (the world storage save queue is empty). So it just queues the chunks for saving and stops the world.
Reply
Thanks given by:
#9
Yup, got it working!Big Grin
But you've to wait 10 seconds... D:
Reply
Thanks given by:




Users browsing this thread: 6 Guest(s)