Created profilers for ping and rtt metrics #77

Implemented averaging of network latency samples via NetworkProfiler
NetworkProfiler handles the interfacing between Profiler plugin and Pinger system
Created IntervalBaseSystem which is a copy of IntervalSystem without dependency on any Aspect
Added support for a PacketListener for Pinger system (receives callbacks for received ping packets)
This commit is contained in:
Collin Smith 2020-06-12 15:51:56 -07:00
parent 2e9e3f2b1f
commit 1c920b461c
4 changed files with 117 additions and 8 deletions

View File

@ -0,0 +1,35 @@
package com.riiablo.engine;
import com.artemis.BaseSystem;
public abstract class IntervalBaseSystem extends BaseSystem {
private final float interval;
protected float acc;
private float delta;
public IntervalBaseSystem(float interval) {
this.interval = interval;
}
protected float getIntervalDelta() {
return interval + delta;
}
protected float getTimeDelta() {
return world.getDelta();
}
@Override
protected boolean checkProcessing() {
acc += getTimeDelta();
if (acc >= interval) {
acc -= interval;
delta = (acc - delta);
return true;
}
return false;
}
}

View File

@ -0,0 +1,54 @@
package com.riiablo.engine.client;
import com.riiablo.Riiablo;
import com.riiablo.engine.IntervalBaseSystem;
import com.riiablo.net.packet.d2gs.Ping;
import com.riiablo.profiler.SystemProfiler;
public class NetworkProfiler extends IntervalBaseSystem implements Pinger.PacketListener {
private static final String TAG = "NetworkProfiler";
private static final boolean DEBUG = !true;
/**
* Seconds to store samples -- averages will be taken of this time frame.
*/
private static final float SAMPLES_DURATION = 30;
protected Pinger pinger;
protected SystemProfiler pingProfiler;
protected SystemProfiler rttProfiler;
private long ping;
private long rtt;
public NetworkProfiler() {
super(SAMPLES_DURATION / SystemProfiler.SAMPLES);
}
@Override
protected void initialize() {
pinger.addPacketListener(this);
pingProfiler = SystemProfiler.create("Ping");
pingProfiler.setColor(0, 1, 1, 1);
rttProfiler = SystemProfiler.create("RTT");
rttProfiler.setColor(1, 0, 1, 1);
}
@Override
protected void processSystem() {
pingProfiler.sample(ping * 1000000);
Riiablo.metrics.ping = pingProfiler.getAverage() / 1000000;
rttProfiler.sample(rtt * 1000000);
Riiablo.metrics.rtt = rttProfiler.getAverage() / 1000000;
}
@Override
public void onPingResponse(Pinger pinger, Ping packet, long ping, long rtt) {
this.ping = ping;
this.rtt = rtt;
}
}

View File

@ -5,24 +5,24 @@ import java.io.OutputStream;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import com.artemis.annotations.All;
import com.artemis.annotations.Wire;
import com.artemis.systems.IntervalSystem;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.net.Socket;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.TimeUtils;
import com.riiablo.Riiablo;
import com.riiablo.engine.IntervalBaseSystem;
import com.riiablo.net.packet.d2gs.D2GS;
import com.riiablo.net.packet.d2gs.D2GSData;
import com.riiablo.net.packet.d2gs.Ping;
@All
public class Pinger extends IntervalSystem {
public class Pinger extends IntervalBaseSystem {
private static final String TAG = "Pinger";
private static final boolean DEBUG = !true;
final Array<PacketListener> packetListeners = new Array<>(false, 16);
@Wire(name = "client.socket")
protected Socket socket;
@ -30,12 +30,14 @@ public class Pinger extends IntervalSystem {
// it may be possible to use Gdx.graphics.getFrameId() -- but that isn't related to engine tick
private int tick;
public long ping;
public long rtt;
// TODO: provide a running average of past N RTTs
// private final double deltas[] = new double[5];
// private int deltaCount;
public Pinger() {
super(null, 1.0f);
super(1.0f);
}
@Override
@ -55,7 +57,21 @@ public class Pinger extends IntervalSystem {
}
public void Ping(Ping packet) {
Riiablo.metrics.ping = TimeUtils.millis() - packet.sendTime() - packet.processTime();
Riiablo.metrics.rtt = TimeUtils.millis() - packet.sendTime();
ping = TimeUtils.millis() - packet.sendTime() - packet.processTime();
rtt = TimeUtils.millis() - packet.sendTime();
notifyPing(packet, ping, rtt);
}
public boolean addPacketListener(PacketListener l) {
packetListeners.add(l);
return true;
}
private void notifyPing(Ping packet, long ping, long rtt) {
for (PacketListener l : packetListeners) l.onPingResponse(this, packet, ping, rtt);
}
public interface PacketListener {
void onPingResponse(Pinger pinger, Ping packet, long ping, long rtt);
}
}

View File

@ -1,9 +1,12 @@
package com.riiablo.screen;
import com.artemis.WorldConfigurationBuilder;
import com.badlogic.gdx.net.Socket;
import com.riiablo.engine.client.ClientNetworkReceiver;
import com.riiablo.engine.client.ClientNetworkSyncronizer;
import com.riiablo.engine.client.NetworkProfiler;
import com.riiablo.engine.client.Pinger;
import com.riiablo.save.CharData;
@ -24,6 +27,7 @@ public class NetworkedGameScreen extends GameScreen {
builder.with(WorldConfigurationBuilder.Priority.HIGH, new ClientNetworkReceiver());
builder.with(new ClientNetworkSyncronizer());
builder.with(new Pinger());
builder.with(new NetworkProfiler());
return builder;
}