Permalink
Browse files

Adding sim network statistics

  • Loading branch information...
1 parent 7c91d98 commit 7224bc39e33442c913f9f10b1a17ecbf8e0c1d73 @benvanik committed Jul 23, 2012
@@ -257,7 +257,9 @@ gf.sim.ClientSimulator.prototype.sendPendingCommands_ = function(frame) {
writer, gf.sim.packets.ExecCommands.writeInstance);
// Write commands
- this.outgoingCommandList_.write(writer);
+ var writtenCount = this.outgoingCommandList_.write(writer);
+ this.statistics.outgoingCommands += writtenCount;
+ this.statistics.outgoingCommandSize += writer.offset;
// Send
this.session_.send(writer.finish());
@@ -314,6 +316,11 @@ gf.sim.ClientSimulator.prototype.handleSyncSimulation_ =
var deleteEntityCount = reader.readVarInt();
var commandCount = reader.readVarInt();
+ this.statistics.entityCreates += createEntityCount;
+ this.statistics.entityUpdates += updateEntityCount;
+ this.statistics.entityDeletes += deleteEntityCount;
+ this.statistics.incomingCommands += commandCount;
+
// Confirm prediction sequence number
// This performs the slicing of the stashed command list to be only those
// sent or unsent and not yet confirmed
@@ -325,8 +332,12 @@ gf.sim.ClientSimulator.prototype.handleSyncSimulation_ =
// TODO(benvanik): cached parenting list
var parentingRequired = null;
+ var startOffset = 0;
+
// Create entities
for (var n = 0; n < createEntityCount; n++) {
+ startOffset = reader.offset;
+
// Read entity ID, uncompress into full ID
var entityId = reader.readVarInt() << 1;
@@ -348,6 +359,7 @@ gf.sim.ClientSimulator.prototype.handleSyncSimulation_ =
// Load initial values
entity.read(reader);
+ this.statistics.entityCreateSize += reader.offset - startOffset;
// Add to simulation
this.addEntity(entity);
@@ -367,6 +379,8 @@ gf.sim.ClientSimulator.prototype.handleSyncSimulation_ =
// Update entities
for (var n = 0; n < updateEntityCount; n++) {
+ startOffset = reader.offset;
+
// Read entity ID, uncompress into full ID
var entityId = reader.readVarInt() << 1;
@@ -380,14 +394,18 @@ gf.sim.ClientSimulator.prototype.handleSyncSimulation_ =
// Load delta values
entity.readDelta(reader);
+ this.statistics.entityUpdateSize += reader.offset - startOffset;
gf.log.write('<- update entity', entityId);
}
// Delete entities
for (var n = 0; n < deleteEntityCount; n++) {
+ startOffset = reader.offset;
+
// Read entity ID, uncompress into full ID
var entityId = reader.readVarInt() << 1;
+ this.statistics.entityDeleteSize += reader.offset - startOffset;
// Find entity
var entity = this.getEntity(entityId);
@@ -423,6 +441,8 @@ gf.sim.ClientSimulator.prototype.handleSyncSimulation_ =
// Commands
for (var n = 0; n < commandCount; n++) {
+ startOffset = reader.offset;
+
// Read command type
var commandTypeId = reader.readVarInt();
var commandFactory = this.getCommandFactory(commandTypeId);
@@ -435,6 +455,7 @@ gf.sim.ClientSimulator.prototype.handleSyncSimulation_ =
// Read command data
var command = commandFactory.allocate();
command.read(reader);
+ this.statistics.incomingCommandSize += reader.offset - startOffset;
// Queue for processing
this.incomingCommandList_.addCommand(command);
View
@@ -64,7 +64,7 @@ gf.sim.Command = function(commandFactory) {
* @param {!gf.net.PacketReader} reader Packet reader.
*/
gf.sim.Command.prototype.read = function(reader) {
- this.time = reader.readUint32() / 1000;
+ this.time = reader.readVarInt() / 1000;
this.targetEntityId = reader.readVarInt();
};
@@ -74,7 +74,7 @@ gf.sim.Command.prototype.read = function(reader) {
* @param {!gf.net.PacketWriter} writer Packet writer.
*/
gf.sim.Command.prototype.write = function(writer) {
- writer.writeUint32((this.time * 1000) | 0);
+ writer.writeVarInt((this.time * 1000) | 0);
writer.writeVarInt(this.targetEntityId);
};
@@ -138,7 +138,7 @@ gf.sim.PredictedCommand.prototype.read = function(reader) {
goog.base(this, 'read', reader);
this.sequence = reader.readVarInt();
- this.timeDelta = reader.readUint32() / 1000;
+ this.timeDelta = reader.readVarInt() / 1000;
};
@@ -150,5 +150,5 @@ gf.sim.PredictedCommand.prototype.write = function(writer) {
writer.writeVarInt(this.sequence);
// TODO(benvanik): write compressed time - this could probably fit in 16bits
- writer.writeUint32((this.timeDelta * 1000) | 0);
+ writer.writeVarInt((this.timeDelta * 1000) | 0);
};
View
@@ -65,6 +65,13 @@ gf.sim.Observer = function(simulator, session, user) {
this.simulator_ = simulator;
/**
+ * Statistics for fast access.
+ * @private
+ * @type {!gf.sim.Statistics}
+ */
+ this.statistics_ = simulator.statistics;
+
+ /**
* Network session.
* @private
* @type {!gf.net.ServerSession}
@@ -295,6 +302,8 @@ gf.sim.Observer.prototype.flush = function(time) {
this.lastFlushTime_ = time;
// TODO(benvanik): ignore if not enough time has elapsed
+ var startOffset = 0;
+
// Prepare packet
var writer = this.writer_;
writer.begin(this.confirmedSequence_);
@@ -317,7 +326,10 @@ gf.sim.Observer.prototype.flush = function(time) {
}
// Add command
+ startOffset = writer.offset;
writer.addCommand(command);
+ this.statistics_.outgoingCommands++;
+ this.statistics_.outgoingCommandSize += writer.offset - startOffset;
}
this.outgoingCommandList_.resetList();
}
@@ -341,12 +353,19 @@ gf.sim.Observer.prototype.flush = function(time) {
}
// Add create/update/delete based on flags
+ startOffset = writer.offset;
if (dirtyFlags & gf.sim.EntityDirtyFlag.DELETED) {
writer.addDeleteEntity(entity);
+ this.statistics_.entityDeletes++;
+ this.statistics_.entityDeleteSize += writer.offset - startOffset;
} else if (dirtyFlags & gf.sim.EntityDirtyFlag.CREATED) {
writer.addCreateEntity(entity);
+ this.statistics_.entityCreates++;
+ this.statistics_.entityCreateSize += writer.offset - startOffset;
} else if (dirtyFlags & gf.sim.EntityDirtyFlag.UPDATED) {
writer.addUpdateEntity(entity);
+ this.statistics_.entityUpdates++;
+ this.statistics_.entityUpdateSize += writer.offset - startOffset;
}
}
@@ -400,6 +400,10 @@ gf.sim.ServerSimulator.prototype.handleExecCommands_ =
// Read header
var commandCount = reader.readVarInt();
+ // Update stats
+ this.statistics.incomingCommands += commandCount;
+ this.statistics.incomingCommandSize += packet.data.length;
+
// Commands
for (var n = 0; n < commandCount; n++) {
// Read command type
View
@@ -28,6 +28,7 @@ goog.require('gf.sim.EntityDirtyFlag');
goog.require('gf.sim.IEntityWatcher');
goog.require('gf.sim.PredictedCommand');
goog.require('gf.sim.Scheduler');
+goog.require('gf.sim.Statistics');
goog.require('gf.sim.commands');
goog.require('goog.array');
goog.require('goog.asserts');
@@ -55,6 +56,12 @@ gf.sim.Simulator = function(runtime, baseEntityId) {
goog.base(this, runtime);
/**
+ * Statistics information, refreshed every frame.
+ * @type {!gf.sim.Statistics}
+ */
+ this.statistics = new gf.sim.Statistics();
+
+ /**
* Event scheduler.
* @private
* @type {!gf.sim.Scheduler}
View
@@ -0,0 +1,190 @@
+/**
+ * Copyright 2012 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @author benvanik@google.com (Ben Vanik)
+ */
+
+goog.provide('gf.sim.Statistics');
+
+
+
+/**
+ * Basic statistics about the simulation.
+ */
+gf.sim.Statistics = function() {
+ /**
+ * @type {number}
+ */
+ this.entityCreates = 0;
+
+ /**
+ * @type {number}
+ */
+ this.entityCreateSize = 0;
+
+ /**
+ * @type {number}
+ */
+ this.entityUpdates = 0;
+
+ /**
+ * @type {number}
+ */
+ this.entityUpdateSize = 0;
+
+ /**
+ * @type {number}
+ */
+ this.entityDeletes = 0;
+
+ /**
+ * @type {number}
+ */
+ this.entityDeleteSize = 0;
+
+ /**
+ * @type {number}
+ */
+ this.incomingCommands = 0;
+
+ /**
+ * @type {number}
+ */
+ this.incomingCommandSize = 0;
+
+ /**
+ * @type {number}
+ */
+ this.outgoingCommands = 0;
+
+ /**
+ * @type {number}
+ */
+ this.outgoingCommandSize = 0;
+
+ // TODO(benvanik): # of update ticks
+
+ /**
+ * @type {number}
+ */
+ this.incomingBps = 0;
+
+ /**
+ * @type {number}
+ */
+ this.outgoingBps = 0;
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this.incomingBpsSum_ = 0;
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this.outgoingBpsSum_ = 0;
+
+ /**
+ * @private
+ * @type {number}
+ */
+ this.lastTime_ = 0;
+};
+
+
+/**
+ * Updates statistics by resetting instantaneous and averaging others.
+ * @param {number} time Current frame time.
+ */
+gf.sim.Statistics.prototype.update = function(time) {
+ if (gf.SERVER) {
+ this.outgoingBpsSum_ += this.entityCreateSize;
+ this.outgoingBpsSum_ += this.entityUpdateSize;
+ this.outgoingBpsSum_ += this.entityDeleteSize;
+ } else {
+ this.incomingBpsSum_ += this.entityCreateSize;
+ this.incomingBpsSum_ += this.entityUpdateSize;
+ this.incomingBpsSum_ += this.entityDeleteSize;
+ }
+ this.incomingBpsSum_ += this.incomingCommandSize;
+ this.outgoingBpsSum_ += this.outgoingCommandSize;
+
+ if (time - this.lastTime_ >= 1) {
+ this.lastTime_ = time;
+ this.incomingBps = this.incomingBpsSum_;
+ this.outgoingBps = this.outgoingBpsSum_;
+ this.incomingBpsSum_ = 0;
+ this.outgoingBpsSum_ = 0;
+ }
+
+ this.entityCreates = this.entityCreateSize = 0;
+ this.entityUpdates = this.entityUpdateSize = 0;
+ this.entityDeletes = this.entityDeleteSize = 0;
+ this.incomingCommands = this.incomingCommandSize = 0;
+ this.outgoingCommands = this.outgoingCommandSize = 0;
+};
+
+
+/**
+ * Pads a number with zeros.
+ * @private
+ * @param {number} number Input number.
+ * @param {number} digits Digits to pad to.
+ */
+gf.sim.Statistics.pad_ = function(number, digits) {
+ var s = String(number);
+ while (s.length < digits) {
+ s = ' ' + s;
+ }
+ return s;
+};
+
+
+/**
+ * Gets a debug information string that can be printed to the console.
+ * @return {string} Debug info.
+ */
+gf.sim.Statistics.prototype.getDebugInfo = function() {
+ return [
+ 'i/s:',
+ gf.sim.Statistics.pad_(Math.round(this.incomingBps), 4),
+ ' o/s:',
+ gf.sim.Statistics.pad_(Math.round(this.outgoingBps), 4),
+ ' ec:',
+ gf.sim.Statistics.pad_(this.entityCreates, 2),
+ '/',
+ gf.sim.Statistics.pad_(this.entityCreateSize, 4),
+ ' eu:',
+ gf.sim.Statistics.pad_(this.entityUpdates, 2),
+ '/',
+ gf.sim.Statistics.pad_(this.entityUpdateSize, 4),
+ ' ed:',
+ gf.sim.Statistics.pad_(this.entityDeletes, 2),
+ '/',
+ gf.sim.Statistics.pad_(this.entityDeleteSize, 4),
+ ' ic:',
+ gf.sim.Statistics.pad_(this.incomingCommands, 2),
+ '/',
+ gf.sim.Statistics.pad_(this.incomingCommandSize, 4),
+ ' oc:',
+ gf.sim.Statistics.pad_(this.outgoingCommands, 2),
+ '/',
+ gf.sim.Statistics.pad_(this.outgoingCommandSize, 4)
+ ].join('');
+};
Oops, something went wrong.

0 comments on commit 7224bc3

Please sign in to comment.