From 3640d0204f77dff3b1c4bd50229b60a49d2745e5 Mon Sep 17 00:00:00 2001
From: Dan Lake
Date: Thu, 21 Apr 2011 01:51:08 -0700
Subject: Added ability to remove unacked packet from UnackedPacketCollection
without an acknowledgement from the network. This prevents RTT and throttles
from being updated as they would when an ACK is actually received. Also fixed
stats logging for unacked bytes and resent packets in this case.
---
.../Region/ClientStack/LindenUDP/LLClientView.cs | 12 ++++++++--
.../LindenUDP/UnackedPacketCollection.cs | 28 ++++++++++++++++++++++
2 files changed, 38 insertions(+), 2 deletions(-)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 1e8bbb8..6129e10 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -3590,7 +3590,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Remove the update packet from the list of packets waiting for acknowledgement
// because we are requeuing the list of updates. They will be resent in new packets
// with the most recent state and priority.
- m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber, 0, true);
+ m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
+
+ // Count this as a resent packet since we are going to requeue all of the updates contained in it
+ Interlocked.Increment(ref m_udpClient.PacketsResent);
+
foreach (EntityUpdate update in updates)
ResendPrimUpdate(update);
}
@@ -4038,7 +4042,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Remove the update packet from the list of packets waiting for acknowledgement
// because we are requeuing the list of updates. They will be resent in new packets
// with the most recent state.
- m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber, 0, true);
+ m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
+
+ // Count this as a resent packet since we are going to requeue all of the updates contained in it
+ Interlocked.Increment(ref m_udpClient.PacketsResent);
+
foreach (ObjectPropertyUpdate update in updates)
ResendPropertyUpdate(update);
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index b170964..90a87fa 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -83,6 +83,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
/// Marks a packet as acknowledged
+ /// This method is used when an acknowledgement is received from the network for a previously
+ /// sent packet. Effects of removal this way are to update unacked byte count, adjust RTT
+ /// and increase throttle to the coresponding client.
///
/// Sequence number of the packet to
/// acknowledge
@@ -95,6 +98,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
///
+ /// Marks a packet as no longer needing acknowledgement without a received acknowledgement.
+ /// This method is called when a packet expires and we no longer need an acknowledgement.
+ /// When some reliable packet types expire, they are handled in a way other than simply
+ /// resending them. The only effect of removal this way is to update unacked byte count.
+ ///
+ /// Sequence number of the packet to
+ /// acknowledge
+ /// The packet is removed from the collection immediately.
+ /// This function is not threadsafe. It must be called by the thread calling GetExpiredPackets.
+ public void Remove(uint sequenceNumber)
+ {
+ OutgoingPacket removedPacket;
+ if (m_packets.TryGetValue(sequenceNumber, out removedPacket))
+ {
+ if (removedPacket != null)
+ {
+ m_packets.Remove(sequenceNumber);
+
+ // Update stats
+ Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
+ }
+ }
+ }
+
+ ///
/// Returns a list of all of the packets with a TickCount older than
/// the specified timeout
///
--
cgit v1.1
From 7f28dd4b3195e020eed51fa1229083123935125b Mon Sep 17 00:00:00 2001
From: Dan Lake
Date: Thu, 21 Apr 2011 15:40:32 -0700
Subject: Refactor UnackedPacketCollection so ProcessQueues will handle Adds,
Acks, and Removes in that order.
---
.../Region/ClientStack/LindenUDP/LLUDPServer.cs | 4 +-
.../LindenUDP/UnackedPacketCollection.cs | 56 ++++++++++++----------
2 files changed, 34 insertions(+), 26 deletions(-)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index bd58ddc..aff90c5 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -672,7 +672,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
if (packet.Header.AppendedAcks && packet.Header.AckList != null)
{
for (int i = 0; i < packet.Header.AckList.Length; i++)
- udpClient.NeedAcks.Remove(packet.Header.AckList[i], now, packet.Header.Resent);
+ udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent);
}
// Handle PacketAck packets
@@ -681,7 +681,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
PacketAckPacket ackPacket = (PacketAckPacket)packet;
for (int i = 0; i < ackPacket.Packets.Length; i++)
- udpClient.NeedAcks.Remove(ackPacket.Packets[i].ID, now, packet.Header.Resent);
+ udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent);
// We don't need to do anything else with PacketAck packets
return;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
index 90a87fa..793aefe 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/UnackedPacketCollection.cs
@@ -65,7 +65,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Holds packets that need to be added to the unacknowledged list
private LocklessQueue m_pendingAdds = new LocklessQueue();
/// Holds information about pending acknowledgements
- private LocklessQueue m_pendingRemoves = new LocklessQueue();
+ private LocklessQueue m_pendingAcknowledgements = new LocklessQueue();
+ /// Holds information about pending removals
+ private LocklessQueue m_pendingRemoves = new LocklessQueue();
///
/// Add an unacked packet to the collection
@@ -92,9 +94,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Current value of Environment.TickCount
/// This does not immediately acknowledge the packet, it only
/// queues the ack so it can be handled in a thread-safe way later
- public void Remove(uint sequenceNumber, int currentTime, bool fromResend)
+ public void Acknowledge(uint sequenceNumber, int currentTime, bool fromResend)
{
- m_pendingRemoves.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
+ m_pendingAcknowledgements.Enqueue(new PendingAck(sequenceNumber, currentTime, fromResend));
}
///
@@ -105,21 +107,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
/// Sequence number of the packet to
/// acknowledge
- /// The packet is removed from the collection immediately.
- /// This function is not threadsafe. It must be called by the thread calling GetExpiredPackets.
+ /// The does not immediately remove the packet, it only queues the removal
+ /// so it can be handled in a thread safe way later
public void Remove(uint sequenceNumber)
{
- OutgoingPacket removedPacket;
- if (m_packets.TryGetValue(sequenceNumber, out removedPacket))
- {
- if (removedPacket != null)
- {
- m_packets.Remove(sequenceNumber);
-
- // Update stats
- Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
- }
- }
+ m_pendingRemoves.Enqueue(sequenceNumber);
}
///
@@ -179,15 +171,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_packets[pendingAdd.SequenceNumber] = pendingAdd;
// Process all the pending removes, including updating statistics and round-trip times
- PendingAck pendingRemove;
- OutgoingPacket ackedPacket;
- while (m_pendingRemoves.TryDequeue(out pendingRemove))
+ PendingAck pendingAcknowledgement;
+ while (m_pendingAcknowledgements.TryDequeue(out pendingAcknowledgement))
{
- if (m_packets.TryGetValue(pendingRemove.SequenceNumber, out ackedPacket))
+ OutgoingPacket ackedPacket;
+ if (m_packets.TryGetValue(pendingAcknowledgement.SequenceNumber, out ackedPacket))
{
if (ackedPacket != null)
{
- m_packets.Remove(pendingRemove.SequenceNumber);
+ m_packets.Remove(pendingAcknowledgement.SequenceNumber);
// As with other network applications, assume that an acknowledged packet is an
// indication that the network can handle a little more load, speed up the transmission
@@ -196,16 +188,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Update stats
Interlocked.Add(ref ackedPacket.Client.UnackedBytes, -ackedPacket.Buffer.DataLength);
- if (!pendingRemove.FromResend)
+ if (!pendingAcknowledgement.FromResend)
{
// Calculate the round-trip time for this packet and its ACK
- int rtt = pendingRemove.RemoveTime - ackedPacket.TickCount;
+ int rtt = pendingAcknowledgement.RemoveTime - ackedPacket.TickCount;
if (rtt > 0)
ackedPacket.Client.UpdateRoundTrip(rtt);
}
}
}
}
+
+ uint pendingRemove;
+ while(m_pendingRemoves.TryDequeue(out pendingRemove))
+ {
+ OutgoingPacket removedPacket;
+ if (m_packets.TryGetValue(pendingRemove, out removedPacket))
+ {
+ if (removedPacket != null)
+ {
+ m_packets.Remove(pendingRemove);
+
+ // Update stats
+ Interlocked.Add(ref removedPacket.Client.UnackedBytes, -removedPacket.Buffer.DataLength);
+ }
+ }
+ }
}
}
-}
\ No newline at end of file
+}
--
cgit v1.1
From c5159ad8d00e5b2dc19eb100ec2e74a7a605e139 Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Thu, 21 Apr 2011 15:40:38 -0700
Subject: Add some locking on the child list for the token bucket hiearchy. A
few other cosmetic changes.
---
.../Region/ClientStack/LindenUDP/TokenBucket.cs | 37 +++++++++++++---------
1 file changed, 22 insertions(+), 15 deletions(-)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 4ee6d3a..8ce64d5 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -29,6 +29,8 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
+using OpenSim.Framework;
+
using log4net;
namespace OpenSim.Region.ClientStack.LindenUDP
@@ -177,7 +179,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
RequestedDripRate = dripRate;
// TotalDripRequest = dripRate; // this will be overwritten when a child node registers
// MaxBurst = (Int64)((double)dripRate * m_quantumsPerBurst);
- m_lastDrip = Environment.TickCount & Int32.MaxValue;
+ m_lastDrip = Util.EnvironmentTickCount();
}
#endregion Constructor
@@ -211,12 +213,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public void RegisterRequest(TokenBucket child, Int64 request)
{
- m_children[child] = request;
- // m_totalDripRequest = m_children.Values.Sum();
+ lock (m_children)
+ {
+ m_children[child] = request;
+ // m_totalDripRequest = m_children.Values.Sum();
- m_totalDripRequest = 0;
- foreach (KeyValuePair cref in m_children)
- m_totalDripRequest += cref.Value;
+ m_totalDripRequest = 0;
+ foreach (KeyValuePair cref in m_children)
+ m_totalDripRequest += cref.Value;
+ }
// Pass the new values up to the parent
if (m_parent != null)
@@ -229,12 +234,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public void UnregisterRequest(TokenBucket child)
{
- m_children.Remove(child);
- // m_totalDripRequest = m_children.Values.Sum();
+ lock (m_children)
+ {
+ m_children.Remove(child);
+ // m_totalDripRequest = m_children.Values.Sum();
- m_totalDripRequest = 0;
- foreach (KeyValuePair cref in m_children)
- m_totalDripRequest += cref.Value;
+ m_totalDripRequest = 0;
+ foreach (KeyValuePair cref in m_children)
+ m_totalDripRequest += cref.Value;
+ }
+
// Pass the new values up to the parent
if (m_parent != null)
@@ -297,10 +306,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Determine the interval over which we are adding tokens, never add
// more than a single quantum of tokens
- Int32 now = Environment.TickCount & Int32.MaxValue;
- Int32 deltaMS = Math.Min(now - m_lastDrip, m_ticksPerQuantum);
-
- m_lastDrip = now;
+ Int32 deltaMS = Math.Min(Util.EnvironmentTickCountSubtract(m_lastDrip), m_ticksPerQuantum);
+ m_lastDrip = Util.EnvironmentTickCount();
// This can be 0 in the very unusual case that the timer wrapped
// It can be 0 if we try add tokens at a sub-tick rate
--
cgit v1.1
From 3534f4492ae747baff492f4bc10bf06994ee1bc6 Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Fri, 22 Apr 2011 14:01:12 -0700
Subject: Various clean ups. Removed some debugging code. Added a new "show
pqueues" command to look at the entity update priority queue. Added a "name"
parameter to show queues, show pqueues and show throttles to look at data for
a specific user.
---
OpenSim/Framework/PriorityQueue.cs | 7 +-
.../Region/ClientStack/LindenUDP/LLClientView.cs | 5 +
.../Region/ClientStack/LindenUDP/LLUDPClient.cs | 24 +----
.../Agent/UDP/Linden/LindenUDPInfoModule.cs | 103 ++++++++++++++++++++-
4 files changed, 110 insertions(+), 29 deletions(-)
diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs
index eec2a92..ea718c4 100644
--- a/OpenSim/Framework/PriorityQueue.cs
+++ b/OpenSim/Framework/PriorityQueue.cs
@@ -174,14 +174,13 @@ namespace OpenSim.Framework
}
}
+ ///
+ ///
public override string ToString()
{
string s = "";
for (int i = 0; i < NumberOfQueues; i++)
- {
- if (s != "") s += ",";
- s += m_heaps[i].Count.ToString();
- }
+ s += String.Format("{0,7} ",m_heaps[i].Count);
return s;
}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 6129e10..32a075a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -385,6 +385,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
///
+ /// Entity update queues
+ ///
+ public PriorityQueue EntityUpdateQueue { get { return m_entityUpdates; } }
+
+ ///
/// First name of the agent/avatar represented by the client
///
public string FirstName { get { return m_firstName; } }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 20bfec8..103ec66 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -228,26 +228,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// Information about the client connection
public ClientInfo GetClientInfo()
{
-///
- TokenBucket tb;
-
- tb = m_throttleClient.Parent;
- m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest,"ROOT");
-
- tb = m_throttleClient;
- m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CLIENT");
-
- tb = m_throttleCategory;
- m_log.WarnFormat("[TOKENS] {3}: Actual={0},Request={1},TotalRequest={2}",tb.DripRate,tb.RequestedDripRate,tb.TotalDripRequest," CATEGORY");
-
- for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
- {
- tb = m_throttleCategories[i];
- m_log.WarnFormat("[TOKENS] {4} <{0}:{1}>: Actual={2},Requested={3}",AgentID,i,tb.DripRate,tb.RequestedDripRate," BUCKET");
- }
-
-///
-
// TODO: This data structure is wrong in so many ways. Locking and copying the entire lists
// of pending and needed ACKs for every client every time some method wants information about
// this connection is a recipe for poor performance
@@ -259,12 +239,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
info.landThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate;
info.windThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate;
info.cloudThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate;
- // info.taskThrottle = m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate + m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
info.taskThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate;
info.assetThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate;
info.textureThrottle = (int)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate;
- info.totalThrottle = info.resendThrottle + info.landThrottle + info.windThrottle + info.cloudThrottle +
- info.taskThrottle + info.assetThrottle + info.textureThrottle;
+ info.totalThrottle = (int)m_throttleCategory.DripRate;
return info;
}
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index 6a24cc1..ddbc079 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -82,6 +82,14 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
m_scenes[scene.RegionInfo.RegionID] = scene;
scene.AddCommand(
+ this, "show pqueues",
+ "show pqueues [full]",
+ "Show priority queue data for each client",
+ "Without the 'full' option, only root agents are shown."
+ + " With the 'full' option child agents are also shown.",
+ ShowPQueuesReport);
+
+ scene.AddCommand(
this, "show queues",
"show queues [full]",
"Show queue data for each client",
@@ -119,6 +127,11 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
// m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName);
}
+ protected void ShowPQueuesReport(string module, string[] cmd)
+ {
+ MainConsole.Instance.Output(GetPQueuesReport(cmd));
+ }
+
protected void ShowQueuesReport(string module, string[] cmd)
{
MainConsole.Instance.Output(GetQueuesReport(cmd));
@@ -155,6 +168,80 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
"");
}
+
+ ///
+ /// Generate UDP Queue data report for each client
+ ///
+ ///
+ ///
+ protected string GetPQueuesReport(string[] showParams)
+ {
+ bool showChildren = false;
+ string pname = "";
+
+ if (showParams.Length > 2 && showParams[2] == "full")
+ showChildren = true;
+ else if (showParams.Length > 3)
+ pname = showParams[2] + " " + showParams[3];
+
+ StringBuilder report = new StringBuilder();
+
+ int columnPadding = 2;
+ int maxNameLength = 18;
+ int maxRegionNameLength = 14;
+ int maxTypeLength = 4;
+ int totalInfoFieldsLength = maxNameLength + columnPadding + maxRegionNameLength + columnPadding + maxTypeLength + columnPadding;
+
+ report.Append(GetColumnEntry("User", maxNameLength, columnPadding));
+ report.Append(GetColumnEntry("Region", maxRegionNameLength, columnPadding));
+ report.Append(GetColumnEntry("Type", maxTypeLength, columnPadding));
+
+ report.AppendFormat(
+ "{0,7} {1,7} {2,7} {3,7} {4,7} {5,7} {6,7} {7,7} {8,7} {9,7} {10,7} {11,7}\n",
+ "Pri 0",
+ "Pri 1",
+ "Pri 2",
+ "Pri 3",
+ "Pri 4",
+ "Pri 5",
+ "Pri 6",
+ "Pri 7",
+ "Pri 8",
+ "Pri 9",
+ "Pri 10",
+ "Pri 11");
+
+ lock (m_scenes)
+ {
+ foreach (Scene scene in m_scenes.Values)
+ {
+ scene.ForEachClient(
+ delegate(IClientAPI client)
+ {
+ if (client is LLClientView)
+ {
+ bool isChild = scene.PresenceChildStatus(client.AgentId);
+ if (isChild && !showChildren)
+ return;
+
+ string name = client.Name;
+ if (pname != "" && name != pname)
+ return;
+
+ string regionName = scene.RegionInfo.RegionName;
+
+ report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
+ report.Append(GetColumnEntry(regionName, maxRegionNameLength, columnPadding));
+ report.Append(GetColumnEntry(isChild ? "Cd" : "Rt", maxTypeLength, columnPadding));
+ report.AppendLine(((LLClientView)client).EntityUpdateQueue.ToString());
+ }
+ });
+ }
+ }
+
+ return report.ToString();
+ }
+
///
/// Generate UDP Queue data report for each client
///
@@ -163,10 +250,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
protected string GetQueuesReport(string[] showParams)
{
bool showChildren = false;
+ string pname = "";
if (showParams.Length > 2 && showParams[2] == "full")
showChildren = true;
-
+ else if (showParams.Length > 3)
+ pname = showParams[2] + " " + showParams[3];
+
StringBuilder report = new StringBuilder();
int columnPadding = 2;
@@ -224,6 +314,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
return;
string name = client.Name;
+ if (pname != "" && name != pname)
+ return;
+
string regionName = scene.RegionInfo.RegionName;
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
@@ -249,10 +342,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
protected string GetThrottlesReport(string[] showParams)
{
bool showChildren = false;
+ string pname = "";
if (showParams.Length > 2 && showParams[2] == "full")
showChildren = true;
-
+ else if (showParams.Length > 3)
+ pname = showParams[2] + " " + showParams[3];
+
StringBuilder report = new StringBuilder();
int columnPadding = 2;
@@ -314,6 +410,9 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
return;
string name = client.Name;
+ if (pname != "" && name != pname)
+ return;
+
string regionName = scene.RegionInfo.RegionName;
LLUDPClient llUdpClient = llClient.UDPClient;
--
cgit v1.1
From 08e58e7ca6602782e1727bed9ade89fa42e9b55b Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Fri, 22 Apr 2011 14:02:34 -0700
Subject: Set the initial rate for the adaptive throttle to 160Kpbs or about 15
packets per second.
---
OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 8ce64d5..677d3d1 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -322,10 +322,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
- //
- // The minimum rate for flow control.
- //
- protected const Int64 m_minimumFlow = m_minimumDripRate * 10;
+ ///
+ /// The minimum rate for flow control. Minimum drip rate is one
+ /// packet per second. Open the throttle to 15 packets per second
+ /// or about 160kbps.
+ ///
+ protected const Int64 m_minimumFlow = m_minimumDripRate * 15;
//
// The maximum rate for flow control. Drip rate can never be
--
cgit v1.1
From a3bd769cb33ee59b883998205454bb340d44cb9e Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Fri, 22 Apr 2011 14:55:23 -0700
Subject: Added a second immediate queue to be used for the BestAvatar policy
and currently used for all of an avatars attachments by the other policies.
Also changed the way items are pulled from the update queues to bias close
objects even more.
---
OpenSim/Framework/PriorityQueue.cs | 99 +++++++++++++++++++++-----
OpenSim/Region/Framework/Scenes/Prioritizer.cs | 34 +++++++--
2 files changed, 112 insertions(+), 21 deletions(-)
diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs
index ea718c4..8eeafd1 100644
--- a/OpenSim/Framework/PriorityQueue.cs
+++ b/OpenSim/Framework/PriorityQueue.cs
@@ -42,22 +42,40 @@ namespace OpenSim.Framework
public delegate bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity);
- // Heap[0] for self updates
- // Heap[1..12] for entity updates
-
+ ///
+ /// Total number of queues (priorities) available
+ ///
public const uint NumberOfQueues = 12;
- public const uint ImmediateQueue = 0;
+
+ ///
+ /// Number of queuest (priorities) that are processed immediately
+ /// [] m_heaps = new MinHeap[NumberOfQueues];
private Dictionary m_lookupTable;
+
+ // internal state used to ensure the deqeues are spread across the priority
+ // queues "fairly". queuecounts is the amount to pull from each queue in
+ // each pass. weighted towards the higher priority queues
private uint m_nextQueue = 0;
+ private uint m_countFromQueue = 0;
+ private uint[] m_queueCounts = { 8, 4, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1 };
+
+ // next request is a counter of the number of updates queued, it provides
+ // a total ordering on the updates coming through the queue and is more
+ // lightweight (and more discriminating) than tick count
private UInt64 m_nextRequest = 0;
+ ///
+ /// Lock for enqueue and dequeue operations on the priority queue
+ ///
private object m_syncRoot = new object();
public object SyncRoot {
get { return this.m_syncRoot; }
}
+#region constructor
public PriorityQueue() : this(MinHeap.DEFAULT_CAPACITY) { }
public PriorityQueue(int capacity)
@@ -66,8 +84,16 @@ namespace OpenSim.Framework
for (int i = 0; i < m_heaps.Length; ++i)
m_heaps[i] = new MinHeap(capacity);
+
+ m_nextQueue = NumberOfImmediateQueues;
+ m_countFromQueue = m_queueCounts[m_nextQueue];
}
+#endregion Constructor
+#region PublicMethods
+ ///
+ /// Return the number of items in the queues
+ ///
public int Count
{
get
@@ -79,6 +105,9 @@ namespace OpenSim.Framework
}
}
+ ///
+ /// Enqueue an item into the specified priority queue
+ ///
public bool Enqueue(uint pqueue, IEntityUpdate value)
{
LookupItem lookup;
@@ -100,32 +129,62 @@ namespace OpenSim.Framework
return true;
}
+ ///
+ /// Remove an item from one of the queues. Specifically, it removes the
+ /// oldest item from the next queue in order to provide fair access to
+ /// all of the queues
+ ///
public bool TryDequeue(out IEntityUpdate value, out Int32 timeinqueue)
{
// If there is anything in priority queue 0, return it first no
// matter what else. Breaks fairness. But very useful.
- if (m_heaps[ImmediateQueue].Count > 0)
+ for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
+ {
+ if (m_heaps[iq].Count > 0)
+ {
+ MinHeapItem item = m_heaps[iq].RemoveMin();
+ m_lookupTable.Remove(item.Value.Entity.LocalId);
+ timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
+ value = item.Value;
+
+ return true;
+ }
+ }
+
+ // To get the fair queing, we cycle through each of the
+ // queues when finding an element to dequeue.
+ // We pull (NumberOfQueues - QueueIndex) items from each queue in order
+ // to give lower numbered queues a higher priority and higher percentage
+ // of the bandwidth.
+
+ // Check for more items to be pulled from the current queue
+ if (m_heaps[m_nextQueue].Count > 0 && m_countFromQueue > 0)
{
- MinHeapItem item = m_heaps[ImmediateQueue].RemoveMin();
+ m_countFromQueue--;
+
+ MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value;
-
+
return true;
}
-
- for (int i = 0; i < NumberOfQueues; ++i)
+
+ // Find the next non-immediate queue with updates in it
+ for (int i = 1; i < NumberOfQueues; ++i)
{
- // To get the fair queing, we cycle through each of the
- // queues when finding an element to dequeue, this code
- // assumes that the distribution of updates in the queues
- // is polynomial, probably quadractic (eg distance of PI * R^2)
- uint h = (uint)((m_nextQueue + i) % NumberOfQueues);
- if (m_heaps[h].Count > 0)
+ m_nextQueue = (uint)((m_nextQueue + i) % NumberOfQueues);
+ m_countFromQueue = m_queueCounts[m_nextQueue];
+
+ // if this is one of the immediate queues, just skip it
+ if (m_nextQueue < NumberOfImmediateQueues)
+ continue;
+
+ if (m_heaps[m_nextQueue].Count > 0)
{
- m_nextQueue = (uint)((h + 1) % NumberOfQueues);
+ m_countFromQueue--;
- MinHeapItem item = m_heaps[h].RemoveMin();
+ MinHeapItem item = m_heaps[m_nextQueue].RemoveMin();
m_lookupTable.Remove(item.Value.Entity.LocalId);
timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime);
value = item.Value;
@@ -139,6 +198,10 @@ namespace OpenSim.Framework
return false;
}
+ ///
+ /// Reapply the prioritization function to each of the updates currently
+ /// stored in the priority queues.
+ ///
{
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 2e80156..a7637c0 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
// If this is an update for our own avatar give it the highest priority
if (client.AgentId == entity.UUID)
- return PriorityQueue.ImmediateQueue;
+ return 0;
uint priority;
@@ -119,16 +119,40 @@ namespace OpenSim.Region.Framework.Scenes
private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
{
- return 1;
+ // And anything attached to this avatar gets top priority as well
+ if (entity is SceneObjectPart)
+ {
+ SceneObjectPart sop = (SceneObjectPart)entity;
+ if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
+ return 1;
+ }
+
+ return PriorityQueue.NumberOfImmediateQueues; // first queue past the immediate queues
}
private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
{
+ // And anything attached to this avatar gets top priority as well
+ if (entity is SceneObjectPart)
+ {
+ SceneObjectPart sop = (SceneObjectPart)entity;
+ if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
+ return 1;
+ }
+
return ComputeDistancePriority(client,entity,false);
}
private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
{
+ // And anything attached to this avatar gets top priority as well
+ if (entity is SceneObjectPart)
+ {
+ SceneObjectPart sop = (SceneObjectPart)entity;
+ if (sop.ParentGroup.RootPart.IsAttachment && client.AgentId == sop.ParentGroup.RootPart.AttachedAvatar)
+ return 1;
+ }
+
return ComputeDistancePriority(client,entity,true);
}
@@ -197,8 +221,10 @@ namespace OpenSim.Region.Framework.Scenes
// And convert the distance to a priority queue, this computation gives queues
// at 10, 20, 40, 80, 160, 320, 640, and 1280m
- uint pqueue = 1;
- for (int i = 0; i < 8; i++)
+ uint pqueue = PriorityQueue.NumberOfImmediateQueues;
+ uint queues = PriorityQueue.NumberOfQueues - PriorityQueue.NumberOfImmediateQueues;
+
+ for (int i = 0; i < queues - 1; i++)
{
if (distance < 10 * Math.Pow(2.0,i))
break;
--
cgit v1.1
From e2c6ed236d45e91ffb354b1c59e9f5a5a5b7952d Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Sat, 23 Apr 2011 12:17:10 -0700
Subject: Fix a bug looping through the priority queues. This should fix the
problem of not all prims being sent without reprioritization.
---
OpenSim/Framework/PriorityQueue.cs | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs
index 8eeafd1..3e6fdaa 100644
--- a/OpenSim/Framework/PriorityQueue.cs
+++ b/OpenSim/Framework/PriorityQueue.cs
@@ -101,6 +101,7 @@ namespace OpenSim.Framework
int count = 0;
for (int i = 0; i < m_heaps.Length; ++i)
count += m_heaps[i].Count;
+
return count;
}
}
@@ -171,9 +172,9 @@ namespace OpenSim.Framework
}
// Find the next non-immediate queue with updates in it
- for (int i = 1; i < NumberOfQueues; ++i)
+ for (int i = 0; i < NumberOfQueues; ++i)
{
- m_nextQueue = (uint)((m_nextQueue + i) % NumberOfQueues);
+ m_nextQueue = (uint)((m_nextQueue + 1) % NumberOfQueues);
m_countFromQueue = m_queueCounts[m_nextQueue];
// if this is one of the immediate queues, just skip it
--
cgit v1.1
From 024c12abc3aa42432e55e322141cad1edeb5bad1 Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Mon, 25 Apr 2011 10:44:41 -0700
Subject: Cleaned up various configuration options. Removed the category
throttle limits because the only ones used now are the defaults (which are
overwritten by the client throttles anyway). Updated the default rates to
correspond to about 350kbps.
Also added a configuration to disable adaptive throttle. The default
is the previous behavior (no adaptation).
---
.../Region/ClientStack/LindenUDP/LLUDPClient.cs | 13 ++--
.../Region/ClientStack/LindenUDP/ThrottleRates.cs | 80 ++++------------------
.../Region/ClientStack/LindenUDP/TokenBucket.cs | 19 +++--
.../Agent/UDP/Linden/LindenUDPInfoModule.cs | 18 ++---
bin/OpenSimDefaults.ini | 40 +++++------
5 files changed, 60 insertions(+), 110 deletions(-)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 103ec66..494cb0c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -181,9 +181,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_maxRTO = maxRTO;
// Create a token bucket throttle for this client that has the scene token bucket as a parent
- m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.TotalLimit);
+ m_throttleClient = new AdaptiveTokenBucket(parentThrottle, rates.Total, rates.AdaptiveThrottlesEnabled);
// Create a token bucket throttle for the total categary with the client bucket as a throttle
- m_throttleCategory = new TokenBucket(m_throttleClient, rates.TotalLimit);
+ m_throttleCategory = new TokenBucket(m_throttleClient, rates.Total);
// Create an array of token buckets for this clients different throttle categories
m_throttleCategories = new TokenBucket[THROTTLE_CATEGORY_COUNT];
@@ -194,7 +194,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
// Initialize the packet outboxes, where packets sit while they are waiting for tokens
m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue();
// Initialize the token buckets that control the throttling for each category
- m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetLimit(type));
+ m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
}
// Default the retransmission timeout to three seconds
@@ -341,12 +341,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
task = Math.Max(task, LLUDPServer.MTU);
texture = Math.Max(texture, LLUDPServer.MTU);
asset = Math.Max(asset, LLUDPServer.MTU);
- state = Math.Max(state, LLUDPServer.MTU);
- int total = resend + land + wind + cloud + task + texture + asset + state;
+ int total = resend + land + wind + cloud + task + texture + asset;
- //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}",
- // AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
+ //m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
+ // AgentID, resend, land, wind, cloud, task, texture, asset, total);
// Update the token buckets with new throttle values
TokenBucket bucket;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
index aaf6e26..c9aac0b 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/ThrottleRates.cs
@@ -52,30 +52,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public int Texture;
/// Drip rate for asset packets
public int Asset;
- /// Drip rate for state packets
- public int State;
+
/// Drip rate for the parent token bucket
public int Total;
- /// Maximum burst rate for resent packets
- public int ResendLimit;
- /// Maximum burst rate for land packets
- public int LandLimit;
- /// Maximum burst rate for wind packets
- public int WindLimit;
- /// Maximum burst rate for cloud packets
- public int CloudLimit;
- /// Maximum burst rate for task (state and transaction) packets
- public int TaskLimit;
- /// Maximum burst rate for texture packets
- public int TextureLimit;
- /// Maximum burst rate for asset packets
- public int AssetLimit;
- /// Maximum burst rate for state packets
- public int StateLimit;
- /// Burst rate for the parent token bucket
- public int TotalLimit;
-
+ /// Flag used to enable adaptive throttles
+ public bool AdaptiveThrottlesEnabled;
+
///
/// Default constructor
///
@@ -86,26 +69,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
{
IConfig throttleConfig = config.Configs["ClientStack.LindenUDP"];
- Resend = throttleConfig.GetInt("resend_default", 12500);
- Land = throttleConfig.GetInt("land_default", 1000);
- Wind = throttleConfig.GetInt("wind_default", 1000);
- Cloud = throttleConfig.GetInt("cloud_default", 1000);
- Task = throttleConfig.GetInt("task_default", 1000);
- Texture = throttleConfig.GetInt("texture_default", 1000);
- Asset = throttleConfig.GetInt("asset_default", 1000);
- State = throttleConfig.GetInt("state_default", 1000);
-
- ResendLimit = throttleConfig.GetInt("resend_limit", 18750);
- LandLimit = throttleConfig.GetInt("land_limit", 29750);
- WindLimit = throttleConfig.GetInt("wind_limit", 18750);
- CloudLimit = throttleConfig.GetInt("cloud_limit", 18750);
- TaskLimit = throttleConfig.GetInt("task_limit", 18750);
- TextureLimit = throttleConfig.GetInt("texture_limit", 55750);
- AssetLimit = throttleConfig.GetInt("asset_limit", 27500);
- StateLimit = throttleConfig.GetInt("state_limit", 37000);
+ Resend = throttleConfig.GetInt("resend_default", 6625);
+ Land = throttleConfig.GetInt("land_default", 9125);
+ Wind = throttleConfig.GetInt("wind_default", 1750);
+ Cloud = throttleConfig.GetInt("cloud_default", 1750);
+ Task = throttleConfig.GetInt("task_default", 18500);
+ Texture = throttleConfig.GetInt("texture_default", 18500);
+ Asset = throttleConfig.GetInt("asset_default", 10500);
Total = throttleConfig.GetInt("client_throttle_max_bps", 0);
- TotalLimit = Total;
+
+ AdaptiveThrottlesEnabled = throttleConfig.GetBoolean("enable_adaptive_throttles", false);
}
catch (Exception) { }
}
@@ -128,34 +102,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return Texture;
case ThrottleOutPacketType.Asset:
return Asset;
- case ThrottleOutPacketType.State:
- return State;
- case ThrottleOutPacketType.Unknown:
- default:
- return 0;
- }
- }
-
- public int GetLimit(ThrottleOutPacketType type)
- {
- switch (type)
- {
- case ThrottleOutPacketType.Resend:
- return ResendLimit;
- case ThrottleOutPacketType.Land:
- return LandLimit;
- case ThrottleOutPacketType.Wind:
- return WindLimit;
- case ThrottleOutPacketType.Cloud:
- return CloudLimit;
- case ThrottleOutPacketType.Task:
- return TaskLimit;
- case ThrottleOutPacketType.Texture:
- return TextureLimit;
- case ThrottleOutPacketType.Asset:
- return AssetLimit;
- case ThrottleOutPacketType.State:
- return StateLimit;
case ThrottleOutPacketType.Unknown:
default:
return 0;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 677d3d1..2ec79ab 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -340,6 +340,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
set { m_maxDripRate = (value == 0 ? 0 : Math.Max(value,m_minimumFlow)); }
}
+ private bool m_enabled = false;
+
//
//
//
@@ -357,9 +359,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//
//
//
- public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate) : base(parent,m_minimumFlow)
+ public AdaptiveTokenBucket(TokenBucket parent, Int64 maxDripRate, bool enabled) : base(parent,maxDripRate)
{
- MaxDripRate = maxDripRate;
+ m_enabled = enabled;
+
+ if (m_enabled)
+ {
+ m_log.WarnFormat("[TOKENBUCKET] Adaptive throttle enabled");
+ MaxDripRate = maxDripRate;
+ AdjustedDripRate = m_minimumFlow;
+ }
}
//
@@ -368,7 +377,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
public void ExpirePackets(Int32 count)
{
// m_log.WarnFormat("[ADAPTIVEBUCKET] drop {0} by {1} expired packets",AdjustedDripRate,count);
- AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
+ if (m_enabled)
+ AdjustedDripRate = (Int64) (AdjustedDripRate / Math.Pow(2,count));
}
//
@@ -376,7 +386,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
//
public void AcknowledgePackets(Int32 count)
{
- AdjustedDripRate = AdjustedDripRate + count;
+ if (m_enabled)
+ AdjustedDripRate = AdjustedDripRate + count;
}
}
}
diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
index ddbc079..db17d8f 100644
--- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
+++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs
@@ -398,7 +398,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
if (client is LLClientView)
{
LLClientView llClient = client as LLClientView;
-
+
if (firstClient)
{
report.AppendLine(GetServerThrottlesReport(llClient.UDPServer));
@@ -451,7 +451,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
int maxRegionNameLength = 14;
int maxTypeLength = 4;
- string name = "SERVER AGENT LIMITS";
+ string name = "SERVER AGENT RATES";
report.Append(GetColumnEntry(name, maxNameLength, columnPadding));
report.Append(GetColumnEntry("-", maxRegionNameLength, columnPadding));
@@ -461,13 +461,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden
report.AppendFormat(
"{0,7} {1,8} {2,7} {3,7} {4,7} {5,7} {6,9} {7,7}",
(throttleRates.Total * 8) / 1000,
- (throttleRates.ResendLimit * 8) / 1000,
- (throttleRates.LandLimit * 8) / 1000,
- (throttleRates.WindLimit * 8) / 1000,
- (throttleRates.CloudLimit * 8) / 1000,
- (throttleRates.TaskLimit * 8) / 1000,
- (throttleRates.TextureLimit * 8) / 1000,
- (throttleRates.AssetLimit * 8) / 1000);
+ (throttleRates.Resend * 8) / 1000,
+ (throttleRates.Land * 8) / 1000,
+ (throttleRates.Wind * 8) / 1000,
+ (throttleRates.Cloud * 8) / 1000,
+ (throttleRates.Task * 8) / 1000,
+ (throttleRates.Texture * 8) / 1000,
+ (throttleRates.Asset * 8) / 1000);
return report.ToString();
}
diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini
index 7ea98d4..35e8079 100644
--- a/bin/OpenSimDefaults.ini
+++ b/bin/OpenSimDefaults.ini
@@ -362,30 +362,24 @@
;
;client_throttle_max_bps = 196608
- ; Per-client bytes per second rates for the various throttle categories.
- ; These are default values that will be overriden by clients
- ;
- ;resend_default = 12500
- ;land_default = 1000
- ;wind_default = 1000
- ;cloud_default = 1000
- ;task_default = 1000
- ;texture_default = 1000
- ;asset_default = 1000
- ;state_default = 1000
-
- ; Per-client maximum burst rates in bytes per second for the various
- ; throttle categories. These are default values that will be overriden by
- ; clients
+ ; Adaptive throttling attempts to limit network overload when multiple
+ ; clients login by starting each connection more slowly. Disabled by
+ ; default
;
- ;resend_limit = 18750
- ;land_limit = 29750
- ;wind_limit = 18750
- ;cloud_limit = 18750
- ;task_limit = 18750
- ;texture_limit = 55750
- ;asset_limit = 27500
- ;state_limit = 37000
+ ;enable_adaptive_throttles = true
+
+ ; Per-client bytes per second rates for the various throttle categories.
+ ; These are default values that will be overriden by clients. These
+ ; defaults are approximately equivalent to the throttles set by the Imprudence
+ ; viewer when maximum bandwidth is set to 350kbps
+
+ ;resend_default = 6625
+ ;land_default = 9125
+ ;wind_default = 1750
+ ;cloud_default = 1750
+ ;task_default = 18500
+ ;texture_default = 18500
+ ;asset_default = 10500
; Configures how ObjectUpdates are aggregated. These numbers
; do not literally mean how many updates will be put in each
--
cgit v1.1
From 77ab7ce084d32c45273d79e9ec4f52c43e3a1d97 Mon Sep 17 00:00:00 2001
From: Mic Bowman
Date: Mon, 25 Apr 2011 15:11:29 -0700
Subject: Fixed the transmission of throttles from root agent to child agents.
Child throttles are based on the number of child agents known to the root and
at least 1/4 of the throttle given to the root.
---
.../Region/ClientStack/LindenUDP/LLClientView.cs | 2 +-
.../Region/ClientStack/LindenUDP/LLUDPClient.cs | 40 ++++++++++++++--------
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 33 ++++++++----------
3 files changed, 41 insertions(+), 34 deletions(-)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 32a075a..cdd4224 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -11420,7 +11420,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
///
public byte[] GetThrottlesPacked(float multiplier)
{
- return m_udpClient.GetThrottlesPacked();
+ return m_udpClient.GetThrottlesPacked(multiplier);
}
///
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 494cb0c..50f1e2c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -329,8 +329,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
int asset = (int)(BitConverter.ToSingle(adjData, pos) * 0.125f);
// State is a subcategory of task that we allocate a percentage to
int state = 0;
- // int state = (int)((float)task * STATE_TASK_PERCENTAGE);
- // task -= state;
// Make sure none of the throttles are set below our packet MTU,
// otherwise a throttle could become permanently clogged
@@ -342,17 +340,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
texture = Math.Max(texture, LLUDPServer.MTU);
asset = Math.Max(asset, LLUDPServer.MTU);
- int total = resend + land + wind + cloud + task + texture + asset;
-
+ //int total = resend + land + wind + cloud + task + texture + asset;
//m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, Total={8}",
// AgentID, resend, land, wind, cloud, task, texture, asset, total);
// Update the token buckets with new throttle values
TokenBucket bucket;
- bucket = m_throttleCategory;
- bucket.RequestedDripRate = total;
-
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
bucket.RequestedDripRate = resend;
@@ -381,22 +375,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP
m_packedThrottles = null;
}
- public byte[] GetThrottlesPacked()
+ public byte[] GetThrottlesPacked(float multiplier)
{
byte[] data = m_packedThrottles;
if (data == null)
{
+ float rate;
+
data = new byte[7 * 4];
int i = 0;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate), 0, data, i, 4); i += 4;
- Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate), 0, data, i, 4); i += 4;
+ // multiply by 8 to convert bytes back to bits
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Land].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Task].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
+
+ rate = (float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].RequestedDripRate * 8 * multiplier;
+ Buffer.BlockCopy(Utils.FloatToBytes(rate), 0, data, i, 4); i += 4;
m_packedThrottles = data;
}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 00a1487..ef0eb89 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2632,18 +2632,17 @@ namespace OpenSim.Region.Framework.Scenes
cadu.GroupAccess = 0;
cadu.Position = AbsolutePosition;
cadu.regionHandle = m_rootRegionHandle;
+
+ // Throttles
float multiplier = 1;
- int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
- if (innacurateNeighbors != 0)
- {
- multiplier = 1f / (float)innacurateNeighbors;
- }
- if (multiplier <= 0f)
- {
+ int childRegions = m_knownChildRegions.Count;
+ if (childRegions != 0)
+ multiplier = 1f / childRegions;
+
+ // Minimum throttle for a child region is 1/4 of the root region throttle
+ if (multiplier <= 0.25f)
multiplier = 0.25f;
- }
- //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
cadu.Velocity = Velocity;
@@ -3039,16 +3038,14 @@ namespace OpenSim.Region.Framework.Scenes
// Throttles
float multiplier = 1;
- int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
- if (innacurateNeighbors != 0)
- {
- multiplier = 1f / innacurateNeighbors;
- }
- if (multiplier <= 0f)
- {
+ int childRegions = m_knownChildRegions.Count;
+ if (childRegions != 0)
+ multiplier = 1f / childRegions;
+
+ // Minimum throttle for a child region is 1/4 of the root region throttle
+ if (multiplier <= 0.25f)
multiplier = 0.25f;
- }
- //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
+
cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
cAgent.HeadRotation = m_headrotation;
--
cgit v1.1