把NTP从平均数改成中位数,防止极端值干扰
This commit is contained in:
@@ -5,6 +5,9 @@ import java.time.LocalDateTime;
|
|||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.ZonedDateTime;
|
import java.time.ZonedDateTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import org.kne.math.Long128;
|
import org.kne.math.Long128;
|
||||||
|
|
||||||
@@ -256,4 +259,27 @@ public class NTPTimestamps {
|
|||||||
.setBit(63);
|
.setBit(63);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Long128 median(List<Long128> values) {
|
||||||
|
Objects.requireNonNull(values);
|
||||||
|
if ( values.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("列表不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. 创建副本并排序
|
||||||
|
List<Long128> sorted = new ArrayList<>(values);
|
||||||
|
sorted.sort(Long128::compareTo);
|
||||||
|
|
||||||
|
// 2. 计算中位数
|
||||||
|
int size = sorted.size();
|
||||||
|
if (size % 2 == 1) {
|
||||||
|
// 奇数个:取中间值
|
||||||
|
return sorted.get(size / 2);
|
||||||
|
} else {
|
||||||
|
// 偶数个:取中间两个的平均值
|
||||||
|
Long128 left = sorted.get(size / 2 - 1);
|
||||||
|
Long128 right = sorted.get(size / 2);
|
||||||
|
return left.add(right).divide(Long128.valueOf(2));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -178,8 +178,8 @@ public class LineMonitorGUI extends XFrame {
|
|||||||
jbfcv.getXYPlot().setBackgroundPaint(Color.BLACK);
|
jbfcv.getXYPlot().setBackgroundPaint(Color.BLACK);
|
||||||
jbfcv.getXYPlot().getRenderer().setSeriesPaint(0, Color.CYAN);
|
jbfcv.getXYPlot().getRenderer().setSeriesPaint(0, Color.CYAN);
|
||||||
jbfcv.getXYPlot().getRenderer().setSeriesPaint(1, Color.YELLOW);
|
jbfcv.getXYPlot().getRenderer().setSeriesPaint(1, Color.YELLOW);
|
||||||
jbfcv.getXYPlot().getRenderer().setSeriesPaint(2, Color.GREEN);
|
jbfcv.getXYPlot().getRenderer().setSeriesPaint(2, Color.RED);
|
||||||
jbfcv.getXYPlot().getRenderer().setSeriesPaint(3, Color.RED);
|
jbfcv.getXYPlot().getRenderer().setSeriesPaint(3, Color.GREEN);
|
||||||
changeFont(jbfcv);
|
changeFont(jbfcv);
|
||||||
sbpdpv = new JLabel();
|
sbpdpv = new JLabel();
|
||||||
sbpdpv.setBorder(new LineBorder(Color.DARK_GRAY));
|
sbpdpv.setBorder(new LineBorder(Color.DARK_GRAY));
|
||||||
|
|||||||
@@ -20,26 +20,26 @@ public class SpeedAndTrafficAndDelayMonitorDataImpl extends SpeedAndTrafficMonit
|
|||||||
downSampler.update();
|
downSampler.update();
|
||||||
if(upSampler.getSnapshotPacketCount()>0&&upSampler.getSnapshotTotalDelay()>0) {
|
if(upSampler.getSnapshotPacketCount()>0&&upSampler.getSnapshotTotalDelay()>0) {
|
||||||
getUploadBandwidth(). recordPacket(KLALBUtils.createGlobalUUID(),0, 0, upSampler.getAvgDelayNanos());
|
getUploadBandwidth(). recordPacket(KLALBUtils.createGlobalUUID(),0, 0, upSampler.getAvgDelayNanos());
|
||||||
|
long odelay=upSampler.getMinDelayNanos();
|
||||||
|
if(outDelayMin==Long.MAX_VALUE||odelay<=outDelayMin) {
|
||||||
|
outDelayMin=odelay;
|
||||||
|
}else{
|
||||||
|
outDelayMin=Math.min(odelay, outDelayMin+10000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(downSampler.getSnapshotPacketCount()>0&&downSampler.getSnapshotTotalDelay()>0) {
|
if(downSampler.getSnapshotPacketCount()>0&&downSampler.getSnapshotTotalDelay()>0) {
|
||||||
getDownloadBandwidth(). recordPacket(KLALBUtils.createGlobalUUID(),0, 0, downSampler.getAvgDelayNanos());
|
getDownloadBandwidth(). recordPacket(KLALBUtils.createGlobalUUID(),0, 0, downSampler.getAvgDelayNanos());
|
||||||
|
long idelay=downSampler.getMinDelayNanos();
|
||||||
|
if(inDelayMin==Long.MAX_VALUE||idelay<=inDelayMin) {
|
||||||
|
inDelayMin=idelay;
|
||||||
|
}else{
|
||||||
|
inDelayMin=Math.min(idelay, inDelayMin+10000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
long time=System.nanoTime();
|
long time=System.nanoTime();
|
||||||
if(time-stime>timewindowmax) {
|
if(time-stime>timewindowmax) {
|
||||||
stime=time;
|
stime=time;
|
||||||
long idelay=getInDelay();
|
|
||||||
if(inDelayMin==Long.MAX_VALUE||idelay<=inDelayMin) {
|
|
||||||
inDelayMin=idelay;
|
|
||||||
}else{
|
|
||||||
inDelayMin=(inDelayMin*99+idelay)/100;
|
|
||||||
}
|
|
||||||
long odelay=getOutDelay();
|
|
||||||
if(outDelayMin==Long.MAX_VALUE||odelay<=outDelayMin) {
|
|
||||||
outDelayMin=odelay;
|
|
||||||
}else{
|
|
||||||
outDelayMin=(outDelayMin*99+odelay)/100;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import org.kne.math.Long128;
|
|||||||
public class NTPContext implements Closeable, AutoCloseable {
|
public class NTPContext implements Closeable, AutoCloseable {
|
||||||
private HighAccuracyClock clock;
|
private HighAccuracyClock clock;
|
||||||
private static final boolean debug = false;
|
private static final boolean debug = false;
|
||||||
private static final int REQUEST_COUNT = 10;
|
private static final int REQUEST_COUNT = 5;
|
||||||
|
|
||||||
private Long128 systemFrequencyOffset = NTPTimestamps.nanosToNtp128BitTimeInterval(new Long128(5000));
|
private Long128 systemFrequencyOffset = NTPTimestamps.nanosToNtp128BitTimeInterval(new Long128(5000));
|
||||||
private Long128 localPrecision = NTPTimestamps.nanosToNtp128BitTimeInterval(new Long128(1000));
|
private Long128 localPrecision = NTPTimestamps.nanosToNtp128BitTimeInterval(new Long128(1000));
|
||||||
@@ -117,7 +117,7 @@ public class NTPContext implements Closeable, AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void putPacket(NTPv4Packet nv4, MultiProtocolSocketAddress inetSocketAddress) {
|
protected void putPacket(NTPv4Packet nv4, MultiProtocolSocketAddress inetSocketAddress) {
|
||||||
checkIP();
|
//checkIP();
|
||||||
List<NTPv4Packet> newv = new Vector<NTPv4Packet>();
|
List<NTPv4Packet> newv = new Vector<NTPv4Packet>();
|
||||||
List<NTPv4Packet> oldv = recvmap.putIfAbsent(inetSocketAddress, newv);
|
List<NTPv4Packet> oldv = recvmap.putIfAbsent(inetSocketAddress, newv);
|
||||||
if (oldv == null) {
|
if (oldv == null) {
|
||||||
@@ -132,25 +132,6 @@ public class NTPContext implements Closeable, AutoCloseable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkIP() {
|
|
||||||
Set<Entry<MultiProtocolSocketAddress, List<NTPv4Packet>>> ens = recvmap.entrySet();
|
|
||||||
for (Iterator<Entry<MultiProtocolSocketAddress, List<NTPv4Packet>>> iterator = ens.iterator(); iterator
|
|
||||||
.hasNext();) {
|
|
||||||
Entry<MultiProtocolSocketAddress, List<NTPv4Packet>> entry = (Entry<MultiProtocolSocketAddress, List<NTPv4Packet>>) iterator
|
|
||||||
.next();
|
|
||||||
AtomicBoolean ab = new AtomicBoolean(false);
|
|
||||||
ios.forEach((x) -> {
|
|
||||||
if (!ab.get())
|
|
||||||
if (x.findPeer(entry.getKey()) != null) {
|
|
||||||
ab.set(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (!ab.get()) {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class PeerInfo implements Comparable<PeerInfo> {
|
private class PeerInfo implements Comparable<PeerInfo> {
|
||||||
private MultiProtocolSocketAddress address;
|
private MultiProtocolSocketAddress address;
|
||||||
@@ -225,14 +206,12 @@ public class NTPContext implements Closeable, AutoCloseable {
|
|||||||
PeerInfo pix = peerInfo.get(0);
|
PeerInfo pix = peerInfo.get(0);
|
||||||
currentClock = pix;
|
currentClock = pix;
|
||||||
int i;
|
int i;
|
||||||
int m = Math.min(peerInfo.size(), 3);
|
List<Long128> adjts = new ArrayList<>();
|
||||||
Long128 bi = Long128.ZERO;
|
for (i = 0; i < peerInfo.size(); i++) {
|
||||||
for (i = 0; i < m; i++) {
|
adjts.add(peerInfo.get(i).getAdj());
|
||||||
PeerInfo pi = peerInfo.get(i);
|
|
||||||
Long128 adjt = pi.getAdj();
|
|
||||||
bi = bi.add(adjt);
|
|
||||||
}
|
}
|
||||||
Long128 delta = bi.divide(Long128.valueOf(i));
|
Long128 delta = NTPTimestamps. median(adjts);
|
||||||
|
//System.out.println(adjts+":"+delta);
|
||||||
avgAdj=(avgAdj*7+delta.abs().longValue())/8;
|
avgAdj=(avgAdj*7+delta.abs().longValue())/8;
|
||||||
Long128 deltaabs=delta.abs();
|
Long128 deltaabs=delta.abs();
|
||||||
if (deltaabs.compareTo(adjustThreshold0) > 0&&firstSync.compareAndSet(true, false)) {
|
if (deltaabs.compareTo(adjustThreshold0) > 0&&firstSync.compareAndSet(true, false)) {
|
||||||
|
|||||||
@@ -405,18 +405,5 @@ public class NTPv4Protocol implements Closeable, AutoCloseable {
|
|||||||
return dgs.isClosed();
|
return dgs.isClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException, InterruptedException {
|
|
||||||
HighAccuracyClock hac = new HighAccuracyClock();
|
|
||||||
NTPContext context = new NTPContext(hac);
|
|
||||||
System.out.println(context);
|
|
||||||
NTPv4Protocol nvc = new NTPv4Protocol(context, new MultiProtocolSocketAddress("{UDP}0.0.0.0:123"));// 106.55.184.199
|
|
||||||
nvc.getPeers().add(new NTPPeer("{UDP}106.55.184.199:123", NTPv4Packet.NTP_CLIENT));
|
|
||||||
nvc.getPeers().add(new NTPPeer("{UDP}time.windows.com:123", NTPv4Packet.NTP_CLIENT));
|
|
||||||
nvc.getPeers().add(new NTPPeer("{UDP}127.0.0.1:123", NTPv4Packet.NTP_SYMMETRIC_ACTIVE));
|
|
||||||
/*
|
|
||||||
* for (int i = 0; i < 10000; i++) { Thread.sleep(1000);
|
|
||||||
* System.out.println(context.getCurrentSelfDispersion128());
|
|
||||||
* System.out.println(context); }
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user