Files
KLALB/src/org/kne/cloud/network/perf/Kperf.java
T
2025-04-24 10:16:38 +08:00

479 lines
16 KiB
Java

package org.kne.cloud.network.perf;
import java.io.IOException;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.nio.channels.UnresolvedAddressException;
import java.util.Objects;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.locks.LockSupport;
import org.kne.cloud.clock.AdjustedNanoClock;
import org.kne.cloud.network.MultipurposeSocketAddress;
import org.kne.cloud.network.SpeedLimiter;
import org.kne.cloud.network.ThreadTool;
import org.kne.cloud.network.ipv6.IPv6Packet;
import org.kne.cloud.network.ipv6.Inet6AddressGroup;
import org.kne.cloud.network.klalb.ADDRPacket;
import org.kne.cloud.network.klalb.ADDRREQPacket;
import org.kne.cloud.network.klalb.BWINFPacket;
import org.kne.cloud.network.klalb.IPv6OverKLALBPacket;
import org.kne.cloud.network.klalb.KLALBPacket;
import org.kne.cloud.network.klalb.KLALBPacketLink;
import org.kne.cloud.network.klalb.KLALBUtils;
import org.kne.cloud.network.klalb.PINGPacket;
import org.kne.cloud.network.klalb.PONGPacket;
import org.kne.cloud.network.klalb.VADDRACKPacket;
import org.kne.cloud.network.klalb.VADDRPacket;
import org.kne.cloud.network.klalb.VADDRREQPacket;
import org.kne.cloud.network.monitor.MonitorData;
import org.kne.cloud.network.monitor.QueueingMonitorDataImpl;
public class Kperf implements Runnable{
private ConcurrentLinkedQueue<KLALBPacket> IsendDequeList = new ConcurrentLinkedQueue<KLALBPacket>();
//private PriorityBlockingQueue<KLALBPacket> sendDequeList = new PriorityBlockingQueue<KLALBPacket>();
private static final boolean debug = true;
private static final boolean showpacket = false;
private volatile AdjustedNanoClock adjnc = new AdjustedNanoClock();
private MultipurposeSocketAddress targetAddress;
private MultipurposeSocketAddress bindAddress;
private volatile boolean connected=false;
private volatile KLALBPacketLink link;
private QueueingMonitorDataImpl monitor=new QueueingMonitorDataImpl();
private volatile boolean closed = false;
private volatile Thread tlock;
public Kperf(MultipurposeSocketAddress targetAddress,MultipurposeSocketAddress bindAddress) {
Objects.requireNonNull(targetAddress);
this.targetAddress=targetAddress;
this.bindAddress=bindAddress;
}
public Kperf(MultipurposeSocketAddress targetAddress) {
this(targetAddress,new MultipurposeSocketAddress("[::0]:0"));
}
public Kperf(KLALBPacketLink link) {
Objects.requireNonNull(link);
this.link=link;
}
private SpeedLimiter test = new SpeedLimiter(MIN_SPEED,10000000L);
private static long MIN_SPEED=64*1024L;
private SpeedLimiter congress = new SpeedLimiter(10000000L);
private long congressSpeed = 0;
private double loadPercent = 1.01;
KLALBPacket testPacket=null;
//kperf {KLALB_Stream}[2486:1:f189:7589:f1f7:6f5e:b2eb:1]:4564
//kperf {KLALB_Stream}[2486:1::8888]:4564
@Override
public void run() {
Thread tc = ThreadTool.makeVDaemonThreadIfSupport("测速控制线程", () -> {
final int wtimes=5;
System.out.println("测速开始!");
try {
long startTime;
/*System.out.println("测试1/4:延迟测试");
test.setLimitspeed(0);
startTime=System.nanoTime();
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("上传延迟:%.3fms 下载延迟:%.3fms\n", monitor.getOutDelay()/1000000.0,monitor.getInDelay()/1000000.0);
Thread.sleep(1000);
}
System.out.printf("上传延迟 最小:%.3fms 平均:%.3fms 抖动:%.3fms\n",monitor.getOutDelayMin()/1000000.0,monitor.getOutDelayAvg()/1000000.0,monitor.getOutJitter()/1000000.0);
System.out.printf("下载延迟 最小:%.3fms 平均:%.3fms 抖动:%.3fms\n",monitor.getInDelayMin()/1000000.0,monitor.getInDelayAvg()/1000000.0,monitor.getInJitter()/1000000.0);
System.out.println("等待时间"+wtimes+"s");
Thread.sleep(wtimes*1000);
*/
startTime=System.nanoTime();
if(targetAddress!=null) {
System.out.println("测试2/4:下载带宽测试");
test.setLimitspeed(0);
testPacket=new TESTNPacket(60000);
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("下载带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getInSpeedAvg()));
Thread.sleep(1000);
}
System.out.printf("下载带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getInSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getInSpeedMax2()));
}else {
System.out.println("测试2/4:上传带宽测试");
test.setLimitspeed(1000L*1024L*1024L*1024L);
testPacket=new TESTNPacket(60000);
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("上传带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getOutSpeedAvg()));
Thread.sleep(1000);
}
System.out.printf("上传带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getOutSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getOutSpeedMax2()));
}
System.out.println("等待时间"+wtimes+"s");
Thread.sleep(wtimes*1000);
startTime=System.nanoTime();
if(targetAddress!=null) {
System.out.println("测试3/4:上传带宽测试");
test.setLimitspeed(1000L*1024L*1024L*1024L);
testPacket=new TESTNPacket(60000);
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("上传带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getOutSpeedAvg()));
Thread.sleep(1000);
}
System.out.printf("上传带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getOutSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getOutSpeedMax2()));
}else {
System.out.println("测试3/4:下载带宽测试");
test.setLimitspeed(0);
testPacket=new TESTNPacket(60000);
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("下载带宽:%s/s\n", KLALBUtils.bytesUnit(monitor.getInSpeedAvg()));
Thread.sleep(1000);
}
System.out.printf("下载带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getInSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getInSpeedMax2()));
}
System.out.println("等待时间"+wtimes+"s");
Thread.sleep(wtimes*1000);
startTime=System.nanoTime();
if(targetAddress!=null) {
System.out.println("测试2/4:下载包转发率测试");
test.setLimitspeed(0);
testPacket=new TEST1Packet();
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("下载包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getInPPS()));
Thread.sleep(1000);
}
}else {
System.out.println("测试2/4:上传包转发率测试");
test.setLimitspeed(1000L*1024L*1024L*1024L);
testPacket=new TEST1Packet();
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("上传包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getOutPPS()));
Thread.sleep(1000);
}
//System.out.printf("上传带宽 平均:%s/s 最大:%s/s\n",KLALBUtils.bytesUnit(monitor.getOutSpeedAvg2()),KLALBUtils.bytesUnit(monitor.getOutSpeedMax2()));
}
System.out.println("等待时间"+wtimes+"s");
Thread.sleep(wtimes*1000);
startTime=System.nanoTime();
if(targetAddress!=null) {
System.out.println("测试3/4:上传包转发率测试");
test.setLimitspeed(1000L*1024L*1024L*1024L);
testPacket=new TEST1Packet();
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("上传包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getOutPPS()));
Thread.sleep(1000);
}
}else {
System.out.println("测试3/4:下载包转发率测试");
test.setLimitspeed(0);
testPacket=new TEST1Packet();
for (int i = 0; i < 30; i++) {
System.out.printf("%.2fs\t", (System.nanoTime()- startTime)/1000000000.0);
System.out.printf("下载包转发率:%sPPS\n", KLALBUtils.defaultUnit(monitor.getInPPS()));
Thread.sleep(1000);
}
}
System.out.println("等待时间"+wtimes+"s");
Thread.sleep(wtimes*1000);
System.out.println("测速结束!");
} catch (InterruptedException e) {
System.out.println("测速被中断!");
}finally {
close();
}
});
try {
monitor.setState(MonitorData.CONNECTING);
if(link==null)
link=KLALBUtils.createKLALBPacketLink(bindAddress, targetAddress,false,20000);
link.setSoTimeout(20000);
Thread t = ThreadTool.makeVDaemonThreadIfSupport("测速发送线程", () -> {
tlock = Thread.currentThread();
try {
KLALBPacket kpp = null;
while ((!link.isClosed()) && (!closed)) {
// TimeDebugger tdb=new TimeDebugger();
// tdb.putTime("start");
if(checkBandwidthReportTime()) {
writePacketToKPL(new BWINFPacket(monitor.getOutSpeedAvg2(), monitor.getInSpeedAvg2()));
}
if (checkPingTimeSleep()) {
writePacketToKPL(new PINGPacket(System.nanoTime()));
}else {
KLALBPacket kpip = IsendDequeList.poll();
if (kpip != null) {
writePacketToKPL(kpip);
}else {
KLALBPacket testp=testPacket;
if (testp!=null&&test.checkTransmit(testp.getLength())) {
writePacketToKPL(testp);
}else {
LockSupport.parkNanos(1000000);
}
}
}
Thread.yield();
}
} catch (IOException | UnresolvedAddressException e) {
if (debug)
e.printStackTrace();
} finally {
try {
link.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
t.start();
boolean fst = true;
while ((!link.isClosed()) && (!closed)) {
KLALBPacket kpp = readPacketFromKPL();
if (kpp == null) {
break;
}
switch (kpp.getType()) {
case KLALBPacket.PING:
sendIPacket(new PONGPacket(((PINGPacket) kpp).getTime() ,kpp.getRcvtime(), System.nanoTime()));
break;
case KLALBPacket.PONG:
if (fst) {
// coll.resetCoolingTime();
monitor.setState(MonitorData.ONLINE);
connected=true;
if(targetAddress!=null) {
System.out.println("连接地址"+targetAddress+"成功!");
}else {
System.out.println("接受地址"+link.toString()+"连接成功!");
}
tc.start();
fst = false;
}
PONGPacket png = (PONGPacket) kpp;
long ul = png.getRcvtime() - png.getTimepingsnd()-(png.getTimepongsnd()-png.getTimepingrcv());
long DsndDelayFactor0 = png.getTimepingrcv() - png.getTimepingsnd();
long DrcvDelayFactor0 = png.getRcvtime() - png.getTimepongsnd();
long DsndDelayFactor;
long DrcvDelayFactor;
adjnc.getLock().lock();
try {
adjnc.calibrate(png.getTimepongsnd() + ul / 2 - png.getRcvtime(), ul / 2);
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
if (DsndDelayFactor < 0) {
if (DrcvDelayFactor < 0) {
} else {
adjnc.setDelta(adjnc.getDelta() + DsndDelayFactor);
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
}
} else {
if (DrcvDelayFactor < 0) {
adjnc.setDelta(adjnc.getDelta() - DrcvDelayFactor);
DsndDelayFactor = DsndDelayFactor0 - adjnc.getDelta();
DrcvDelayFactor = DrcvDelayFactor0 + adjnc.getDelta();
}
}
} finally {
adjnc.getLock().unlock();
}
if (DsndDelayFactor >= 0 && DrcvDelayFactor >= 0) {
monitor.setOutDelay(DsndDelayFactor);
monitor.setInDelay(DrcvDelayFactor);
monitor.setRecentPingNanoTime(png.getTimepingsnd());
//pingInterval = monitor.getLatencyAvg()+2000000L;
//double load = 1 - monitor.getOutDelayMin() / (double) monitor.getOutDelay();
loadPercent =Math.max( 1.2,0.4);
}
LockSupport.unpark(tlock);
break;
case KLALBPacket.BWINF:
BWINFPacket bwi = (BWINFPacket) kpp;
if (bwi.getDownSpeed() >= congressSpeed) {
congressSpeed = bwi.getDownSpeed();
} else {
congressSpeed = (congressSpeed * 999 + bwi.getDownSpeed()) / 1000;
}
congress.setLimitspeed(Math.max(MIN_SPEED,(long) (congressSpeed * loadPercent)) );
// System.out.println(congressSpeed);
break;
case KLALBPacket.TESTN:
break;
}
Thread.yield();
}
} catch (IOException e) {
if(monitor.getState()==MonitorData.CONNECTING)
System.out.println("连接目标地址失败!");
if(debug)
e.printStackTrace();
}finally {
monitor.setState(MonitorData.OFFLINE);
if(link!=null) {
try {
link.close();
} catch (IOException e) {
e.printStackTrace();
}
}
tc.interrupt();
}
}
private volatile long time = System.nanoTime();
private volatile long pingInterval = 10000000L;
private volatile long pingIntervalSleep = 200000000L;
private boolean checkPingTime() {
long cu = System.nanoTime();
if (cu - time > pingInterval) {
time = cu;
return true;
} else {
return false;
}
}
private boolean checkPingTimeSleep() {
long cu = System.nanoTime();
if (cu - time > pingIntervalSleep) {
time = cu;
return true;
} else {
return false;
}
}
private volatile long bwtime = System.nanoTime();
private volatile long bwpingInterval = 10000000L;
private volatile long bwpingIntervalSleep = 100000000L;
private boolean checkBandwidthReportTime(){
long cu = System.nanoTime();
if (cu - bwtime > bwpingIntervalSleep) {
bwtime = cu;
return true;
} else {
return false;
}
}
public void close() {
closed = true;
monitor.setState(MonitorData.OFFLINE);
try {
if (link != null)
link.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/*protected void sendPacket(KLALBPacket blk) {
blk.markJoinqueuetime();
sendDequeList.add(blk);
LockSupport.unpark(tlock);
}*/
private void sendIPacket(KLALBPacket blk) {
IsendDequeList.add(blk);
LockSupport.unpark(tlock);
}
private KLALBPacket readPacketFromKPL() throws IOException {
KLALBPacket packet = link.readKLALBPacket();
if (showpacket) {
System.out.println("RX:" + packet);
}
if (packet != null) {
packet.putTimePassport("received");
long length=packet.getLength();
monitor.getInTrafficAL().addAndGet(length);
monitor.getInPacketCounterAL().incrementAndGet();
}
return packet;
}
private void writePacketToKPL(KLALBPacket packet) throws IOException {
long length=packet.getLength();
monitor.getOutTrafficAL().addAndGet(length);
monitor.getOutPacketCounterAL().incrementAndGet();
link.writeKLALBPacket(packet);
link.flush();
packet.putTimePassport("sended");
packet.printPassport();
if (showpacket) {
System.err.println("TX:" + packet);
}
}
public void startPerfing() {
ThreadTool.makeVThreadIfSupport("测速接收线程" ,this).start();
}
}