mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 23:56:29 +02:00
complete initial algorithm for AM throttle
This commit is contained in:
parent
7a2a391852
commit
532bcc9376
3 changed files with 32 additions and 39 deletions
|
@ -166,7 +166,7 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
distribution.reset();
|
distribution.reset();
|
||||||
|
|
||||||
// reset the max distance for this frame
|
// reset the max distance for this frame
|
||||||
float maxDistanceThisFrame = 0.0f;
|
float maxAvatarDistanceThisFrame = 0.0f;
|
||||||
|
|
||||||
// reset the number of sent avatars
|
// reset the number of sent avatars
|
||||||
nodeData->resetNumAvatarsSentLastFrame();
|
nodeData->resetNumAvatarsSentLastFrame();
|
||||||
|
@ -186,6 +186,12 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
if (nodeData->getNumFramesSinceFRDAdjustment() > AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND) {
|
if (nodeData->getNumFramesSinceFRDAdjustment() > AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND) {
|
||||||
|
|
||||||
const float FRD_ADJUSTMENT_ACCEPTABLE_RATIO = 0.8f;
|
const float FRD_ADJUSTMENT_ACCEPTABLE_RATIO = 0.8f;
|
||||||
|
const float HYSTERISIS_GAP = (1 - FRD_ADJUSTMENT_ACCEPTABLE_RATIO);
|
||||||
|
const float HYSTERISIS_MIDDLE_PERCENTAGE = (1 - (HYSTERISIS_GAP * 0.5f));
|
||||||
|
const float FRD_RECOVERY_EPSILON = 0.0001;
|
||||||
|
|
||||||
|
// get the current full rate distance so we can work with it
|
||||||
|
float currentFullRateDistance = nodeData->getFullRateDistance();
|
||||||
|
|
||||||
// qDebug() << "current node outbound bandwidth is" << avatarDataRateLastSecond;
|
// qDebug() << "current node outbound bandwidth is" << avatarDataRateLastSecond;
|
||||||
|
|
||||||
|
@ -194,40 +200,30 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
qDebug() << "Adjustment down required for avatar" << node->getUUID() << "whose current send rate is"
|
qDebug() << "Adjustment down required for avatar" << node->getUUID() << "whose current send rate is"
|
||||||
<< avatarDataRateLastSecond;
|
<< avatarDataRateLastSecond;
|
||||||
|
|
||||||
// is the FRD greater than the MAX FRD? if so, before we calculate anything, set it to the MAX FRD
|
// is the FRD greater than the farthest avatar?
|
||||||
float newFullRateDistance = nodeData->getFullRateDistance();
|
// if so, before we calculate anything, set it to that distance
|
||||||
|
currentFullRateDistance = std::min(currentFullRateDistance, nodeData->getMaxAvatarDistance());
|
||||||
|
|
||||||
if (newFullRateDistance > nodeData->getMaxFullRateDistance()) {
|
// we're adjusting the full rate distance to target a bandwidth in the middle
|
||||||
newFullRateDistance = nodeData->getMaxFullRateDistance();
|
// of the hysterisis gap
|
||||||
}
|
|
||||||
|
|
||||||
// we're adjusting, so we want to drop half the distance to FRD=0
|
currentFullRateDistance *= (_maxKbpsPerNode * HYSTERISIS_MIDDLE_PERCENTAGE) / avatarDataRateLastSecond;
|
||||||
newFullRateDistance /= 2.0f;
|
|
||||||
|
|
||||||
qDebug() << "max FRD is" << nodeData->getMaxFullRateDistance();
|
qDebug() << "farthest possible FRD is" << nodeData->getMaxAvatarDistance();
|
||||||
qDebug() << "current FRD is" << nodeData->getFullRateDistance();
|
qDebug() << "current FRD is" << nodeData->getFullRateDistance();
|
||||||
nodeData->setFullRateDistance(newFullRateDistance);
|
nodeData->setFullRateDistance(currentFullRateDistance);
|
||||||
|
|
||||||
qDebug() << "new FRD is" << nodeData->getFullRateDistance();
|
qDebug() << "new FRD is" << nodeData->getFullRateDistance();
|
||||||
|
|
||||||
nodeData->resetNumFramesSinceFRDAdjustment();
|
nodeData->resetNumFramesSinceFRDAdjustment();
|
||||||
} else if (nodeData->getFullRateDistance() < nodeData->getMaxFullRateDistance()
|
} else if (currentFullRateDistance < nodeData->getMaxAvatarDistance()
|
||||||
&& avatarDataRateLastSecond < _maxKbpsPerNode * FRD_ADJUSTMENT_ACCEPTABLE_RATIO) {
|
&& avatarDataRateLastSecond < _maxKbpsPerNode * FRD_ADJUSTMENT_ACCEPTABLE_RATIO) {
|
||||||
// we are constrained AND we've recovered to below the acceptable ratio, adjust the FRD upwards
|
// we are constrained AND we've recovered to below the acceptable ratio
|
||||||
// by covering half the distance to the max FRD
|
|
||||||
|
|
||||||
qDebug() << "Adjustment up required for avatar" << node->getUUID() << "whose current send rate is"
|
// lets adjust the full rate distance to target a bandwidth in the middle of the hyterisis gap
|
||||||
<< node->getOutboundBandwidth();
|
currentFullRateDistance *= (_maxKbpsPerNode * HYSTERISIS_MIDDLE_PERCENTAGE) / avatarDataRateLastSecond;
|
||||||
|
|
||||||
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->setFullRateDistance(currentFullRateDistance);
|
||||||
nodeData->resetNumFramesSinceFRDAdjustment();
|
nodeData->resetNumFramesSinceFRDAdjustment();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -265,7 +261,7 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
float distanceToAvatar = glm::length(myPosition - otherPosition);
|
float distanceToAvatar = glm::length(myPosition - otherPosition);
|
||||||
|
|
||||||
// potentially update the max full rate distance for this frame
|
// potentially update the max full rate distance for this frame
|
||||||
maxDistanceThisFrame = std::max(maxDistanceThisFrame, distanceToAvatar);
|
maxAvatarDistanceThisFrame = std::max(maxAvatarDistanceThisFrame, distanceToAvatar);
|
||||||
|
|
||||||
if (distanceToAvatar != 0.0f
|
if (distanceToAvatar != 0.0f
|
||||||
&& distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) {
|
&& distribution(generator) > (nodeData->getFullRateDistance() / distanceToAvatar)) {
|
||||||
|
@ -305,7 +301,6 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
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;
|
||||||
|
@ -322,8 +317,6 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
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;
|
||||||
|
@ -338,9 +331,9 @@ void AvatarMixer::broadcastAvatarData() {
|
||||||
|
|
||||||
if (numOtherAvatars == 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->setMaxAvatarDistance(FLT_MAX);
|
||||||
} else {
|
} else {
|
||||||
nodeData->setMaxFullRateDistance(maxDistanceThisFrame);
|
nodeData->setMaxAvatarDistance(maxAvatarDistanceThisFrame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -28,7 +28,7 @@ bool AvatarMixerClientData::checkAndSetHasReceivedFirstPackets() {
|
||||||
void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const {
|
void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const {
|
||||||
jsonObject["display_name"] = _avatar.getDisplayName();
|
jsonObject["display_name"] = _avatar.getDisplayName();
|
||||||
jsonObject["full_rate_distance"] = _fullRateDistance;
|
jsonObject["full_rate_distance"] = _fullRateDistance;
|
||||||
jsonObject["max_full_rate_distance"] = _maxFullRateDistance;
|
jsonObject["max_avatar_distance"] = _maxAvatarDistance;
|
||||||
jsonObject["num_avatars_sent_last_frame"] = _numAvatarsSentLastFrame;
|
jsonObject["num_avatars_sent_last_frame"] = _numAvatarsSentLastFrame;
|
||||||
|
|
||||||
jsonObject[OUTBOUND_AVATAR_DATA_STATS_KEY] = getOutboundAvatarDataKbps();
|
jsonObject[OUTBOUND_AVATAR_DATA_STATS_KEY] = getOutboundAvatarDataKbps();
|
||||||
|
|
|
@ -39,11 +39,11 @@ public:
|
||||||
quint64 getIdentityChangeTimestamp() const { return _identityChangeTimestamp; }
|
quint64 getIdentityChangeTimestamp() const { return _identityChangeTimestamp; }
|
||||||
void setIdentityChangeTimestamp(quint64 identityChangeTimestamp) { _identityChangeTimestamp = identityChangeTimestamp; }
|
void setIdentityChangeTimestamp(quint64 identityChangeTimestamp) { _identityChangeTimestamp = identityChangeTimestamp; }
|
||||||
|
|
||||||
float getFullRateDistance() const { return _fullRateDistance; }
|
|
||||||
void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; }
|
void setFullRateDistance(float fullRateDistance) { _fullRateDistance = fullRateDistance; }
|
||||||
|
float getFullRateDistance() const { return _fullRateDistance; }
|
||||||
|
|
||||||
void setMaxFullRateDistance(float maxFullRateDistance) { _maxFullRateDistance = maxFullRateDistance; }
|
void setMaxAvatarDistance(float maxAvatarDistance) { _maxAvatarDistance = maxAvatarDistance; }
|
||||||
float getMaxFullRateDistance() const { return _maxFullRateDistance; }
|
float getMaxAvatarDistance() const { return _maxAvatarDistance; }
|
||||||
|
|
||||||
void resetNumAvatarsSentLastFrame() { _numAvatarsSentLastFrame = 0; }
|
void resetNumAvatarsSentLastFrame() { _numAvatarsSentLastFrame = 0; }
|
||||||
void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; }
|
void incrementNumAvatarsSentLastFrame() { ++_numAvatarsSentLastFrame; }
|
||||||
|
@ -65,7 +65,7 @@ private:
|
||||||
quint64 _billboardChangeTimestamp = 0;
|
quint64 _billboardChangeTimestamp = 0;
|
||||||
quint64 _identityChangeTimestamp = 0;
|
quint64 _identityChangeTimestamp = 0;
|
||||||
float _fullRateDistance = FLT_MAX;
|
float _fullRateDistance = FLT_MAX;
|
||||||
float _maxFullRateDistance = FLT_MAX;
|
float _maxAvatarDistance = FLT_MAX;
|
||||||
int _numAvatarsSentLastFrame = 0;
|
int _numAvatarsSentLastFrame = 0;
|
||||||
int _numFramesSinceAdjustment = 0;
|
int _numFramesSinceAdjustment = 0;
|
||||||
SimpleMovingAverage _avgOtherAvatarDataRate;
|
SimpleMovingAverage _avgOtherAvatarDataRate;
|
||||||
|
|
Loading…
Reference in a new issue