Console: Fix lifetime participating bandwidth display (ticket #1706)

Add locking to HopConfig counts
Split participatingMessageCount stat into two stats,
participatingMessageCountAvgPerTunnel for throttle (same as old participatingMessagecount)
and participatingMessageCount for console (straight total)
Fix calculation of stat for throttle by adjusting for new
stat coalesce time (50 not 20 seconds)
This commit is contained in:
zzz
2015-11-13 21:18:21 +00:00
parent a028bba997
commit 8a1f02aa89
6 changed files with 52 additions and 17 deletions

View File

@ -81,12 +81,13 @@ public class TunnelRenderer {
int displayed = 0; int displayed = 0;
for (int i = 0; i < participating.size(); i++) { for (int i = 0; i < participating.size(); i++) {
HopConfig cfg = participating.get(i); HopConfig cfg = participating.get(i);
long count = cfg.getProcessedMessagesCount(); int count = cfg.getProcessedMessagesCount();
if (count <= 0) { if (count <= 0) {
inactive++; inactive++;
continue; continue;
} }
processed += count; // everything that isn't 'recent' is already in the tunnel.participatingMessageCount stat
processed += cfg.getRecentMessagesCount();
if (++displayed > DISPLAY_LIMIT) if (++displayed > DISPLAY_LIMIT)
continue; continue;
out.write("<tr>"); out.write("<tr>");
@ -111,13 +112,13 @@ public class TunnelRenderer {
out.write("<td class=\"cells\" align=\"center\">" + DataHelper.formatDuration2(timeLeft) + "</td>"); out.write("<td class=\"cells\" align=\"center\">" + DataHelper.formatDuration2(timeLeft) + "</td>");
else else
out.write("<td class=\"cells\" align=\"center\">(" + _t("grace period") + ")</td>"); out.write("<td class=\"cells\" align=\"center\">(" + _t("grace period") + ")</td>");
out.write("<td class=\"cells\" align=\"center\">" + cfg.getProcessedMessagesCount() + " KB</td>"); out.write("<td class=\"cells\" align=\"center\">" + count + " KB</td>");
int lifetime = (int) ((_context.clock().now() - cfg.getCreation()) / 1000); int lifetime = (int) ((_context.clock().now() - cfg.getCreation()) / 1000);
if (lifetime <= 0) if (lifetime <= 0)
lifetime = 1; lifetime = 1;
if (lifetime > 10*60) if (lifetime > 10*60)
lifetime = 10*60; lifetime = 10*60;
int bps = 1024 * cfg.getProcessedMessagesCount() / lifetime; int bps = 1024 * count / lifetime;
out.write("<td class=\"cells\" align=\"center\">" + bps + " Bps</td>"); out.write("<td class=\"cells\" align=\"center\">" + bps + " Bps</td>");
if (cfg.getSendTo() == null) if (cfg.getSendTo() == null)
out.write("<td class=\"cells\" align=\"center\">" + _t("Outbound Endpoint") + "</td>"); out.write("<td class=\"cells\" align=\"center\">" + _t("Outbound Endpoint") + "</td>");
@ -188,7 +189,8 @@ public class TunnelRenderer {
else else
out.write("<tr> <td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"Outbound\"></td>"); out.write("<tr> <td class=\"cells\" align=\"center\"><img src=\"/themes/console/images/outbound.png\" alt=\"Outbound\" title=\"Outbound\"></td>");
out.write(" <td class=\"cells\" align=\"center\">" + DataHelper.formatDuration2(timeLeft) + "</td>\n"); out.write(" <td class=\"cells\" align=\"center\">" + DataHelper.formatDuration2(timeLeft) + "</td>\n");
out.write(" <td class=\"cells\" align=\"center\">" + info.getProcessedMessagesCount() + " KB</td>\n"); int count = info.getProcessedMessagesCount();
out.write(" <td class=\"cells\" align=\"center\">" + count + " KB</td>\n");
for (int j = 0; j < info.getLength(); j++) { for (int j = 0; j < info.getLength(); j++) {
Hash peer = info.getPeer(j); Hash peer = info.getPeer(j);
TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j)); TunnelId id = (info.isInbound() ? info.getReceiveTunnelId(j) : info.getSendTunnelId(j));
@ -206,9 +208,9 @@ public class TunnelRenderer {
out.write("</tr>\n"); out.write("</tr>\n");
if (info.isInbound()) if (info.isInbound())
processedIn += info.getProcessedMessagesCount(); processedIn += count;
else else
processedOut += info.getProcessedMessagesCount(); processedOut += count;
} }
out.write("</table>\n"); out.write("</table>\n");
if (in != null) { if (in != null) {

View File

@ -1,3 +1,6 @@
2015-11-13 zzz
* Console: Fix lifetime participating bandwidth display (ticket #1706)
2015-11-12 zzz 2015-11-12 zzz
* Console /configclients: * Console /configclients:
= Fix filtering and escaping = Fix filtering and escaping

View File

@ -276,7 +276,7 @@ class RouterThrottleImpl implements RouterThrottle {
// ok, we're not hosed, but can we handle the bandwidth requirements // ok, we're not hosed, but can we handle the bandwidth requirements
// of another tunnel? // of another tunnel?
rs = _context.statManager().getRate("tunnel.participatingMessageCount"); rs = _context.statManager().getRate("tunnel.participatingMessageCountAvgPerTunnel");
r = null; r = null;
double messagesPerTunnel = DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE; double messagesPerTunnel = DEFAULT_MESSAGES_PER_TUNNEL_ESTIMATE;
if (rs != null) { if (rs != null) {

View File

@ -18,7 +18,7 @@ public class RouterVersion {
/** deprecated */ /** deprecated */
public final static String ID = "Monotone"; public final static String ID = "Monotone";
public final static String VERSION = CoreVersion.VERSION; public final static String VERSION = CoreVersion.VERSION;
public final static long BUILD = 26; public final static long BUILD = 27;
/** for example "-test" */ /** for example "-test" */
public final static String EXTRA = "-rc"; public final static String EXTRA = "-rc";

View File

@ -26,6 +26,7 @@ public class HopConfig {
// these 4 were longs, let's save some space // these 4 were longs, let's save some space
// 2 billion * 1KB / 10 minutes = 3 GBps in a single tunnel // 2 billion * 1KB / 10 minutes = 3 GBps in a single tunnel
// we use synchronization instead of an AtomicInteger here to save space
private int _messagesProcessed; private int _messagesProcessed;
private int _oldMessagesProcessed; private int _oldMessagesProcessed;
//private int _messagesSent; //private int _messagesSent;
@ -125,12 +126,29 @@ public class HopConfig {
/** /**
* Take note of a message being pumped through this tunnel. * Take note of a message being pumped through this tunnel.
* "processed" is for incoming and "sent" is for outgoing (could be dropped in between) * "processed" is for incoming and "sent" is for outgoing (could be dropped in between)
* We use synchronization instead of an AtomicInteger here to save space.
*/ */
public void incrementProcessedMessages() { _messagesProcessed++; } public synchronized void incrementProcessedMessages() { _messagesProcessed++; }
public int getProcessedMessagesCount() { return _messagesProcessed; } public synchronized int getProcessedMessagesCount() { return _messagesProcessed; }
public int getRecentMessagesCount() { /**
* This returns the number of processed messages since
* the last time getAndResetRecentMessagesCount() was called.
* As of 0.9.23, does NOT reset the count, see getAndResetRecentMessagesCount().
*/
public synchronized int getRecentMessagesCount() {
return _messagesProcessed - _oldMessagesProcessed;
}
/**
* This returns the number of processed messages since the last time this was called,
* and resets the count. It should only be called by code that updates the router stats.
* See TunnelDispatcher.updateParticipatingStats().
*
* @since 0.9.23
*/
synchronized int getAndResetRecentMessagesCount() {
int rv = _messagesProcessed - _oldMessagesProcessed; int rv = _messagesProcessed - _oldMessagesProcessed;
_oldMessagesProcessed = _messagesProcessed; _oldMessagesProcessed = _messagesProcessed;
return rv; return rv;
@ -169,8 +187,9 @@ public class HopConfig {
} }
buf.append(" exp. ").append(TunnelCreatorConfig.format(_expiration)); buf.append(" exp. ").append(TunnelCreatorConfig.format(_expiration));
if (_messagesProcessed > 0) int messagesProcessed = getProcessedMessagesCount();
buf.append(" used ").append(_messagesProcessed).append("KB"); if (messagesProcessed > 0)
buf.append(" used ").append(messagesProcessed).append("KB");
return buf.toString(); return buf.toString();
} }
} }

View File

@ -163,9 +163,14 @@ public class TunnelDispatcher implements Service {
ctx.statManager().createRateStat("tunnel.participatingMessageDropped", ctx.statManager().createRateStat("tunnel.participatingMessageDropped",
"Dropped for exceeding share limit", "Tunnels", "Dropped for exceeding share limit", "Tunnels",
new long[] { 60*1000l, 60*10*1000l }); new long[] { 60*1000l, 60*10*1000l });
// count for console
ctx.statManager().createRequiredRateStat("tunnel.participatingMessageCount", ctx.statManager().createRequiredRateStat("tunnel.participatingMessageCount",
"Number of 1KB participating messages", "Tunnels", "Number of 1KB participating messages", "Tunnels",
new long[] { 60*1000l, 60*10*1000l, 60*60*1000l }); new long[] { 60*1000l, 60*10*1000l, 60*60*1000l });
// estimate for RouterThrottleImpl
ctx.statManager().createRequiredRateStat("tunnel.participatingMessageCountAvgPerTunnel",
"Estimate of participating messages per tunnel lifetime", "Tunnels",
new long[] { 60*1000l });
ctx.statManager().createRateStat("tunnel.ownedMessageCount", ctx.statManager().createRateStat("tunnel.ownedMessageCount",
"How many messages are sent through a tunnel we created (period == failures)?", "Tunnels", "How many messages are sent through a tunnel we created (period == failures)?", "Tunnels",
new long[] { 60*1000l, 10*60*1000l, 60*60*1000l }); new long[] { 60*1000l, 10*60*1000l, 60*60*1000l });
@ -711,7 +716,7 @@ public class TunnelDispatcher implements Service {
long tooYoung = _context.clock().now() - 60*1000; long tooYoung = _context.clock().now() - 60*1000;
long tooOld = tooYoung - 9*60*1000; long tooOld = tooYoung - 9*60*1000;
for (HopConfig cfg : _participatingConfig.values()) { for (HopConfig cfg : _participatingConfig.values()) {
long c = cfg.getRecentMessagesCount(); long c = cfg.getAndResetRecentMessagesCount();
bw += c; bw += c;
//bwOut += cfg.getRecentSentMessagesCount(); //bwOut += cfg.getRecentSentMessagesCount();
long created = cfg.getCreation(); long created = cfg.getCreation();
@ -720,9 +725,15 @@ public class TunnelDispatcher implements Service {
tcount++; tcount++;
count += c; count += c;
} }
// This is an estimate of the average number of participating messages per tunnel
// in a tunnel lifetime, used only by RouterThrottleImpl
// 10 minutes / 50 seconds = 12
if (tcount > 0) if (tcount > 0)
count = count * 30 / tcount; count = count * (10*60*1000 / ms) / tcount;
_context.statManager().addRateData("tunnel.participatingMessageCount", count, ms); _context.statManager().addRateData("tunnel.participatingMessageCountAvgPerTunnel", count, ms);
// This is a straight count of the total participating messages, used in the router console
_context.statManager().addRateData("tunnel.participatingMessageCount", bw, ms);
// Bandwidth in bits per second
_context.statManager().addRateData("tunnel.participatingBandwidth", bw*1024/(ms/1000), ms); _context.statManager().addRateData("tunnel.participatingBandwidth", bw*1024/(ms/1000), ms);
// moved to FIFOBandwidthRefiller // moved to FIFOBandwidthRefiller
//_context.statManager().addRateData("tunnel.participatingBandwidthOut", bwOut*1024/(ms/1000), ms); //_context.statManager().addRateData("tunnel.participatingBandwidthOut", bwOut*1024/(ms/1000), ms);