内存优化,减轻GC压力
This commit is contained in:
@@ -9,6 +9,7 @@ import java.net.Inet6Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.net.SocketException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -35,6 +36,7 @@ import org.kne.cloud.network.monitor.MonitorData;
|
||||
import org.kne.cloud.network.monitor.SpeedAndTrafficAndDelayMonitorDataImpl;
|
||||
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorData;
|
||||
import org.kne.cloud.network.monitor.SpeedAndTrafficMonitorDataImpl;
|
||||
import org.kne.io.KNEChannels;
|
||||
import org.kne.membandboost.MembandBoost;
|
||||
|
||||
public class KLALBRoutingProtocol extends Thread{
|
||||
@@ -211,20 +213,15 @@ public class KLALBRoutingProtocol extends Thread{
|
||||
while(true) {
|
||||
|
||||
try {
|
||||
byte[]ca=MembandBoost.allocateUninitializedByteArray(65535);
|
||||
DatagramPacket dgp=new DatagramPacket(ca, ca.length);
|
||||
ds.receive(dgp);
|
||||
//System.out.println(Arrays.toString( Arrays.copyOf( dgp.getData(),dgp.getLength())));
|
||||
ByteArrayInputStream bi=new ByteArrayInputStream(dgp.getData(),0,dgp.getLength());
|
||||
KLALBRoutingProtocolPacket kp=KLALBRoutingProtocolPacket.readKLALBPacketFromChannel(Channels.newChannel(bi));
|
||||
KLALBRoutingProtocolPacket kp=receivePacket();
|
||||
|
||||
switch(kp.getType()) {
|
||||
case KLALBRoutingProtocolPacket.RINFO_REQ:
|
||||
RouterInfo rifr=netmap.get(router.getLocator().getAddress());
|
||||
if(debug)
|
||||
System.out.println("get Request from:"+dgp.getSocketAddress());
|
||||
System.out.println("get Request from:"+kp.getFrom());
|
||||
if(rifr!=null) {
|
||||
writePacket( new RouterInfoPacket( rifr,false,-1), dgp.getSocketAddress());
|
||||
writePacket( new RouterInfoPacket( rifr,false,-1), kp.getFrom());
|
||||
if(debug)
|
||||
System.out.println("response router info:"+rifr);
|
||||
}else {
|
||||
@@ -246,7 +243,7 @@ public class KLALBRoutingProtocol extends Thread{
|
||||
netmap.put(rif.getLocator().getAddress(), rif);
|
||||
noticeUpdate();
|
||||
if(rifp.isFlood()) {
|
||||
floodPacket( dgp.getSocketAddress(), rifp);
|
||||
floodPacket( kp.getFrom(), rifp);
|
||||
|
||||
}
|
||||
|
||||
@@ -259,7 +256,7 @@ public class KLALBRoutingProtocol extends Thread{
|
||||
break;
|
||||
case KLALBRoutingProtocolPacket.JSON_DATA:
|
||||
JsonDataPacket data=(JsonDataPacket) kp;
|
||||
receivers.forEach((v)->{v.accept(dgp.getSocketAddress(),data);});
|
||||
receivers.forEach((v)->{v.accept(kp.getFrom(),data);});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -276,7 +273,32 @@ public class KLALBRoutingProtocol extends Thread{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final ThreadLocal<ByteBuffer> LSDB_RX_BUFFER =
|
||||
ThreadLocal.withInitial(() -> ByteBuffer.allocate(65535));
|
||||
|
||||
private KLALBRoutingProtocolPacket receivePacket() throws IOException {
|
||||
// 2. 获取并重置缓冲区
|
||||
ByteBuffer bbf = LSDB_RX_BUFFER.get();
|
||||
bbf.clear();
|
||||
|
||||
// 3. 构造 DatagramPacket(注意这里要传底层 array 和 capacity)
|
||||
DatagramPacket dgp = new DatagramPacket(bbf.array(), bbf.capacity());
|
||||
|
||||
// 4. 阻塞接收
|
||||
ds.receive(dgp);
|
||||
|
||||
// 5. 限制缓冲区范围到实际收到的长度
|
||||
bbf.limit(dgp.getLength());
|
||||
bbf.position(0);
|
||||
|
||||
// 6. 直接用 KNEChannels 包装 ByteBuffer,避免 ByteArrayInputStream
|
||||
KLALBRoutingProtocolPacket kp = KLALBRoutingProtocolPacket.readKLALBPacketFromChannel(
|
||||
KNEChannels.newReadableChannel(bbf)
|
||||
);
|
||||
if(kp!=null)
|
||||
kp.setFrom(dgp.getSocketAddress());
|
||||
return kp;
|
||||
}
|
||||
private void floodPacket(SocketAddress except,RouterInfoPacket rifp) throws IOException {
|
||||
long asn=rifp.getASN();
|
||||
List<Neighbor>ln= router.getNeighbors();
|
||||
@@ -304,20 +326,34 @@ public class KLALBRoutingProtocol extends Thread{
|
||||
public void sendJsonPacketToAddress(JsonDataPacket pkt,SocketAddress dest) throws IOException {
|
||||
writePacket(pkt,dest);
|
||||
}
|
||||
|
||||
private void writePacket(KLALBRoutingProtocolPacket pkt,SocketAddress dest) throws IOException {
|
||||
ByteArrayOutputStream bos=new ByteArrayOutputStream(65535);
|
||||
KLALBRoutingProtocolPacket.writeKLALBPacketToChannel(Channels.newChannel(bos),pkt);
|
||||
byte[]to=bos.toByteArray();
|
||||
DatagramPacket dgpx=new DatagramPacket(to,to.length);
|
||||
// 1. 在类成员变量处定义一个 64KB 的 ThreadLocal 缓冲区
|
||||
// 注意:这里依然使用 65535,因为你说 LSDB 同步可能需要这么大
|
||||
private static final ThreadLocal<ByteBuffer> LSDB_TX_BUFFER =
|
||||
ThreadLocal.withInitial(() -> ByteBuffer.allocate(65535));
|
||||
|
||||
private void writePacket(KLALBRoutingProtocolPacket pkt, SocketAddress dest) throws IOException {
|
||||
// 2. 从 ThreadLocal 获取,并清空状态
|
||||
ByteBuffer bbf = LSDB_TX_BUFFER.get();
|
||||
bbf.clear();
|
||||
|
||||
// 3. 使用 KNEChannels 绑定到 ByteBuffer,直接写入
|
||||
// 这避免了 ByteArrayOutputStream 内部的动态扩容和拷贝
|
||||
KLALBRoutingProtocolPacket.writeKLALBPacketToChannel(KNEChannels.newWritableChannel(bbf), pkt);
|
||||
|
||||
// 4. 翻转,准备读取数据
|
||||
bbf.flip();
|
||||
|
||||
// 5. 直接拿底层的 byte[] 和真实的 limit 发送
|
||||
DatagramPacket dgpx = new DatagramPacket(bbf.array(), bbf.limit());
|
||||
dgpx.setSocketAddress(dest);
|
||||
|
||||
sendLock.lock();
|
||||
try {
|
||||
ds.send(dgpx);
|
||||
}catch(BindException e) {
|
||||
ds.send(dgpx);
|
||||
} catch (BindException e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Cannot assign:"+dest);
|
||||
}finally {
|
||||
System.err.println("Cannot assign:" + dest);
|
||||
} finally {
|
||||
sendLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user