mirror of
https://github.com/overte-org/overte.git
synced 2025-04-14 07:47:30 +02:00
capture network bandwidth stats from NodeList rather than various places
This commit is contained in:
parent
105b2c5fd7
commit
bee895ba0a
17 changed files with 239 additions and 159 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -38,3 +38,5 @@ interface/resources/visage/*
|
||||||
|
|
||||||
# Ignore interfaceCache for Linux users
|
# Ignore interfaceCache for Linux users
|
||||||
interface/interfaceCache/
|
interface/interfaceCache/
|
||||||
|
|
||||||
|
TAGS
|
||||||
|
|
|
@ -433,6 +433,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(saveScripts()));
|
connect(this, SIGNAL(aboutToQuit()), this, SLOT(saveScripts()));
|
||||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
|
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
|
||||||
|
|
||||||
|
// hook up bandwidth estimator
|
||||||
|
connect(nodeList.data(), SIGNAL(dataSent(const quint8, const int)),
|
||||||
|
&_bandwidthRecorder, SLOT(updateOutboundData(const quint8, const int)));
|
||||||
|
connect(nodeList.data(), SIGNAL(dataReceived(const quint8, const int)),
|
||||||
|
&_bandwidthRecorder, SLOT(updateInboundData(const quint8, const int)));
|
||||||
|
|
||||||
// check first run...
|
// check first run...
|
||||||
bool firstRun = SettingHandles::firstRun.get();
|
bool firstRun = SettingHandles::firstRun.get();
|
||||||
if (firstRun) {
|
if (firstRun) {
|
||||||
|
@ -771,25 +777,8 @@ void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum)
|
||||||
|
|
||||||
void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) {
|
void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) {
|
||||||
foreach(NodeType_t type, destinationNodeTypes) {
|
foreach(NodeType_t type, destinationNodeTypes) {
|
||||||
|
|
||||||
// Perform the broadcast for one type
|
// Perform the broadcast for one type
|
||||||
int nReceivingNodes = DependencyManager::get<NodeList>()->broadcastToNodes(packet, NodeSet() << type);
|
DependencyManager::get<NodeList>()->broadcastToNodes(packet, NodeSet() << type);
|
||||||
|
|
||||||
// Feed number of bytes to corresponding channel of the bandwidth meter, if any (done otherwise)
|
|
||||||
double bandwidth_amount = nReceivingNodes * packet.size();
|
|
||||||
switch (type) {
|
|
||||||
case NodeType::Agent:
|
|
||||||
case NodeType::AvatarMixer:
|
|
||||||
_bandwidthRecorder.avatarsChannel->output.updateValue(bandwidth_amount);
|
|
||||||
_bandwidthRecorder.totalChannel->input.updateValue(bandwidth_amount);
|
|
||||||
break;
|
|
||||||
case NodeType::EntityServer:
|
|
||||||
_bandwidthRecorder.octreeChannel->output.updateValue(bandwidth_amount);
|
|
||||||
_bandwidthRecorder.totalChannel->output.updateValue(bandwidth_amount);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2383,10 +2372,6 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
||||||
|
|
||||||
// make sure we still have an active socket
|
// make sure we still have an active socket
|
||||||
nodeList->writeUnverifiedDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
nodeList->writeUnverifiedDatagram(reinterpret_cast<const char*>(queryPacket), packetLength, node);
|
||||||
|
|
||||||
// Feed number of bytes to corresponding channel of the bandwidth meter
|
|
||||||
_bandwidthRecorder.octreeChannel->output.updateValue(packetLength);
|
|
||||||
_bandwidthRecorder.totalChannel->output.updateValue(packetLength);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -3374,8 +3359,6 @@ int Application::parseOctreeStats(const QByteArray& packet, const SharedNodePoin
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::packetSent(quint64 length) {
|
void Application::packetSent(quint64 length) {
|
||||||
_bandwidthRecorder.octreeChannel->output.updateValue(length);
|
|
||||||
_bandwidthRecorder.totalChannel->output.updateValue(length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString SETTINGS_KEY = "Settings";
|
const QString SETTINGS_KEY = "Settings";
|
||||||
|
|
|
@ -768,9 +768,6 @@ void Audio::handleAudioInput() {
|
||||||
int packetBytes = currentPacketPtr - audioDataPacket;
|
int packetBytes = currentPacketPtr - audioDataPacket;
|
||||||
nodeList->writeDatagram(audioDataPacket, packetBytes, audioMixer);
|
nodeList->writeDatagram(audioDataPacket, packetBytes, audioMixer);
|
||||||
_outgoingAvatarAudioSequenceNumber++;
|
_outgoingAvatarAudioSequenceNumber++;
|
||||||
|
|
||||||
Application::getInstance()->getBandwidthRecorder()->audioChannel->output.updateValue(packetBytes);
|
|
||||||
Application::getInstance()->getBandwidthRecorder()->totalChannel->output.updateValue(packetBytes);
|
|
||||||
}
|
}
|
||||||
delete[] inputAudioSamples;
|
delete[] inputAudioSamples;
|
||||||
}
|
}
|
||||||
|
@ -828,9 +825,6 @@ void Audio::addReceivedAudioToStream(const QByteArray& audioByteArray) {
|
||||||
// Audio output must exist and be correctly set up if we're going to process received audio
|
// Audio output must exist and be correctly set up if we're going to process received audio
|
||||||
_receivedAudioStream.parseData(audioByteArray);
|
_receivedAudioStream.parseData(audioByteArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::getInstance()->getBandwidthRecorder()->audioChannel->input.updateValue(audioByteArray.size());
|
|
||||||
Application::getInstance()->getBandwidthRecorder()->totalChannel->input.updateValue(audioByteArray.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Audio::parseAudioEnvironmentData(const QByteArray &packet) {
|
void Audio::parseAudioEnvironmentData(const QByteArray &packet) {
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
//
|
|
||||||
// BandwidthMeter.cpp
|
|
||||||
// interface/src/ui
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 2015-1-30
|
|
||||||
// Copyright 2015 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Based on code by Tobias Schwinger
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <GeometryCache.h>
|
|
||||||
#include "BandwidthRecorder.h"
|
|
||||||
|
|
||||||
|
|
||||||
BandwidthRecorder::Channel::Channel(char const* const caption,
|
|
||||||
char const* unitCaption,
|
|
||||||
double unitScale,
|
|
||||||
unsigned colorRGBA) :
|
|
||||||
caption(caption),
|
|
||||||
unitCaption(unitCaption),
|
|
||||||
unitScale(unitScale),
|
|
||||||
colorRGBA(colorRGBA)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BandwidthRecorder::BandwidthRecorder() {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BandwidthRecorder::~BandwidthRecorder() {
|
|
||||||
delete audioChannel;
|
|
||||||
delete avatarsChannel;
|
|
||||||
delete octreeChannel;
|
|
||||||
delete metavoxelsChannel;
|
|
||||||
delete totalChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BandwidthRecorder::Stream::Stream(float msToAverage) : _value(0.0f), _msToAverage(msToAverage) {
|
|
||||||
_prevTime.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BandwidthRecorder::Stream::updateValue(double amount) {
|
|
||||||
|
|
||||||
// Determine elapsed time
|
|
||||||
double dt = (double)_prevTime.nsecsElapsed() / 1000000.0; // ns to ms
|
|
||||||
|
|
||||||
// Ignore this value when timer imprecision yields dt = 0
|
|
||||||
if (dt == 0.0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_prevTime.start();
|
|
||||||
|
|
||||||
// Compute approximate average
|
|
||||||
_value = glm::mix(_value, amount / dt,
|
|
||||||
glm::clamp(dt / _msToAverage, 0.0, 1.0));
|
|
||||||
}
|
|
|
@ -39,8 +39,7 @@ void DatagramProcessor::processDatagrams() {
|
||||||
|
|
||||||
while (DependencyManager::get<NodeList>()->getNodeSocket().hasPendingDatagrams()) {
|
while (DependencyManager::get<NodeList>()->getNodeSocket().hasPendingDatagrams()) {
|
||||||
incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
|
incomingPacket.resize(nodeList->getNodeSocket().pendingDatagramSize());
|
||||||
nodeList->getNodeSocket().readDatagram(incomingPacket.data(), incomingPacket.size(),
|
nodeList->readDatagram(incomingPacket, senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
|
||||||
senderSockAddr.getAddressPointer(), senderSockAddr.getPortPointer());
|
|
||||||
|
|
||||||
_inPacketCount++;
|
_inPacketCount++;
|
||||||
_inByteCount += incomingPacket.size();
|
_inByteCount += incomingPacket.size();
|
||||||
|
@ -73,7 +72,7 @@ void DatagramProcessor::processDatagrams() {
|
||||||
|
|
||||||
if (audioMixer) {
|
if (audioMixer) {
|
||||||
audioMixer->setLastHeardMicrostamp(usecTimestampNow());
|
audioMixer->setLastHeardMicrostamp(usecTimestampNow());
|
||||||
audioMixer->recordBytesReceived(incomingPacket.size());
|
// audioMixer->recordBytesReceived(incomingPacket.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -82,8 +81,8 @@ void DatagramProcessor::processDatagrams() {
|
||||||
// this will keep creatorTokenIDs to IDs mapped correctly
|
// this will keep creatorTokenIDs to IDs mapped correctly
|
||||||
EntityItemID::handleAddEntityResponse(incomingPacket);
|
EntityItemID::handleAddEntityResponse(incomingPacket);
|
||||||
application->getEntities()->getTree()->handleAddEntityResponse(incomingPacket);
|
application->getEntities()->getTree()->handleAddEntityResponse(incomingPacket);
|
||||||
application->_bandwidthRecorder.octreeChannel->input.updateValue(incomingPacket.size());
|
// application->_bandwidthRecorder.octreeChannel->input.updateValue(incomingPacket.size());
|
||||||
application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
|
// application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
|
||||||
break;
|
break;
|
||||||
case PacketTypeEntityData:
|
case PacketTypeEntityData:
|
||||||
case PacketTypeEntityErase:
|
case PacketTypeEntityErase:
|
||||||
|
@ -97,8 +96,8 @@ void DatagramProcessor::processDatagrams() {
|
||||||
// add this packet to our list of octree packets and process them on the octree data processing
|
// add this packet to our list of octree packets and process them on the octree data processing
|
||||||
application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket);
|
application->_octreeProcessor.queueReceivedPacket(matchedNode, incomingPacket);
|
||||||
}
|
}
|
||||||
application->_bandwidthRecorder.octreeChannel->input.updateValue(incomingPacket.size());
|
// application->_bandwidthRecorder.octreeChannel->input.updateValue(incomingPacket.size());
|
||||||
application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
|
// application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PacketTypeMetavoxelData:
|
case PacketTypeMetavoxelData:
|
||||||
|
@ -113,15 +112,15 @@ void DatagramProcessor::processDatagrams() {
|
||||||
|
|
||||||
if (avatarMixer) {
|
if (avatarMixer) {
|
||||||
avatarMixer->setLastHeardMicrostamp(usecTimestampNow());
|
avatarMixer->setLastHeardMicrostamp(usecTimestampNow());
|
||||||
avatarMixer->recordBytesReceived(incomingPacket.size());
|
// avatarMixer->recordBytesReceived(incomingPacket.size());
|
||||||
|
|
||||||
QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram",
|
QMetaObject::invokeMethod(&application->getAvatarManager(), "processAvatarMixerDatagram",
|
||||||
Q_ARG(const QByteArray&, incomingPacket),
|
Q_ARG(const QByteArray&, incomingPacket),
|
||||||
Q_ARG(const QWeakPointer<Node>&, avatarMixer));
|
Q_ARG(const QWeakPointer<Node>&, avatarMixer));
|
||||||
}
|
}
|
||||||
|
|
||||||
application->_bandwidthRecorder.avatarsChannel->input.updateValue(incomingPacket.size());
|
// application->_bandwidthRecorder.avatarsChannel->input.updateValue(incomingPacket.size());
|
||||||
application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
|
// application->_bandwidthRecorder.totalChannel->input.updateValue(incomingPacket.size());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PacketTypeDomainConnectionDenied: {
|
case PacketTypeDomainConnectionDenied: {
|
||||||
|
|
|
@ -899,8 +899,6 @@ int MetavoxelSystemClient::parseData(const QByteArray& packet) {
|
||||||
} else {
|
} else {
|
||||||
QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet));
|
QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet));
|
||||||
}
|
}
|
||||||
Application::getInstance()->getBandwidthRecorder()->metavoxelsChannel->input.updateValue(packet.size());
|
|
||||||
Application::getInstance()->getBandwidthRecorder()->totalChannel->input.updateValue(packet.size());
|
|
||||||
}
|
}
|
||||||
return packet.size();
|
return packet.size();
|
||||||
}
|
}
|
||||||
|
@ -1016,8 +1014,6 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) {
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<NodeList>()->writeDatagram(data, _node);
|
DependencyManager::get<NodeList>()->writeDatagram(data, _node);
|
||||||
}
|
}
|
||||||
Application::getInstance()->getBandwidthRecorder()->metavoxelsChannel->output.updateValue(data.size());
|
|
||||||
Application::getInstance()->getBandwidthRecorder()->totalChannel->output.updateValue(data.size());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,8 +47,8 @@ QLabel* BandwidthDialog::ChannelDisplay::setupLabel(QFormLayout* form) {
|
||||||
|
|
||||||
void BandwidthDialog::ChannelDisplay::setLabelText() {
|
void BandwidthDialog::ChannelDisplay::setLabelText() {
|
||||||
std::string strBuf =
|
std::string strBuf =
|
||||||
std::to_string ((int) (ch->input.getValue() * ch->unitScale)) + "/" +
|
std::to_string ((int) (ch->getAverageInputKilobitsPerSecond() * ch->unitScale)) + "/" +
|
||||||
std::to_string ((int) (ch->output.getValue() * ch->unitScale)) + " " + ch->unitCaption;
|
std::to_string ((int) (ch->getAverageOutputKilobitsPerSecond() * ch->unitScale)) + " " + ch->unitCaption;
|
||||||
label->setText(strBuf.c_str());
|
label->setText(strBuf.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@ BandwidthDialog::BandwidthDialog(QWidget* parent, BandwidthRecorder* model) :
|
||||||
avatarsChannelDisplay = new ChannelDisplay(_model->avatarsChannel, form);
|
avatarsChannelDisplay = new ChannelDisplay(_model->avatarsChannel, form);
|
||||||
octreeChannelDisplay = new ChannelDisplay(_model->octreeChannel, form);
|
octreeChannelDisplay = new ChannelDisplay(_model->octreeChannel, form);
|
||||||
metavoxelsChannelDisplay = new ChannelDisplay(_model->metavoxelsChannel, form);
|
metavoxelsChannelDisplay = new ChannelDisplay(_model->metavoxelsChannel, form);
|
||||||
|
otherChannelDisplay = new ChannelDisplay(_model->otherChannel, form);
|
||||||
totalChannelDisplay = new ChannelDisplay(_model->totalChannel, form);
|
totalChannelDisplay = new ChannelDisplay(_model->totalChannel, form);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ BandwidthDialog::~BandwidthDialog() {
|
||||||
delete avatarsChannelDisplay;
|
delete avatarsChannelDisplay;
|
||||||
delete octreeChannelDisplay;
|
delete octreeChannelDisplay;
|
||||||
delete metavoxelsChannelDisplay;
|
delete metavoxelsChannelDisplay;
|
||||||
|
delete otherChannelDisplay;
|
||||||
delete totalChannelDisplay;
|
delete totalChannelDisplay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +88,7 @@ void BandwidthDialog::paintEvent(QPaintEvent* event) {
|
||||||
avatarsChannelDisplay->setLabelText();
|
avatarsChannelDisplay->setLabelText();
|
||||||
octreeChannelDisplay->setLabelText();
|
octreeChannelDisplay->setLabelText();
|
||||||
metavoxelsChannelDisplay->setLabelText();
|
metavoxelsChannelDisplay->setLabelText();
|
||||||
|
otherChannelDisplay->setLabelText();
|
||||||
totalChannelDisplay->setLabelText();
|
totalChannelDisplay->setLabelText();
|
||||||
|
|
||||||
this->QDialog::paintEvent(event);
|
this->QDialog::paintEvent(event);
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
ChannelDisplay* avatarsChannelDisplay;
|
ChannelDisplay* avatarsChannelDisplay;
|
||||||
ChannelDisplay* octreeChannelDisplay;
|
ChannelDisplay* octreeChannelDisplay;
|
||||||
ChannelDisplay* metavoxelsChannelDisplay;
|
ChannelDisplay* metavoxelsChannelDisplay;
|
||||||
|
ChannelDisplay* otherChannelDisplay;
|
||||||
|
|
||||||
// sums of all the other channels
|
// sums of all the other channels
|
||||||
ChannelDisplay* totalChannelDisplay;
|
ChannelDisplay* totalChannelDisplay;
|
||||||
|
|
|
@ -216,6 +216,8 @@ void Stats::display(
|
||||||
QLocale locale(QLocale::English);
|
QLocale locale(QLocale::English);
|
||||||
std::stringstream octreeStats;
|
std::stringstream octreeStats;
|
||||||
|
|
||||||
|
BandwidthRecorder* bandwidthRecorder = Application::getInstance()->getBandwidthRecorder();
|
||||||
|
|
||||||
if (_lastHorizontalOffset != horizontalOffset) {
|
if (_lastHorizontalOffset != horizontalOffset) {
|
||||||
resetWidth(glCanvas->width(), horizontalOffset);
|
resetWidth(glCanvas->width(), horizontalOffset);
|
||||||
_lastHorizontalOffset = horizontalOffset;
|
_lastHorizontalOffset = horizontalOffset;
|
||||||
|
@ -440,8 +442,12 @@ void Stats::display(
|
||||||
SharedNodePointer avatarMixer = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::AvatarMixer);
|
SharedNodePointer avatarMixer = DependencyManager::get<NodeList>()->soloNodeOfType(NodeType::AvatarMixer);
|
||||||
if (avatarMixer) {
|
if (avatarMixer) {
|
||||||
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
sprintf(avatarMixerStats, "Avatar Mixer: %.f kbps, %.f pps",
|
||||||
roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
// roundf(avatarMixer->getAverageKilobitsPerSecond()),
|
||||||
roundf(avatarMixer->getAveragePacketsPerSecond()));
|
// roundf(avatarMixer->getAveragePacketsPerSecond())
|
||||||
|
roundf(bandwidthRecorder->audioChannel->getAverageInputKilobitsPerSecond() +
|
||||||
|
bandwidthRecorder->audioChannel->getAverageOutputKilobitsPerSecond()),
|
||||||
|
roundf(bandwidthRecorder->audioChannel->getAverageInputPacketsPerSecond() +
|
||||||
|
bandwidthRecorder->audioChannel->getAverageOutputPacketsPerSecond()));
|
||||||
} else {
|
} else {
|
||||||
sprintf(avatarMixerStats, "No Avatar Mixer");
|
sprintf(avatarMixerStats, "No Avatar Mixer");
|
||||||
}
|
}
|
||||||
|
|
123
libraries/networking/src/BandwidthRecorder.cpp
Normal file
123
libraries/networking/src/BandwidthRecorder.cpp
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
//
|
||||||
|
// BandwidthMeter.cpp
|
||||||
|
// interface/src/ui
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2015-1-30
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Based on code by Tobias Schwinger
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
// #include <GeometryCache.h>
|
||||||
|
#include "BandwidthRecorder.h"
|
||||||
|
|
||||||
|
|
||||||
|
BandwidthRecorder::Channel::Channel(char const* const caption,
|
||||||
|
char const* unitCaption,
|
||||||
|
double unitScale,
|
||||||
|
unsigned colorRGBA) :
|
||||||
|
caption(caption),
|
||||||
|
unitCaption(unitCaption),
|
||||||
|
unitScale(unitScale),
|
||||||
|
colorRGBA(colorRGBA)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
float BandwidthRecorder::Channel::getAverageInputPacketsPerSecond() {
|
||||||
|
return (1 / _input.getEventDeltaAverage());
|
||||||
|
}
|
||||||
|
|
||||||
|
float BandwidthRecorder::Channel::getAverageOutputPacketsPerSecond() {
|
||||||
|
return (1 / _output.getEventDeltaAverage());
|
||||||
|
}
|
||||||
|
|
||||||
|
float BandwidthRecorder::Channel::getAverageInputKilobitsPerSecond() {
|
||||||
|
return (_input.getAverageSampleValuePerSecond() * (8.0f / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
float BandwidthRecorder::Channel::getAverageOutputKilobitsPerSecond() {
|
||||||
|
return (_output.getAverageSampleValuePerSecond() * (8.0f / 1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BandwidthRecorder::Channel::updateInputAverage(const float sample) {
|
||||||
|
_input.updateAverage(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BandwidthRecorder::Channel::updateOutputAverage(const float sample) {
|
||||||
|
_output.updateAverage(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BandwidthRecorder::BandwidthRecorder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BandwidthRecorder::~BandwidthRecorder() {
|
||||||
|
delete audioChannel;
|
||||||
|
delete avatarsChannel;
|
||||||
|
delete octreeChannel;
|
||||||
|
delete metavoxelsChannel;
|
||||||
|
delete totalChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void BandwidthRecorder::updateInboundData(const quint8 channelType, const int sample) {
|
||||||
|
|
||||||
|
totalChannel->updateInputAverage(sample);
|
||||||
|
|
||||||
|
// see Node.h NodeType
|
||||||
|
switch (channelType) {
|
||||||
|
case NodeType::DomainServer:
|
||||||
|
case NodeType::EntityServer:
|
||||||
|
octreeChannel->updateInputAverage(sample);
|
||||||
|
break;
|
||||||
|
case NodeType::MetavoxelServer:
|
||||||
|
case NodeType::EnvironmentServer:
|
||||||
|
metavoxelsChannel->updateInputAverage(sample);
|
||||||
|
break;
|
||||||
|
case NodeType::AudioMixer:
|
||||||
|
audioChannel->updateInputAverage(sample);
|
||||||
|
break;
|
||||||
|
case NodeType::Agent:
|
||||||
|
case NodeType::AvatarMixer:
|
||||||
|
avatarsChannel->updateInputAverage(sample);
|
||||||
|
break;
|
||||||
|
case NodeType::Unassigned:
|
||||||
|
default:
|
||||||
|
otherChannel->updateInputAverage(sample);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BandwidthRecorder::updateOutboundData(const quint8 channelType, const int sample) {
|
||||||
|
|
||||||
|
totalChannel->updateOutputAverage(sample);
|
||||||
|
|
||||||
|
// see Node.h NodeType
|
||||||
|
switch (channelType) {
|
||||||
|
case NodeType::DomainServer:
|
||||||
|
case NodeType::EntityServer:
|
||||||
|
octreeChannel->updateOutputAverage(sample);
|
||||||
|
break;
|
||||||
|
case NodeType::MetavoxelServer:
|
||||||
|
case NodeType::EnvironmentServer:
|
||||||
|
metavoxelsChannel->updateOutputAverage(sample);
|
||||||
|
break;
|
||||||
|
case NodeType::AudioMixer:
|
||||||
|
audioChannel->updateOutputAverage(sample);
|
||||||
|
break;
|
||||||
|
case NodeType::Agent:
|
||||||
|
case NodeType::AvatarMixer:
|
||||||
|
avatarsChannel->updateOutputAverage(sample);
|
||||||
|
break;
|
||||||
|
case NodeType::Unassigned:
|
||||||
|
default:
|
||||||
|
otherChannel->updateOutputAverage(sample);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,42 +14,46 @@
|
||||||
#ifndef hifi_BandwidthRecorder_h
|
#ifndef hifi_BandwidthRecorder_h
|
||||||
#define hifi_BandwidthRecorder_h
|
#define hifi_BandwidthRecorder_h
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
#include "Node.h"
|
||||||
|
#include "SimpleMovingAverage.h"
|
||||||
|
|
||||||
const double DEFAULT_UNIT_SCALE = 8000.0 / 1024.0;
|
const double DEFAULT_UNIT_SCALE = 1.0;
|
||||||
|
|
||||||
const unsigned int COLOR0 = 0x33cc99ff;
|
const unsigned int COLOR0 = 0x33cc99ff;
|
||||||
const unsigned int COLOR1 = 0xffef40c0;
|
const unsigned int COLOR1 = 0xffef40c0;
|
||||||
const unsigned int COLOR2 = 0xd0d0d0a0;
|
const unsigned int COLOR2 = 0xd0d0d0a0;
|
||||||
|
|
||||||
|
|
||||||
class BandwidthRecorder {
|
class BandwidthRecorder : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BandwidthRecorder();
|
BandwidthRecorder();
|
||||||
~BandwidthRecorder();
|
~BandwidthRecorder();
|
||||||
|
|
||||||
// keep track of data rate in one direction
|
|
||||||
class Stream {
|
|
||||||
public:
|
|
||||||
Stream(float msToAverage = 3000.0f);
|
|
||||||
void updateValue(double amount);
|
|
||||||
double getValue() const { return _value; }
|
|
||||||
private:
|
|
||||||
double _value; // Current value.
|
|
||||||
double _msToAverage; // Milliseconds to average.
|
|
||||||
QElapsedTimer _prevTime; // Time of last feed.
|
|
||||||
};
|
|
||||||
|
|
||||||
// keep track of data rate in two directions as well as units and style to use during display
|
// keep track of data rate in two directions as well as units and style to use during display
|
||||||
class Channel {
|
class Channel {
|
||||||
public:
|
public:
|
||||||
Channel(char const* const caption, char const* unitCaption, double unitScale, unsigned colorRGBA);
|
Channel(char const* const caption, char const* unitCaption, double unitScale, unsigned colorRGBA);
|
||||||
Stream input;
|
float getAverageInputPacketsPerSecond();
|
||||||
Stream output;
|
float getAverageOutputPacketsPerSecond();
|
||||||
|
float getAverageInputKilobitsPerSecond();
|
||||||
|
float getAverageOutputKilobitsPerSecond();
|
||||||
|
|
||||||
|
void updateInputAverage(const float sample);
|
||||||
|
void updateOutputAverage(const float sample);
|
||||||
|
|
||||||
|
// XXX make these private
|
||||||
char const* const caption;
|
char const* const caption;
|
||||||
char const* unitCaption;
|
char const* unitCaption;
|
||||||
double unitScale;
|
double unitScale;
|
||||||
unsigned colorRGBA;
|
unsigned colorRGBA;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SimpleMovingAverage _input;
|
||||||
|
SimpleMovingAverage _output;
|
||||||
};
|
};
|
||||||
|
|
||||||
// create the channels we keep track of
|
// create the channels we keep track of
|
||||||
|
@ -57,7 +61,12 @@ class BandwidthRecorder {
|
||||||
Channel* avatarsChannel = new Channel("Avatars", "Kbps", DEFAULT_UNIT_SCALE, COLOR1);
|
Channel* avatarsChannel = new Channel("Avatars", "Kbps", DEFAULT_UNIT_SCALE, COLOR1);
|
||||||
Channel* octreeChannel = new Channel("Octree", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
|
Channel* octreeChannel = new Channel("Octree", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
|
||||||
Channel* metavoxelsChannel = new Channel("Metavoxels", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
|
Channel* metavoxelsChannel = new Channel("Metavoxels", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
|
||||||
|
Channel* otherChannel = new Channel("Other", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
|
||||||
Channel* totalChannel = new Channel("Total", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
|
Channel* totalChannel = new Channel("Total", "Kbps", DEFAULT_UNIT_SCALE, COLOR2);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void updateInboundData(const quint8 channelType, const int bytes);
|
||||||
|
void updateOutboundData(const quint8 channelType, const int bytes);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -208,6 +208,22 @@ bool LimitedNodeList::packetVersionAndHashMatch(const QByteArray& packet) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// qint64 LimitedNodeList::readDatagram(char* data, qint64 maxSize, QHostAddress* address = 0, quint16 * port = 0) {
|
||||||
|
|
||||||
|
qint64 LimitedNodeList::readDatagram(QByteArray& incomingPacket, QHostAddress* address = 0, quint16 * port = 0) {
|
||||||
|
qint64 result = getNodeSocket().readDatagram(incomingPacket.data(), incomingPacket.size(), address, port);
|
||||||
|
|
||||||
|
SharedNodePointer sendingNode = sendingNodeForPacket(incomingPacket);
|
||||||
|
if (sendingNode) {
|
||||||
|
emit dataReceived(sendingNode->getType(), incomingPacket.size());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
emit dataReceived(NodeType::Unassigned, incomingPacket.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr,
|
qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSockAddr& destinationSockAddr,
|
||||||
const QUuid& connectionSecret) {
|
const QUuid& connectionSecret) {
|
||||||
QByteArray datagramCopy = datagram;
|
QByteArray datagramCopy = datagram;
|
||||||
|
@ -231,10 +247,11 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const HifiSock
|
||||||
return bytesWritten;
|
return bytesWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
|
qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram,
|
||||||
const HifiSockAddr& overridenSockAddr) {
|
const SharedNodePointer& destinationNode,
|
||||||
|
const HifiSockAddr& overridenSockAddr) {
|
||||||
if (destinationNode) {
|
if (destinationNode) {
|
||||||
// if we don't have an ovveriden address, assume they want to send to the node's active socket
|
// if we don't have an overridden address, assume they want to send to the node's active socket
|
||||||
const HifiSockAddr* destinationSockAddr = &overridenSockAddr;
|
const HifiSockAddr* destinationSockAddr = &overridenSockAddr;
|
||||||
if (overridenSockAddr.isNull()) {
|
if (overridenSockAddr.isNull()) {
|
||||||
if (destinationNode->getActiveSocket()) {
|
if (destinationNode->getActiveSocket()) {
|
||||||
|
@ -245,6 +262,8 @@ qint64 LimitedNodeList::writeDatagram(const QByteArray& datagram, const SharedNo
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit dataSent(destinationNode->getType(), datagram.size());
|
||||||
|
|
||||||
return writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret());
|
return writeDatagram(datagram, *destinationSockAddr, destinationNode->getConnectionSecret());
|
||||||
}
|
}
|
||||||
|
@ -303,7 +322,7 @@ int LimitedNodeList::updateNodeWithDataFromPacket(const SharedNodePointer& match
|
||||||
QMutexLocker locker(&matchingNode->getMutex());
|
QMutexLocker locker(&matchingNode->getMutex());
|
||||||
|
|
||||||
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
|
matchingNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||||
matchingNode->recordBytesReceived(packet.size());
|
// matchingNode->recordBytesReceived(packet.size());
|
||||||
|
|
||||||
if (!matchingNode->getLinkedData() && linkedDataCreateCallback) {
|
if (!matchingNode->getLinkedData() && linkedDataCreateCallback) {
|
||||||
linkedDataCreateCallback(matchingNode.data());
|
linkedDataCreateCallback(matchingNode.data());
|
||||||
|
|
|
@ -82,6 +82,8 @@ public:
|
||||||
QUdpSocket& getDTLSSocket();
|
QUdpSocket& getDTLSSocket();
|
||||||
|
|
||||||
bool packetVersionAndHashMatch(const QByteArray& packet);
|
bool packetVersionAndHashMatch(const QByteArray& packet);
|
||||||
|
|
||||||
|
qint64 readDatagram(QByteArray& incomingPacket, QHostAddress* address, quint16 * port);
|
||||||
|
|
||||||
qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
|
qint64 writeDatagram(const QByteArray& datagram, const SharedNodePointer& destinationNode,
|
||||||
const HifiSockAddr& overridenSockAddr = HifiSockAddr());
|
const HifiSockAddr& overridenSockAddr = HifiSockAddr());
|
||||||
|
@ -180,6 +182,9 @@ signals:
|
||||||
|
|
||||||
void localSockAddrChanged(const HifiSockAddr& localSockAddr);
|
void localSockAddrChanged(const HifiSockAddr& localSockAddr);
|
||||||
void publicSockAddrChanged(const HifiSockAddr& publicSockAddr);
|
void publicSockAddrChanged(const HifiSockAddr& publicSockAddr);
|
||||||
|
|
||||||
|
void dataSent(const quint8 channel_type, const int bytes);
|
||||||
|
void dataReceived(const quint8 channel_type, const int bytes);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0);
|
LimitedNodeList(unsigned short socketListenPort = 0, unsigned short dtlsListenPort = 0);
|
||||||
|
|
|
@ -47,7 +47,7 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
|
||||||
_activeSocket(NULL),
|
_activeSocket(NULL),
|
||||||
_symmetricSocket(),
|
_symmetricSocket(),
|
||||||
_connectionSecret(),
|
_connectionSecret(),
|
||||||
_bytesReceivedMovingAverage(NULL),
|
// _bytesReceivedMovingAverage(NULL),
|
||||||
_linkedData(NULL),
|
_linkedData(NULL),
|
||||||
_isAlive(true),
|
_isAlive(true),
|
||||||
_pingMs(-1), // "Uninitialized"
|
_pingMs(-1), // "Uninitialized"
|
||||||
|
@ -60,32 +60,32 @@ Node::Node(const QUuid& uuid, NodeType_t type, const HifiSockAddr& publicSocket,
|
||||||
|
|
||||||
Node::~Node() {
|
Node::~Node() {
|
||||||
delete _linkedData;
|
delete _linkedData;
|
||||||
delete _bytesReceivedMovingAverage;
|
// delete _bytesReceivedMovingAverage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node::recordBytesReceived(int bytesReceived) {
|
// void Node::recordBytesReceived(int bytesReceived) {
|
||||||
if (!_bytesReceivedMovingAverage) {
|
// if (!_bytesReceivedMovingAverage) {
|
||||||
_bytesReceivedMovingAverage = new SimpleMovingAverage(100);
|
// _bytesReceivedMovingAverage = new SimpleMovingAverage(100);
|
||||||
}
|
// }
|
||||||
|
|
||||||
_bytesReceivedMovingAverage->updateAverage((float) bytesReceived);
|
// _bytesReceivedMovingAverage->updateAverage((float) bytesReceived);
|
||||||
}
|
// }
|
||||||
|
|
||||||
float Node::getAveragePacketsPerSecond() {
|
// float Node::getAveragePacketsPerSecond() {
|
||||||
if (_bytesReceivedMovingAverage) {
|
// if (_bytesReceivedMovingAverage) {
|
||||||
return (1 / _bytesReceivedMovingAverage->getEventDeltaAverage());
|
// return (1 / _bytesReceivedMovingAverage->getEventDeltaAverage());
|
||||||
} else {
|
// } else {
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
float Node::getAverageKilobitsPerSecond() {
|
// float Node::getAverageKilobitsPerSecond() {
|
||||||
if (_bytesReceivedMovingAverage) {
|
// if (_bytesReceivedMovingAverage) {
|
||||||
return (_bytesReceivedMovingAverage->getAverageSampleValuePerSecond() * (8.0f / 1000));
|
// return (_bytesReceivedMovingAverage->getAverageSampleValuePerSecond() * (8.0f / 1000));
|
||||||
} else {
|
// } else {
|
||||||
return 0;
|
// return 0;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void Node::updateClockSkewUsec(int clockSkewSample) {
|
void Node::updateClockSkewUsec(int clockSkewSample) {
|
||||||
_clockSkewMovingPercentile.updatePercentile((float)clockSkewSample);
|
_clockSkewMovingPercentile.updatePercentile((float)clockSkewSample);
|
||||||
|
|
|
@ -63,9 +63,9 @@ public:
|
||||||
bool isAlive() const { return _isAlive; }
|
bool isAlive() const { return _isAlive; }
|
||||||
void setAlive(bool isAlive) { _isAlive = isAlive; }
|
void setAlive(bool isAlive) { _isAlive = isAlive; }
|
||||||
|
|
||||||
void recordBytesReceived(int bytesReceived);
|
// void recordBytesReceived(int bytesReceived);
|
||||||
float getAverageKilobitsPerSecond();
|
// float getAverageKilobitsPerSecond();
|
||||||
float getAveragePacketsPerSecond();
|
// float getAveragePacketsPerSecond();
|
||||||
|
|
||||||
int getPingMs() const { return _pingMs; }
|
int getPingMs() const { return _pingMs; }
|
||||||
void setPingMs(int pingMs) { _pingMs = pingMs; }
|
void setPingMs(int pingMs) { _pingMs = pingMs; }
|
||||||
|
@ -99,7 +99,7 @@ private:
|
||||||
HifiSockAddr _symmetricSocket;
|
HifiSockAddr _symmetricSocket;
|
||||||
|
|
||||||
QUuid _connectionSecret;
|
QUuid _connectionSecret;
|
||||||
SimpleMovingAverage* _bytesReceivedMovingAverage;
|
// SimpleMovingAverage* _bytesReceivedMovingAverage;
|
||||||
NodeData* _linkedData;
|
NodeData* _linkedData;
|
||||||
bool _isAlive;
|
bool _isAlive;
|
||||||
int _pingMs;
|
int _pingMs;
|
||||||
|
|
|
@ -108,6 +108,9 @@ void NodeList::timePingReply(const QByteArray& packet, const SharedNodePointer&
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
|
void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteArray& packet) {
|
||||||
|
|
||||||
|
emit dataReceived(NodeType::AudioMixer, packet.size()); // XXX
|
||||||
|
|
||||||
switch (packetTypeForPacket(packet)) {
|
switch (packetTypeForPacket(packet)) {
|
||||||
case PacketTypeDomainList: {
|
case PacketTypeDomainList: {
|
||||||
processDomainServerList(packet);
|
processDomainServerList(packet);
|
||||||
|
@ -157,6 +160,7 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PacketTypeUnverifiedPing: {
|
case PacketTypeUnverifiedPing: {
|
||||||
|
|
||||||
// send back a reply
|
// send back a reply
|
||||||
QByteArray replyPacket = constructPingReplyPacket(packet, _domainHandler.getICEClientID());
|
QByteArray replyPacket = constructPingReplyPacket(packet, _domainHandler.getICEClientID());
|
||||||
writeUnverifiedDatagram(replyPacket, senderSockAddr);
|
writeUnverifiedDatagram(replyPacket, senderSockAddr);
|
||||||
|
|
|
@ -8,7 +8,7 @@ do
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
find . -name *.cpp -print | while read I
|
find . -name *.cpp -print | grep -v 'moc_' | while read I
|
||||||
do
|
do
|
||||||
etags --append "$I"
|
etags --append "$I"
|
||||||
done
|
done
|
||||||
|
|
Loading…
Reference in a new issue