mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 12:54:30 +02:00
initial pass at tailoring the FRD for send rate
This commit is contained in:
parent
5b55a52a04
commit
744d026e81
3 changed files with 78 additions and 15 deletions
|
@ -164,20 +164,70 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
|
|
||||||
// reset the internal state for correct random number distribution
|
// reset the internal state for correct random number distribution
|
||||||
distribution.reset();
|
distribution.reset();
|
||||||
|
|
||||||
// reset the max distance for this frame
|
// reset the max distance for this frame
|
||||||
float maxDistanceThisFrame = 0.0f;
|
float maxDistanceThisFrame = 0.0f;
|
||||||
|
|
||||||
// reset the number of sent avatars
|
// reset the number of sent avatars
|
||||||
nodeData->resetNumAvatarsSentLastFrame();
|
nodeData->resetNumAvatarsSentLastFrame();
|
||||||
|
|
||||||
|
// keep a counter of the number of considered avatars
|
||||||
|
int numOtherAvatars = 0;
|
||||||
|
|
||||||
|
float dataRateLastSecond = node->getOutboundBandwidth();
|
||||||
|
|
||||||
// Check if it is time to adjust what we send this client based on the observed
|
// Check if it is time to adjust what we send this client based on the observed
|
||||||
// bandwidth to this node. We do this once a second, which is also the window for
|
// bandwidth to this node. We do this once a second, which is also the window for
|
||||||
// the bandwidth reported by node->getOutboundBandwidth();
|
// the bandwidth reported by node->getOutboundBandwidth();
|
||||||
if (nodeData->getNumFramesSinceAdjustment() > AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND) {
|
if (nodeData->getNumFramesSinceFRDAdjustment() > AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND) {
|
||||||
qDebug() << "Consider adjustment for avatar whose current send rate is" << node->getOutboundBandwidth();
|
|
||||||
|
const float FRD_ADJUSTMENT_ACCEPTABLE_RATIO = 0.8f;
|
||||||
nodeData->resetNumFramesSinceAdjustment();
|
|
||||||
|
qDebug() << "current node outbound bandwidth is" << dataRateLastSecond;
|
||||||
|
|
||||||
|
if(dataRateLastSecond > _maxKbpsPerNode) {
|
||||||
|
|
||||||
|
qDebug() << "Adjustment down required for avatar" << node->getUUID() << "whose current send rate is"
|
||||||
|
<< dataRateLastSecond;
|
||||||
|
|
||||||
|
// is the FRD greater than the MAX FRD? if so, before we calculate anything, set it to the MAX FRD
|
||||||
|
float newFullRateDistance = nodeData->getFullRateDistance();
|
||||||
|
|
||||||
|
if (newFullRateDistance > nodeData->getMaxFullRateDistance()) {
|
||||||
|
newFullRateDistance = nodeData->getMaxFullRateDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we're adjusting, so we want to drop half the distance to FRD=0
|
||||||
|
newFullRateDistance /= 2.0f;
|
||||||
|
|
||||||
|
qDebug() << "max FRD is" << nodeData->getMaxFullRateDistance();
|
||||||
|
qDebug() << "current FRD is" << nodeData->getFullRateDistance();
|
||||||
|
nodeData->setFullRateDistance(newFullRateDistance);
|
||||||
|
|
||||||
|
qDebug() << "new FRD is" << nodeData->getFullRateDistance();
|
||||||
|
|
||||||
|
nodeData->resetNumFramesSinceFRDAdjustment();
|
||||||
|
} else if (nodeData->getFullRateDistance() < nodeData->getMaxFullRateDistance()
|
||||||
|
&& dataRateLastSecond < _maxKbpsPerNode * FRD_ADJUSTMENT_ACCEPTABLE_RATIO) {
|
||||||
|
// we are constrained AND we've recovered to below the acceptable ratio, adjust the FRD upwards
|
||||||
|
// by covering half the distance to the max FRD
|
||||||
|
|
||||||
|
qDebug() << "Adjustment up required for avatar" << node->getUUID() << "whose current send rate is"
|
||||||
|
<< node->getOutboundBandwidth();
|
||||||
|
|
||||||
|
float newFullRateDistance = nodeData->getFullRateDistance();
|
||||||
|
newFullRateDistance += (nodeData->getMaxFullRateDistance() - newFullRateDistance) / 2.0f;
|
||||||
|
|
||||||
|
qDebug() << "max FRD is" << nodeData->getMaxFullRateDistance();
|
||||||
|
qDebug() << "current FRD is" << nodeData->getFullRateDistance();
|
||||||
|
nodeData->setFullRateDistance(newFullRateDistance);
|
||||||
|
|
||||||
|
qDebug() << "new FRD is" << nodeData->getFullRateDistance();
|
||||||
|
|
||||||
|
nodeData->resetNumFramesSinceFRDAdjustment();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
nodeData->increaseNumFramesSinceAdjustment();
|
nodeData->incrementNumFramesSinceFRDAdjustment();
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is an AGENT we have received head data from
|
// this is an AGENT we have received head data from
|
||||||
|
@ -194,6 +244,8 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
[&](const SharedNodePointer& otherNode) {
|
[&](const SharedNodePointer& otherNode) {
|
||||||
|
++numOtherAvatars;
|
||||||
|
|
||||||
AvatarMixerClientData* otherNodeData = reinterpret_cast<AvatarMixerClientData*>(otherNode->getLinkedData());
|
AvatarMixerClientData* otherNodeData = reinterpret_cast<AvatarMixerClientData*>(otherNode->getLinkedData());
|
||||||
MutexTryLocker lock(otherNodeData->getMutex());
|
MutexTryLocker lock(otherNodeData->getMutex());
|
||||||
if (!lock.isLocked()) {
|
if (!lock.isLocked()) {
|
||||||
|
@ -215,6 +267,8 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
&& distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) {
|
&& distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nodeData->incrementNumAvatarsSentLastFrame();
|
||||||
|
|
||||||
QByteArray avatarByteArray;
|
QByteArray avatarByteArray;
|
||||||
avatarByteArray.append(otherNode->getUUID().toRfc4122());
|
avatarByteArray.append(otherNode->getUUID().toRfc4122());
|
||||||
|
@ -244,6 +298,8 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
|
QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
|
||||||
billboardPacket.append(otherNode->getUUID().toRfc4122());
|
billboardPacket.append(otherNode->getUUID().toRfc4122());
|
||||||
billboardPacket.append(otherNodeData->getAvatar().getBillboard());
|
billboardPacket.append(otherNodeData->getAvatar().getBillboard());
|
||||||
|
|
||||||
|
qDebug() << "Sending a billboard packet to" << node->getUUID();
|
||||||
nodeList->writeDatagram(billboardPacket, node);
|
nodeList->writeDatagram(billboardPacket, node);
|
||||||
|
|
||||||
++_sumBillboardPackets;
|
++_sumBillboardPackets;
|
||||||
|
@ -259,7 +315,9 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
QByteArray individualData = otherNodeData->getAvatar().identityByteArray();
|
QByteArray individualData = otherNodeData->getAvatar().identityByteArray();
|
||||||
individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122());
|
individualData.replace(0, NUM_BYTES_RFC4122_UUID, otherNode->getUUID().toRfc4122());
|
||||||
identityPacket.append(individualData);
|
identityPacket.append(individualData);
|
||||||
|
|
||||||
|
qDebug() << "Sending an identity packet to" << node->getUUID();
|
||||||
|
|
||||||
nodeList->writeDatagram(identityPacket, node);
|
nodeList->writeDatagram(identityPacket, node);
|
||||||
|
|
||||||
++_sumIdentityPackets;
|
++_sumIdentityPackets;
|
||||||
|
@ -267,7 +325,7 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
});
|
});
|
||||||
nodeList->writeDatagram(mixedAvatarByteArray, node);
|
nodeList->writeDatagram(mixedAvatarByteArray, node);
|
||||||
|
|
||||||
if (nodeData->getNumAvatarsSentLastFrame() == 0) {
|
if (numOtherAvatars == 0) {
|
||||||
// update the full rate distance to FLOAT_MAX since we didn't have any other avatars to send
|
// update the full rate distance to FLOAT_MAX since we didn't have any other avatars to send
|
||||||
nodeData->setMaxFullRateDistance(FLT_MAX);
|
nodeData->setMaxFullRateDistance(FLT_MAX);
|
||||||
} else {
|
} else {
|
||||||
|
@ -438,7 +496,9 @@ void AvatarMixer::parseDomainServerSettings(const QJsonObject& domainSettings) {
|
||||||
if (!nodeBandwidthValue.isDouble()) {
|
if (!nodeBandwidthValue.isDouble()) {
|
||||||
qDebug() << NODE_SEND_BANDWIDTH_KEY << "is not a double - will continue with default value";
|
qDebug() << NODE_SEND_BANDWIDTH_KEY << "is not a double - will continue with default value";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int KILO_PER_MEGA = 1000;
|
||||||
|
|
||||||
_maxMbpsPerNode = nodeBandwidthValue.toDouble(DEFAULT_NODE_SEND_BANDWIDTH);
|
_maxKbpsPerNode = nodeBandwidthValue.toDouble(DEFAULT_NODE_SEND_BANDWIDTH) * KILO_PER_MEGA;
|
||||||
qDebug() << "The maximum send bandwidth per node is" << _maxMbpsPerNode << "Mbps.";
|
qDebug() << "The maximum send bandwidth per node is" << _maxKbpsPerNode << "kbps.";
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ private:
|
||||||
int _sumBillboardPackets;
|
int _sumBillboardPackets;
|
||||||
int _sumIdentityPackets;
|
int _sumIdentityPackets;
|
||||||
|
|
||||||
float _maxMbpsPerNode = 0.0f;
|
float _maxKbpsPerNode = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AvatarMixer_h
|
#endif // hifi_AvatarMixer_h
|
||||||
|
|
|
@ -36,15 +36,18 @@ public:
|
||||||
void setIdentityChangeTimestamp(quint64 identityChangeTimestamp) { _identityChangeTimestamp = identityChangeTimestamp; }
|
void setIdentityChangeTimestamp(quint64 identityChangeTimestamp) { _identityChangeTimestamp = identityChangeTimestamp; }
|
||||||
|
|
||||||
float getFullRateDistance() const { return _fullRateDistance; }
|
float getFullRateDistance() const { return _fullRateDistance; }
|
||||||
void setMaxFullRateDistance(float distance) { _maxFullRateDistance = distance; }
|
void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; }
|
||||||
|
|
||||||
|
void setMaxFullRateDistance(float maxFullRateDistance) { _maxFullRateDistance = maxFullRateDistance; }
|
||||||
|
float getMaxFullRateDistance() const { return _maxFullRateDistance; }
|
||||||
|
|
||||||
void resetNumAvatarsSentLastFrame() { _numAvatarsSentLastFrame = 0; }
|
void resetNumAvatarsSentLastFrame() { _numAvatarsSentLastFrame = 0; }
|
||||||
void increaseNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; }
|
void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; }
|
||||||
int getNumAvatarsSentLastFrame() const { return _numAvatarsSentLastFrame; }
|
int getNumAvatarsSentLastFrame() const { return _numAvatarsSentLastFrame; }
|
||||||
|
|
||||||
int getNumFramesSinceAdjustment() const { return _numFramesSinceAdjustment; }
|
int getNumFramesSinceFRDAdjustment() const { return _numFramesSinceAdjustment; }
|
||||||
void increaseNumFramesSinceAdjustment() { ++_numFramesSinceAdjustment; }
|
void incrementNumFramesSinceFRDAdjustment() { ++_numFramesSinceAdjustment; }
|
||||||
void resetNumFramesSinceAdjustment() { _numFramesSinceAdjustment = 0; }
|
void resetNumFramesSinceFRDAdjustment() { _numFramesSinceAdjustment = 0; }
|
||||||
|
|
||||||
void loadJSONStats(QJsonObject& jsonObject) const;
|
void loadJSONStats(QJsonObject& jsonObject) const;
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in a new issue