ThreadPool manager rework.

This commit is contained in:
MobiusDev
2017-08-23 05:23:31 +00:00
parent 374c53df4b
commit b77de360af
718 changed files with 3180 additions and 7193 deletions

View File

@@ -309,7 +309,6 @@ import handlers.telnethandlers.server.ServerAbort;
import handlers.telnethandlers.server.ServerRestart;
import handlers.telnethandlers.server.ServerShutdown;
import handlers.telnethandlers.server.Status;
import handlers.telnethandlers.server.ThreadPoolDebug;
import handlers.usercommandhandlers.ChannelDelete;
import handlers.usercommandhandlers.ChannelInfo;
import handlers.usercommandhandlers.ChannelLeave;
@@ -751,7 +750,6 @@ public class MasterHandler
TelnetServer.getInstance().addHandler(new ServerRestart());
TelnetServer.getInstance().addHandler(new ServerShutdown());
TelnetServer.getInstance().addHandler(new Status());
TelnetServer.getInstance().addHandler(new ThreadPoolDebug());
TelnetServer.getInstance().addHandler(new handlers.telnethandlers.server.Debug());
}

View File

@@ -20,14 +20,12 @@ import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.GameServer;
import com.l2jmobius.gameserver.GameTimeController;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.cache.HtmCache;
import com.l2jmobius.gameserver.data.xml.impl.AdminData;
import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
@@ -72,14 +70,6 @@ public class AdminServerInfo implements IAdminCommandHandler
html.replace("%usedMem%", (RunTime.maxMemory() / mb) - (((RunTime.maxMemory() - RunTime.totalMemory()) + RunTime.freeMemory()) / mb));
html.replace("%freeMem%", ((RunTime.maxMemory() - RunTime.totalMemory()) + RunTime.freeMemory()) / mb);
html.replace("%totalMem%", Runtime.getRuntime().maxMemory() / 1048576);
html.replace("%theardInfoGen%", buildTheardInfo("GENERAL"));
html.replace("%theardInfoEff%", buildTheardInfo("EFFECTS"));
html.replace("%theardInfoAi%", buildTheardInfo("AI"));
html.replace("%theardInfoEvent%", buildTheardInfo("EVENT"));
html.replace("%theardInfoPack%", buildTheardInfo("PACKETS"));
html.replace("%theardInfoIOPack%", buildTheardInfo("IOPACKETS"));
html.replace("%theardInfoGenTask%", buildTheardInfo("GENERAL_TASKS"));
html.replace("%theardInfoEvnTask%", buildTheardInfo("EVENT_TASKS"));
activeChar.sendPacket(html);
}
return true;
@@ -96,22 +86,6 @@ public class AdminServerInfo implements IAdminCommandHandler
return days + " Days, " + hours + " Hours, " + TimeUnit.MILLISECONDS.toMinutes(time) + " Minutes";
}
private String buildTheardInfo(String category)
{
final StringBuilder tb = new StringBuilder();
tb.append("<table width=\"270\" border=\"0\" bgcolor=\"444444\">");
for (Entry<String, Object> info : ThreadPoolManager.getInstance().getStats(category).getSet().entrySet())
{
tb.append("<tr>");
tb.append("<td>" + info.getKey() + ":</td>");
tb.append("<td><font color=\"00FF00\">" + info.getValue() + "</font></td>");
tb.append("</tr>");
}
tb.append("</table>");
return tb.toString();
}
private int getPlayersCount(String type)
{
switch (type)

View File

@@ -46,7 +46,7 @@ public class AdminTest implements IAdminCommandHandler
{
if (command.equals("admin_stats"))
{
for (String line : ThreadPoolManager.getInstance().getStats())
for (String line : ThreadPoolManager.getStats())
{
activeChar.sendMessage(line);
}

View File

@@ -57,7 +57,7 @@ public class ClassChange extends AbstractEffect
{
final L2PcInstance player = effected.getActingPlayer();
// TODO: FIX ME - Executing 1 second later otherwise interupted exception during storeCharBase()
ThreadPoolManager.getInstance().scheduleGeneral(() ->
ThreadPoolManager.schedule(() ->
{
final int activeClass = player.getClassId().getId();

View File

@@ -67,7 +67,7 @@ public final class ServitorShare extends AbstractEffect
if (effected != null)
{
ThreadPoolManager.getInstance().scheduleEffect(new ScheduledEffectExitTask(effected, info.getSkill().getId()), 100);
ThreadPoolManager.schedule(new ScheduledEffectExitTask(effected, info.getSkill().getId()), 100);
}
}
}

View File

@@ -162,7 +162,7 @@ public class JailHandler implements IPunishmentHandler
OlympiadManager.getInstance().removeDisconnectedCompetitor(player);
}
ThreadPoolManager.getInstance().scheduleGeneral(new TeleportTask(player, L2JailZone.getLocationIn()), 2000);
ThreadPoolManager.schedule(new TeleportTask(player, L2JailZone.getLocationIn()), 2000);
// Open a Html message to inform the player
final NpcHtmlMessage msg = new NpcHtmlMessage();
@@ -198,7 +198,7 @@ public class JailHandler implements IPunishmentHandler
*/
private static void removeFromPlayer(L2PcInstance player)
{
ThreadPoolManager.getInstance().scheduleGeneral(new TeleportTask(player, L2JailZone.getLocationOut()), 2000);
ThreadPoolManager.schedule(new TeleportTask(player, L2JailZone.getLocationOut()), 2000);
// Open a Html message to inform the player
final NpcHtmlMessage msg = new NpcHtmlMessage();

View File

@@ -68,7 +68,7 @@ public class Debug implements ITelnetCommand
@Override
public String getUsage()
{
return "Debug <decay/packetsend/PacketTP/IOPacketTP/GeneralTP/full>";
return "Debug <decay/packetsend/full>";
}
@Override
@@ -108,90 +108,6 @@ public class Debug implements ITelnetCommand
player.sendPacket(sp);
return "Packet has been sent!";
}
case "PacketTP":
{
final String str = ThreadPoolManager.getInstance().getPacketStats();
int i = 0;
File f = new File("./log/StackTrace-PacketTP-" + i + ".txt");
while (f.exists())
{
i++;
f = new File("./log/StackTrace-PacketTP-" + i + ".txt");
}
f.getParentFile().mkdirs();
try
{
Files.write(f.toPath(), str.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
}
catch (IOException e)
{
LOGGER.log(Level.WARNING, "Couldn't write packet tp.", e);
}
return str;
}
case "IOPacketTP":
{
final String str = ThreadPoolManager.getInstance().getIOPacketStats();
int i = 0;
File f = new File("./log/StackTrace-IOPacketTP-" + i + ".txt");
while (f.exists())
{
i++;
f = new File("./log/StackTrace-IOPacketTP-" + i + ".txt");
}
f.getParentFile().mkdirs();
try
{
Files.write(f.toPath(), str.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
}
catch (IOException e)
{
LOGGER.log(Level.WARNING, "Couldn't write packet tp.", e);
}
return str;
}
case "GeneralTP":
{
final String str = ThreadPoolManager.getInstance().getGeneralStats();
int i = 0;
File f = new File("./log/StackTrace-GeneralTP-" + i + ".txt");
while (f.exists())
{
i++;
f = new File("./log/StackTrace-GeneralTP-" + i + ".txt");
}
f.getParentFile().mkdirs();
try
{
Files.write(f.toPath(), str.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
}
catch (IOException e)
{
LOGGER.log(Level.WARNING, "Couldn't write packet tp.", e);
}
return str;
}
case "GeneralScheduledTP":
{
final String str = ThreadPoolManager.getInstance().getGeneralStats();
int i = 0;
File f = new File("./log/StackTrace-GeneralScheduledTP-" + i + ".txt");
while (f.exists())
{
i++;
f = new File("./log/StackTrace-GeneralScheduledTP-" + i + ".txt");
}
f.getParentFile().mkdirs();
try
{
Files.write(f.toPath(), str.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
}
catch (IOException e)
{
LOGGER.log(Level.WARNING, "Couldn't write packet tp.", e);
}
return str;
}
case "full":
{
final Calendar cal = Calendar.getInstance();
@@ -283,7 +199,7 @@ public class Debug implements ITelnetCommand
}
sb.append("\r\n## Thread Pool Manager Statistics ##\r\n");
for (String line : ThreadPoolManager.getInstance().getStats())
for (String line : ThreadPoolManager.getStats())
{
sb.append(line);
sb.append("\r\n");

View File

@@ -42,9 +42,9 @@ public class Performance implements ITelnetCommand
@Override
public String handle(ChannelHandlerContext ctx, String[] args)
{
ThreadPoolManager.getInstance().purge();
// ThreadPoolManager.purge();
final StringBuilder sb = new StringBuilder();
for (String line : ThreadPoolManager.getInstance().getStats())
for (String line : ThreadPoolManager.getStats())
{
sb.append(line + Config.EOL);
}

View File

@@ -42,9 +42,9 @@ public class Purge implements ITelnetCommand
@Override
public String handle(ChannelHandlerContext ctx, String[] args)
{
ThreadPoolManager.getInstance().purge();
ThreadPoolManager.purge();
final StringBuilder sb = new StringBuilder("STATUS OF THREAD POOLS AFTER PURGE COMMAND:" + Config.EOL);
for (String line : ThreadPoolManager.getInstance().getStats())
for (String line : ThreadPoolManager.getStats())
{
sb.append(line + Config.EOL);
}

View File

@@ -1,171 +0,0 @@
/*
* This file is part of the L2J Mobius project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package handlers.telnethandlers.server;
import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.l2jmobius.Config;
import com.l2jmobius.gameserver.ThreadPoolManager;
import com.l2jmobius.gameserver.ThreadPoolManager.RunnableWrapper;
import com.l2jmobius.gameserver.network.telnet.ITelnetCommand;
import io.netty.channel.ChannelHandlerContext;
/**
* @author UnAfraid
*/
public class ThreadPoolDebug implements ITelnetCommand
{
private static final Logger LOGGER = Logger.getLogger(ThreadPoolDebug.class.getName());
@Override
public String getCommand()
{
return "threadpooldebug";
}
@Override
public String getUsage()
{
return "threadpooldebug [effect, general, ai, events]";
}
@Override
public String handle(ChannelHandlerContext ctx, String[] args)
{
String pool = "_generalScheduledThreadPool";
if (args.length > 0)
{
switch (args[0])
{
case "effect":
{
pool = "_effectsScheduledThreadPool";
break;
}
case "general":
{
pool = "_generalScheduledThreadPool";
break;
}
case "ai":
{
pool = "_aiScheduledThreadPool";
break;
}
case "events":
{
pool = "_eventScheduledThreadPool";
break;
}
default:
{
return args[0] + " is not implemented!";
}
}
}
final ScheduledThreadPoolExecutor executor = getObject(ThreadPoolManager.class, ThreadPoolManager.getInstance(), pool, ScheduledThreadPoolExecutor.class);
if (executor == null)
{
return "Couldn't retreive " + pool + "!";
}
Class<?> adapterClass;
try
{
adapterClass = Class.forName("java.util.concurrent.Executors$RunnableAdapter");
}
catch (Exception e)
{
return e.getMessage();
}
final Map<String, Integer> tasks = new HashMap<>();
for (Runnable run : executor.getQueue())
{
try
{
if (run instanceof FutureTask)
{
final Object callableObject = getObject(FutureTask.class, run, "callable", Object.class);
final Object taskObject = getObject(adapterClass, callableObject, "task", Object.class);
if (taskObject instanceof RunnableWrapper)
{
final Runnable task = getObject(RunnableWrapper.class, taskObject, "_r", Runnable.class);
final String name = task.getClass().getName();
final int times = tasks.containsKey(name) ? tasks.get(name) : 0;
tasks.put(name, times + 1);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
final StringBuilder sb = new StringBuilder();
sb.append(pool + " queue size: " + executor.getQueue().size() + Config.EOL);
tasks.entrySet().stream().sorted(Comparator.comparingInt(Entry::getValue)).forEach(entry -> sb.append("Class: " + entry.getKey() + " = " + entry.getValue() + Config.EOL));
return sb.toString();
}
private static <T> T getObject(Class<?> sourceClass, Object sourceInstance, String fieldName, Class<T> targetClass)
{
try
{
final Field field = sourceClass.getDeclaredField(fieldName);
// Mark down if field was accessible
final boolean isAccessible = field.isAccessible();
// Enforce accessible to retrieve the object associated with this field
if (!isAccessible)
{
field.setAccessible(true);
}
// Get the object
final Object fieldObject = field.get(sourceInstance);
// Restore the original accessible state.
field.setAccessible(isAccessible);
// Make sure the object is the one we expect to be
if (targetClass.isInstance(fieldObject))
{
return targetClass.cast(fieldObject);
}
}
catch (Exception e)
{
LOGGER.log(Level.WARNING, "Error while retrieving object of " + sourceInstance.getClass().getName() + "." + fieldName, e);
}
return null;
}
}