Fixed two bugs with delta calculation:

- if a pong response took more than 5 seconds to receive, another ping
  would be sent. When the pong finally arrived the delta would be
  calculated using the most recently sent ping.
  Fix: don't send more pings while waiting on a pong.
- After a pong is received, the _deltas array is mangled while
  calculating the server delta, making subsequent pongs possibly
  overwrite earlier calculated deltas.
  Fix: calculate using a copy.

Also, changed the delta calculation to be the mean of the deltas rather
than the median. Left code in to do it both ways if this change was not
kosher...


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3990 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2006-03-30 01:08:32 +00:00
parent 07bc269f59
commit 981deb3b6b
2 changed files with 43 additions and 15 deletions
@@ -483,7 +483,7 @@ public class Client
if (_dcalc.isDone()) { if (_dcalc.isDone()) {
Log.debug("Time offset from server: " + _serverDelta + "ms."); Log.debug("Time offset from server: " + _serverDelta + "ms.");
_dcalc = null; _dcalc = null;
} else { } else if (_dcalc.shouldSendPing()) {
// otherwise, send another ping // otherwise, send another ping
PingRequest req = new PingRequest(); PingRequest req = new PingRequest();
_comm.postMessage(req); _comm.postMessage(req);
@@ -621,17 +621,15 @@ public class Client
*/ */
void gotPong (PongResponse pong) void gotPong (PongResponse pong)
{ {
// if we're not calculating our client/server time delta, then we // if we're not currently calculating our client/server delta, then
// don't need to do anything with the pong // we can throw away the pong
if (_dcalc == null) { if (_dcalc != null) {
return; // we update the delta after every receipt so as to immediately
// obtain an estimate of the clock delta and then refine it as
// more packets come in
_dcalc.gotPong(pong);
_serverDelta = _dcalc.getTimeDelta();
} }
// we update the delta after every receipt so as to immediately
// obtain an estimate of the clock delta and then refine it as
// more packets come in
_dcalc.gotPong(pong);
_serverDelta = _dcalc.getTimeDelta();
} }
/** /**
@@ -1,5 +1,5 @@
// //
// $Id: DeltaCalculator.java,v 1.8 2004/10/22 01:19:55 mdb Exp $ // $Id$
// //
// Narya library - tools for developing networked games // Narya library - tools for developing networked games
// Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved
@@ -45,6 +45,14 @@ public class DeltaCalculator
_deltas = new long[CLOCK_SYNC_PING_COUNT]; _deltas = new long[CLOCK_SYNC_PING_COUNT];
} }
/**
* Should we send another ping?
*/
public boolean shouldSendPing ()
{
return (_ping == null) && !isDone();
}
/** /**
* Must be called when a ping message is sent to the server. * Must be called when a ping message is sent to the server.
*/ */
@@ -69,6 +77,7 @@ public class DeltaCalculator
// make a note of when the ping message was sent and when the pong // make a note of when the ping message was sent and when the pong
// response was received (both in client time) // response was received (both in client time)
long send = _ping.getPackStamp(), recv = pong.getUnpackStamp(); long send = _ping.getPackStamp(), recv = pong.getUnpackStamp();
_ping = null; // clear out the saved sent ping
// make a note of when the pong response was sent (in server time) // make a note of when the pong response was sent (in server time)
// and the processing delay incurred on the server // and the processing delay incurred on the server
@@ -93,9 +102,30 @@ public class DeltaCalculator
*/ */
public long getTimeDelta () public long getTimeDelta ()
{ {
// sort the estimates and return one from the middle if (_iter == 0) { // no responses yet
Arrays.sort(_deltas); return 0L;
return _deltas[_deltas.length/2]; }
if (true) {
// return the mean
long est = 0;
for (int ii=0; ii < _iter; ii++) {
est += _deltas[ii];
}
return (est / _iter);
} else {
// return the median value
// copy the deltas array so that we don't alter things before
// all pongs have arrived
long[] deltasCopy = new long[_iter];
System.arraycopy(_deltas, 0, deltasCopy, 0, _iter);
// sort the estimates and return one from the middle
Arrays.sort(deltasCopy);
return deltasCopy[deltasCopy.length/2];
}
} }
/** /**