From bf517899a7a63278d4ed22d5485c37d61d47bb58 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Mon, 22 Jul 2013 23:30:09 +0100
Subject: Add AverageUDPProcessTime stat to try and get a handle on how long
we're taking on the initial processing of a UDP packet.
If we're not receiving packets with multiple threads (m_asyncPacketHandling) then this is critical since it will limit the number of incoming UDP requests that the region can handle and affects packet loss.
If m_asyncPacketHandling then this is less critical though a long process will increase the scope for threads to race.
This is an experimental stat which may be changed.
---
.../Region/ClientStack/Linden/UDP/LLUDPServer.cs | 19 +++++++++--
.../ClientStack/Linden/UDP/OpenSimUDPBase.cs | 39 ++++++++++++++++++++++
2 files changed, 56 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region')
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index f5c0b05..d3823f3 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -70,8 +70,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
StatsManager.RegisterStat(
new Stat(
"IncomingPacketsProcessedCount",
- "Number of inbound UDP packets processed",
- "Number of inbound UDP packets processed",
+ "Number of inbound LL protocol packets processed",
+ "Number of inbound LL protocol packets processed",
"",
"clientstack",
scene.Name,
@@ -79,6 +79,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
MeasuresOfInterest.AverageChangeOverTime,
stat => stat.Value = m_udpServer.IncomingPacketsProcessed,
StatVerbosity.Debug));
+
+ StatsManager.RegisterStat(
+ new Stat(
+ "AverageUDPProcessTime",
+ "Average number of milliseconds taken to process each incoming UDP packet in a sample.",
+ "This is for initial receive processing which is separate from the later client LL packet processing stage.",
+ "ms",
+ "clientstack",
+ scene.Name,
+ StatType.Pull,
+ MeasuresOfInterest.None,
+ stat => stat.Value = m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond,
+// stat =>
+// stat.Value = Math.Round(m_udpServer.AverageReceiveTicksForLastSamplePeriod / TimeSpan.TicksPerMillisecond, 7),
+ StatVerbosity.Debug));
}
public bool HandlesRegion(Location x)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index a919141..46a3261 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -78,6 +78,26 @@ namespace OpenMetaverse
public bool IsRunningOutbound { get; private set; }
///
+ /// Number of receives over which to establish a receive time average.
+ ///
+ private readonly static int s_receiveTimeSamples = 500;
+
+ ///
+ /// Current number of samples taken to establish a receive time average.
+ ///
+ private int m_currentReceiveTimeSamples;
+
+ ///
+ /// Cumulative receive time for the sample so far.
+ ///
+ private int m_receiveTicksInCurrentSamplePeriod;
+
+ ///
+ /// The average time taken for each require receive in the last sample.
+ ///
+ public float AverageReceiveTicksForLastSamplePeriod { get; private set; }
+
+ ///
/// Default constructor
///
/// Local IP address to bind the server to
@@ -286,6 +306,8 @@ namespace OpenMetaverse
try
{
+ int startTick = Util.EnvironmentTickCount();
+
// get the length of data actually read from the socket, store it with the
// buffer
buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
@@ -293,6 +315,23 @@ namespace OpenMetaverse
// call the abstract method PacketReceived(), passing the buffer that
// has just been filled from the socket read.
PacketReceived(buffer);
+
+ // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler)
+ // then a particular stat may be inaccurate due to a race condition. We won't worry about this
+ // since this should be rare and won't cause a runtime problem.
+ if (m_currentReceiveTimeSamples >= s_receiveTimeSamples)
+ {
+ AverageReceiveTicksForLastSamplePeriod
+ = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples;
+
+ m_receiveTicksInCurrentSamplePeriod = 0;
+ m_currentReceiveTimeSamples = 0;
+ }
+ else
+ {
+ m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick);
+ m_currentReceiveTimeSamples++;
+ }
}
catch (SocketException) { }
catch (ObjectDisposedException) { }
--
cgit v1.1