Io write Update

Removed usage of busy loop in handling sent packets.
This commit is contained in:
ronancpl
2019-08-30 00:44:05 -03:00
parent efbce82a8b
commit 82d6d6d757
6 changed files with 8 additions and 178 deletions

View File

@@ -61,7 +61,6 @@ import net.server.world.World;
import org.apache.mina.core.session.IoSession;
import net.server.world.announcer.MapleAnnouncerCoordinator;
import client.inventory.MapleInventoryType;
import constants.GameConstants;
import constants.ServerConstants;
@@ -95,7 +94,6 @@ public class MapleClient {
private MapleAESOFB receive;
private final IoSession session;
private MapleCharacter player;
private MapleAnnouncerCoordinator announcer = MapleAnnouncerCoordinator.getInstance();
private int channel = 1;
private int accId = -4;
private boolean loggedIn = false;
@@ -120,6 +118,7 @@ public class MapleClient {
private final Semaphore actionsSemaphore = new Semaphore(7);
private final Lock lock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT, true);
private final Lock encoderLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ENCODER, true);
private final Lock announcerLock = MonitoredReentrantLockFactory.createLock(MonitoredLockType.CLIENT_ANNOUNCER, true);
private static final Lock loginLocks[] = new Lock[200]; // thanks Masterrulax & try2hack for pointing out a bottleneck issue here
private Calendar tempBanCalendar;
private int votePoints;
@@ -1143,13 +1142,6 @@ public class MapleClient {
public void setWorld(int world) {
this.world = world;
World wserv = Server.getInstance().getWorld(world);
if (wserv != null) {
this.announcer = wserv.getAnnouncerCoordinator();
} else {
this.announcer = MapleAnnouncerCoordinator.getInstance();
}
}
public void pongReceived() {
@@ -1475,7 +1467,12 @@ public class MapleClient {
}
public void announce(final byte[] packet) { // thanks GitGud for noticing an opportunity for improvement by overcoming "synchronized announce"
announcer.append(session, packet);
announcerLock.lock();
try {
session.write(packet);
} finally {
announcerLock.unlock();
}
}
public void announceHint(String msg, int length) {

View File

@@ -71,7 +71,6 @@ import net.server.worker.RankingLoginWorker;
import net.server.worker.ReleaseLockWorker;
import net.server.worker.RespawnWorker;
import net.server.world.World;
import net.server.world.announcer.MapleAnnouncerCoordinator;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.buffer.SimpleBufferAllocator;
@@ -950,7 +949,6 @@ public class Server {
System.exit(0);
}
MapleAnnouncerCoordinator.getInstance().init();
System.out.println();
if(ServerConstants.USE_FAMILY_SYSTEM) {

View File

@@ -35,6 +35,7 @@ public enum MonitoredLockType {
CHARACTER_EVT,
CHARACTER_STA,
CLIENT,
CLIENT_ANNOUNCER,
CLIENT_ENCODER,
CLIENT_SESSION,
CLIENT_LOGIN,

View File

@@ -98,7 +98,6 @@ import net.server.worker.ServerMessageWorker;
import net.server.worker.TimedMapObjectWorker;
import net.server.worker.TimeoutWorker;
import net.server.worker.WeddingReservationWorker;
import net.server.world.announcer.MapleAnnouncerCoordinator;
import tools.DatabaseConnection;
import tools.MaplePacketCreator;
import tools.Pair;
@@ -125,7 +124,6 @@ public class World {
private PlayerStorage players = new PlayerStorage();
private MapleMatchCheckerCoordinator matchChecker = new MapleMatchCheckerCoordinator();
private MaplePartySearchCoordinator partySearch = new MaplePartySearchCoordinator();
private MapleAnnouncerCoordinator announcer = new MapleAnnouncerCoordinator();
private final ReentrantReadWriteLock chnLock = new MonitoredReentrantReadWriteLock(MonitoredLockType.WORLD_CHANNELS, true);
private ReadLock chnRLock = chnLock.readLock();
@@ -224,8 +222,6 @@ public class World {
FamilyDailyResetWorker.resetEntitlementUsage(this);
tman.register(new FamilyDailyResetWorker(this), 24 * 60 * 60 * 1000, timeLeft);
}
announcer.init();
}
public int getChannelsSize() {
@@ -557,10 +553,6 @@ public class World {
return partySearch;
}
public MapleAnnouncerCoordinator getAnnouncerCoordinator() {
return announcer;
}
public void addPlayer(MapleCharacter chr) {
players.addPlayer(chr);
}
@@ -2170,7 +2162,6 @@ public class World {
players.disconnectAll();
players = null;
announcer.shutdown();
clearWorldData();
System.out.println("Finished shutting down world " + id + "\r\n");
}

View File

@@ -1,83 +0,0 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.world.announcer;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.mina.core.session.IoSession;
import net.server.world.announcer.MapleAnnouncerEntryPool.SessionPacket;
/**
*
* @author Ronan
*/
public class MapleAnnouncerCoordinator {
private static final MapleAnnouncerCoordinator instance = new MapleAnnouncerCoordinator();
public static MapleAnnouncerCoordinator getInstance() { // world-agnostic Announcer coordinator
return instance;
}
private MapleAnnouncerEntryPool pool = new MapleAnnouncerEntryPool();
private ConcurrentLinkedQueue<SessionPacket> queue = new ConcurrentLinkedQueue<>();
private Thread t;
public void append(IoSession io, byte[] packet) {
queue.offer(pool.getSessionPacket(io, packet));
}
public void init() {
final Runnable r = new Runnable() {
@Override
public void run() {
while (!Thread.interrupted()) {
try {
SessionPacket p = queue.poll();
if (p != null) {
IoSession session = p.getSession();
byte[] packet = p.getPacket();
session.write(packet);
pool.returnSessionPacket(p);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
t = new Thread(r);
t.start();
}
public void shutdown() {
t.interrupt();
try {
t.join();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
queue.clear();
pool.shutdown();
}
}

View File

@@ -1,74 +0,0 @@
/*
This file is part of the HeavenMS MapleStory Server
Copyleft (L) 2016 - 2019 RonanLana
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation version 3 as published by
the Free Software Foundation. You may not use, modify or distribute
this program under any other version of the GNU Affero General Public
License.
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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.server.world.announcer;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.mina.core.session.IoSession;
/**
*
* @author Ronan
*/
public class MapleAnnouncerEntryPool {
private ConcurrentLinkedQueue<SessionPacket> instancedPairs = new ConcurrentLinkedQueue<>();
private final static int initialCount = 20000; // initial length of the instanced pool
public MapleAnnouncerEntryPool() {
for (int i = 0; i < initialCount; i++) {
instancedPairs.offer(new SessionPacket());
}
}
public class SessionPacket {
private IoSession session;
private byte[] packet;
public IoSession getSession() {
return session;
}
public byte[] getPacket() {
return packet;
}
}
public SessionPacket getSessionPacket(IoSession session, byte[] packet) {
SessionPacket sp = instancedPairs.poll();
if (sp == null) {
sp = new SessionPacket();
}
sp.session = session;
sp.packet = packet;
return sp;
}
public void returnSessionPacket(SessionPacket sp) {
instancedPairs.offer(sp);
}
public void shutdown() {
instancedPairs.clear();
}
}