- 7,099
- 324
- 1,510
Сервак в продакшене через какое-то время заполняет всю выделенную память и начинает жутко фризить из-за частых вызовов gc.
Сделал дамп кучи, посмотрел его в EclipseMemoryAnalizer, там один игрок занимает 10гб
Вот эта коллекция с пакетами для отправки игроку - занимает 10гб, они там как-то копятся и не удаляются.
Такое бывает в разное время у разных игроков.
Посмотрел ванильную форжу, не нашел возможной причины застревания пакетов.
Юзается ядро catserver, версия git-CatServer-1.12.2-222f2a5f.
В катсервере патчи посмотрел, вроде там нет существенных отличий этой части логики.
В качестве быстрой заплатки сделал мод, который раз в 10 мин смотрит всех игроков и очищает эту коллекцию у тех, у кого больше 1000 элементов
Прошла пара дней и ситуация не изменилась.
Что посоветуете с этим делать?
Сделал дамп кучи, посмотрел его в EclipseMemoryAnalizer, там один игрок занимает 10гб
EntityPlayerMP -> connection: NetHandlerPlayServer -> netManager: NetworkManager -> outboundPacketsQueue: Queue<InboundHandlerTuplePacketListener>
Вот эта коллекция с пакетами для отправки игроку - занимает 10гб, они там как-то копятся и не удаляются.
Такое бывает в разное время у разных игроков.
Посмотрел ванильную форжу, не нашел возможной причины застревания пакетов.
Юзается ядро catserver, версия git-CatServer-1.12.2-222f2a5f.
В катсервере патчи посмотрел, вроде там нет существенных отличий этой части логики.
В качестве быстрой заплатки сделал мод, который раз в 10 мин смотрит всех игроков и очищает эту коллекцию у тех, у кого больше 1000 элементов
Java:
@Mod(modid = "packet_leak_fix", acceptableRemoteVersions = "*")
@Mod.EventBusSubscriber
public class Main {
private static int tick = 0;
@SubscribeEvent
public static void serverTick(TickEvent.ServerTickEvent event) {
if (event.phase == TickEvent.Phase.END) {
tick++;
if (tick > 20 * 60 * 10) {
tick = 0;
for (EntityPlayerMP player : FMLCommonHandler.instance().getMinecraftServerInstance().getPlayerList().getPlayers()) {
Queue<NetworkManager.InboundHandlerTuplePacketListener> outboundPacketsQueue = player.connection.netManager.outboundPacketsQueue;
if (outboundPacketsQueue.size() > 1000) {
outboundPacketsQueue.clear();
}
}
}
}
}
}
Что посоветуете с этим делать?