Fix recent regression where adaptive throttles stopped adjusting.
Extends regression tests to test response of adaptive throttles to ack'ed and expired packets.mb-throttle-test
parent
b2e377f168
commit
5ab5d7fe47
|
@ -447,31 +447,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
long total = resend + land + wind + cloud + task + texture + asset;
|
long total = resend + land + wind + cloud + task + texture + asset;
|
||||||
m_throttleClient.TargetDripRate = total;
|
m_throttleClient.TargetDripRate = total;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
TokenBucket bucket;
|
|
||||||
|
|
||||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
|
TokenBucket bucket;
|
||||||
bucket.RequestedDripRate = resend;
|
|
||||||
|
|
||||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
|
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
|
||||||
bucket.RequestedDripRate = land;
|
bucket.RequestedDripRate = resend;
|
||||||
|
|
||||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
|
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
|
||||||
bucket.RequestedDripRate = wind;
|
bucket.RequestedDripRate = land;
|
||||||
|
|
||||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
|
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
|
||||||
bucket.RequestedDripRate = cloud;
|
bucket.RequestedDripRate = wind;
|
||||||
|
|
||||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
|
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
|
||||||
bucket.RequestedDripRate = asset;
|
bucket.RequestedDripRate = cloud;
|
||||||
|
|
||||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
|
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
|
||||||
bucket.RequestedDripRate = task;
|
bucket.RequestedDripRate = asset;
|
||||||
|
|
||||||
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
|
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
|
||||||
bucket.RequestedDripRate = texture;
|
bucket.RequestedDripRate = task;
|
||||||
}
|
|
||||||
|
bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
|
||||||
|
bucket.RequestedDripRate = texture;
|
||||||
|
|
||||||
// Reset the packed throttles cached data
|
// Reset the packed throttles cached data
|
||||||
m_packedThrottles = null;
|
m_packedThrottles = null;
|
||||||
|
|
|
@ -184,7 +184,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
udpServer.Throttle.DebugLevel = 1;
|
udpServer.Throttle.DebugLevel = 1;
|
||||||
udpClient.ThrottleDebugLevel = 1;
|
udpClient.ThrottleDebugLevel = 1;
|
||||||
|
|
||||||
// Total is 28000
|
// Total is 280000
|
||||||
int resendBytes = 10000;
|
int resendBytes = 10000;
|
||||||
int landBytes = 20000;
|
int landBytes = 20000;
|
||||||
int windBytes = 30000;
|
int windBytes = 30000;
|
||||||
|
@ -192,24 +192,38 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
int taskBytes = 50000;
|
int taskBytes = 50000;
|
||||||
int textureBytes = 60000;
|
int textureBytes = 60000;
|
||||||
int assetBytes = 70000;
|
int assetBytes = 70000;
|
||||||
|
int totalBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes;
|
||||||
|
|
||||||
SetThrottles(
|
SetThrottles(
|
||||||
udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
|
udpClient, resendBytes, landBytes, windBytes, cloudBytes, taskBytes, textureBytes, assetBytes);
|
||||||
|
|
||||||
// We expect individual throttle changes to currently have no effect under adaptive, since this is managed
|
// Ratio of current adaptive drip rate to requested bytes
|
||||||
// purely by that throttle. However, we expect the max to change.
|
// XXX: Should hard code this as below so we don't rely on values given by tested code to construct
|
||||||
// XXX: At the moment we check against defaults, but at some point there should be a better test to
|
// expected values.
|
||||||
// active see change over time.
|
double commitRatio = (double)udpClient.FlowThrottle.AdjustedDripRate / udpClient.FlowThrottle.TargetDripRate;
|
||||||
ThrottleRates defaultRates = udpServer.ThrottleRates;
|
|
||||||
|
|
||||||
// Current total is 66750
|
|
||||||
int totalBytes = defaultRates.Resend + defaultRates.Land + defaultRates.Wind + defaultRates.Cloud + defaultRates.Task + defaultRates.Texture + defaultRates.Asset;
|
|
||||||
int totalMaxBytes = resendBytes + landBytes + windBytes + cloudBytes + taskBytes + textureBytes + assetBytes;
|
|
||||||
|
|
||||||
AssertThrottles(
|
AssertThrottles(
|
||||||
udpClient,
|
udpClient,
|
||||||
defaultRates.Resend, defaultRates.Land, defaultRates.Wind, defaultRates.Cloud, defaultRates.Task,
|
LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
|
||||||
defaultRates.Texture, defaultRates.Asset, totalBytes, totalMaxBytes, 0);
|
textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
|
||||||
|
|
||||||
|
// Test an increase in target throttle
|
||||||
|
udpClient.FlowThrottle.AcknowledgePackets(35000);
|
||||||
|
commitRatio = 0.2;
|
||||||
|
|
||||||
|
AssertThrottles(
|
||||||
|
udpClient,
|
||||||
|
resendBytes * commitRatio, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
|
||||||
|
textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
|
||||||
|
|
||||||
|
// Test a decrease in target throttle
|
||||||
|
udpClient.FlowThrottle.ExpirePackets(1);
|
||||||
|
commitRatio = 0.1;
|
||||||
|
|
||||||
|
AssertThrottles(
|
||||||
|
udpClient,
|
||||||
|
LLUDPServer.MTU, landBytes * commitRatio, windBytes * commitRatio, cloudBytes * commitRatio, taskBytes * commitRatio,
|
||||||
|
textureBytes * commitRatio, assetBytes * commitRatio, udpClient.FlowThrottle.AdjustedDripRate, totalBytes, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -376,9 +390,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests
|
||||||
{
|
{
|
||||||
ClientInfo ci = udpClient.GetClientInfo();
|
ClientInfo ci = udpClient.GetClientInfo();
|
||||||
|
|
||||||
// Console.WriteLine(
|
// Console.WriteLine(
|
||||||
// "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}",
|
// "Resend={0}, Land={1}, Wind={2}, Cloud={3}, Task={4}, Texture={5}, Asset={6}, TOTAL = {7}",
|
||||||
// ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle);
|
// ci.resendThrottle, ci.landThrottle, ci.windThrottle, ci.cloudThrottle, ci.taskThrottle, ci.textureThrottle, ci.assetThrottle, ci.totalThrottle);
|
||||||
|
|
||||||
Assert.AreEqual((int)resendBytes, ci.resendThrottle, "Resend");
|
Assert.AreEqual((int)resendBytes, ci.resendThrottle, "Resend");
|
||||||
Assert.AreEqual((int)landBytes, ci.landThrottle, "Land");
|
Assert.AreEqual((int)landBytes, ci.landThrottle, "Land");
|
||||||
|
|
|
@ -77,8 +77,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
|
protected Dictionary<TokenBucket,Int64> m_children = new Dictionary<TokenBucket,Int64>();
|
||||||
|
|
||||||
#region Properties
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The parent bucket of this bucket, or null if this bucket has no
|
/// The parent bucket of this bucket, or null if this bucket has no
|
||||||
/// parent. The parent bucket will limit the aggregate bandwidth of all
|
/// parent. The parent bucket will limit the aggregate bandwidth of all
|
||||||
|
@ -123,7 +121,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// RequestedDripRate is set to 0. Really, this should always return m_dripRate and then we can get
|
/// RequestedDripRate is set to 0. Really, this should always return m_dripRate and then we can get
|
||||||
/// (m_dripRate == 0 ? TotalDripRequest : m_dripRate) on some other properties.
|
/// (m_dripRate == 0 ? TotalDripRequest : m_dripRate) on some other properties.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
protected Int64 m_dripRate;
|
|
||||||
public virtual Int64 RequestedDripRate
|
public virtual Int64 RequestedDripRate
|
||||||
{
|
{
|
||||||
get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); }
|
get { return (m_dripRate == 0 ? TotalDripRequest : m_dripRate); }
|
||||||
|
@ -179,6 +176,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
return (Int64)rate;
|
return (Int64)rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
protected Int64 m_dripRate;
|
||||||
|
|
||||||
// <summary>
|
// <summary>
|
||||||
// The maximum rate for flow control. Drip rate can never be greater than this.
|
// The maximum rate for flow control. Drip rate can never be greater than this.
|
||||||
|
@ -190,30 +188,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Int64 TotalDripRequest { get; protected set; }
|
public Int64 TotalDripRequest { get; protected set; }
|
||||||
|
|
||||||
#endregion Properties
|
|
||||||
|
|
||||||
#region Constructor
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default constructor
|
/// Default constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="identifier">Identifier for this token bucket</param>
|
/// <param name="identifier">Identifier for this token bucket</param>
|
||||||
/// <param name="parent">Parent bucket if this is a child bucket, or
|
/// <param name="parent">Parent bucket if this is a child bucket, or
|
||||||
/// null if this is a root bucket</param>
|
/// null if this is a root bucket</param>
|
||||||
/// <param name="dripRate">Rate that the bucket fills, in bytes per
|
/// <param name="requestedDripRate">
|
||||||
/// second. If zero, the bucket always remains full</param>
|
/// Requested rate that the bucket fills, in bytes per
|
||||||
public TokenBucket(string identifier, TokenBucket parent, Int64 dripRate, Int64 maxDripRate)
|
/// second. If zero, the bucket always remains full.
|
||||||
|
/// </param>
|
||||||
|
public TokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate)
|
||||||
{
|
{
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
|
|
||||||
Parent = parent;
|
Parent = parent;
|
||||||
RequestedDripRate = dripRate;
|
RequestedDripRate = requestedDripRate;
|
||||||
MaxDripRate = maxDripRate;
|
MaxDripRate = maxDripRate;
|
||||||
m_lastDrip = Util.EnvironmentTickCount();
|
m_lastDrip = Util.EnvironmentTickCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion Constructor
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Compute a modifier for the MaxBurst rate. This is 1.0, meaning
|
/// Compute a modifier for the MaxBurst rate. This is 1.0, meaning
|
||||||
/// no modification if the requested bandwidth is less than the
|
/// no modification if the requested bandwidth is less than the
|
||||||
|
@ -374,7 +368,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public Int64 TargetDripRate
|
public Int64 TargetDripRate
|
||||||
{
|
{
|
||||||
get { return m_targetDripRate; }
|
get { return m_targetDripRate; }
|
||||||
set { m_targetDripRate = Math.Max(0, value); }
|
set
|
||||||
|
{
|
||||||
|
m_targetDripRate = Math.Max(value, m_minimumFlow);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
protected Int64 m_targetDripRate;
|
protected Int64 m_targetDripRate;
|
||||||
|
|
||||||
|
@ -384,9 +381,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
public virtual Int64 AdjustedDripRate
|
public virtual Int64 AdjustedDripRate
|
||||||
{
|
{
|
||||||
get { return m_dripRate; }
|
get { return m_dripRate; }
|
||||||
set {
|
set
|
||||||
|
{
|
||||||
m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate);
|
m_dripRate = OpenSim.Framework.Util.Clamp<Int64>(value, m_minimumFlow, TargetDripRate);
|
||||||
m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
|
m_burstRate = (Int64)((double)m_dripRate * m_quantumsPerBurst);
|
||||||
|
|
||||||
if (Parent != null)
|
if (Parent != null)
|
||||||
Parent.RegisterRequest(this, m_dripRate);
|
Parent.RegisterRequest(this, m_dripRate);
|
||||||
}
|
}
|
||||||
|
@ -399,14 +398,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected const Int64 m_minimumFlow = m_minimumDripRate * 15;
|
protected const Int64 m_minimumFlow = m_minimumDripRate * 15;
|
||||||
|
|
||||||
public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 dripRate, Int64 maxDripRate, bool enabled)
|
public AdaptiveTokenBucket(string identifier, TokenBucket parent, Int64 requestedDripRate, Int64 maxDripRate, bool enabled)
|
||||||
: base(identifier, parent, dripRate, maxDripRate)
|
: base(identifier, parent, requestedDripRate, maxDripRate)
|
||||||
{
|
{
|
||||||
AdaptiveEnabled = enabled;
|
AdaptiveEnabled = enabled;
|
||||||
|
|
||||||
if (AdaptiveEnabled)
|
if (AdaptiveEnabled)
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled");
|
// m_log.DebugFormat("[TOKENBUCKET]: Adaptive throttle enabled");
|
||||||
|
TargetDripRate = m_minimumFlow;
|
||||||
AdjustedDripRate = m_minimumFlow;
|
AdjustedDripRate = m_minimumFlow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue