Преглед на файлове

Add object count stats for new IncomingPacket and UDPPacketBuffer pools if they are enabled. Add count stats for existing LLUDP pool.

This introduces a pull stat type in addition to the push stat type.
A pull stat takes a method on construction which knows how to update the stat on request.
In this way, special interfaces for pull stat collection are not necessary.
Justin Clark-Casey (justincc) преди 11 години
родител
ревизия
4578ff74fe

+ 69 - 6
OpenSim/Framework/Monitoring/StatsManager.cs

@@ -248,6 +248,19 @@ namespace OpenSim.Framework.Monitoring
         }
     }
 
+    /// <summary>
+    /// Stat type.
+    /// </summary>
+    /// <remarks>
+    /// A push stat is one which is continually updated and so it's value can simply by read.
+    /// A pull stat is one where reading the value triggers a collection method - the stat is not continually updated.
+    /// </remarks>
+    public enum StatType
+    {
+        Push,
+        Pull
+    }
+
     /// <summary>
     /// Verbosity of stat.
     /// </summary>
@@ -285,29 +298,65 @@ namespace OpenSim.Framework.Monitoring
         /// </value>
         public string Container { get; private set; }
 
+        public StatType StatType { get; private set; }
+
+        /// <summary>
+        /// Action used to update this stat when the value is requested if it's a pull type.
+        /// </summary>
+        public Action<Stat> PullAction { get; private set; }
+
         public StatVerbosity Verbosity { get; private set; }
         public string ShortName { get; private set; }
         public string Name { get; private set; }
         public string Description { get; private set; }
         public virtual string UnitName { get; private set; }
 
-        public virtual double Value { get; set; }
+        public virtual double Value
+        {
+            get
+            {
+                // Asking for an update here means that the updater cannot access this value without infinite recursion.
+                // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being
+                // called by the pull action and just return the value.
+                if (StatType == StatType.Pull)
+                    PullAction(this);
+
+                return m_value;
+            }
+
+            set
+            {
+                m_value = value;
+            }
+        }
+
+        private double m_value;
 
         /// <summary>
         /// Constructor
         /// </summary>
         /// <param name='shortName'>Short name for the stat.  Must not contain spaces.  e.g. "LongFrames"</param>
         /// <param name='name'>Human readable name for the stat.  e.g. "Long frames"</param>
+        /// <param name='description'>Description of stat</param>
         /// <param name='unitName'>
         /// Unit name for the stat.  Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value.
         /// e.g. " frames"
         /// </param>
         /// <param name='category'>Category under which this stat should appear, e.g. "scene".  Do not capitalize.</param>
         /// <param name='container'>Entity to which this stat relates.  e.g. scene name if this is a per scene stat.</param>
+        /// <param name='type'>Push or pull</param>
+        /// <param name='pullAction'>Pull stats need an action to update the stat on request.  Push stats should set null here.</param>
         /// <param name='verbosity'>Verbosity of stat.  Controls whether it will appear in short stat display or only full display.</param>
-        /// <param name='description'>Description of stat</param>
         public Stat(
-            string shortName, string name, string unitName, string category, string container, StatVerbosity verbosity, string description)
+            string shortName,
+            string name,
+            string description,
+            string unitName,
+            string category,
+            string container,
+            StatType type,
+            Action<Stat> pullAction,
+            StatVerbosity verbosity)
         {
             if (StatsManager.SubCommands.Contains(category))
                 throw new Exception(
@@ -315,11 +364,18 @@ namespace OpenSim.Framework.Monitoring
 
             ShortName = shortName;
             Name = name;
+            Description = description;
             UnitName = unitName;
             Category = category;
             Container = container;
+            StatType = type;
+
+            if (StatType == StatType.Push && pullAction != null)
+                throw new Exception("A push stat cannot have a pull action");
+            else
+                PullAction = pullAction;
+
             Verbosity = verbosity;
-            Description = description;
 
             UniqueName = GenUniqueName(Container, Category, ShortName);
         }
@@ -361,8 +417,15 @@ namespace OpenSim.Framework.Monitoring
         }
 
         public PercentageStat(
-            string shortName, string name, string category, string container, StatVerbosity verbosity, string description)
-            : base(shortName, name, "%", category, container, verbosity, description) {}
+            string shortName,
+            string name,
+            string description,
+            string category,
+            string container,
+            StatType type,
+            Action<Stat> pullAction,
+            StatVerbosity verbosity)
+            : base(shortName, name, description, "%", category, container, type, pullAction, verbosity) {}
 
         public override string ToConsoleString()
         {

+ 15 - 0
OpenSim/Framework/Pool.cs

@@ -38,8 +38,23 @@ namespace OpenSim.Framework
     /// </remarks>
     public class Pool<T>
     {
+        /// <summary>
+        /// Number of objects in the pool.
+        /// </summary>
+        public int Count
+        {
+            get
+            {
+                lock (m_pool)
+                    return m_pool.Count;
+            }
+        }
+
         private Stack<T> m_pool;
 
+        /// <summary>
+        /// Maximum pool size.  Beyond this, any returned objects are not pooled.
+        /// </summary>
         private int m_maxPoolSize;
 
         private Func<T> m_createFunction;

+ 14 - 0
OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs

@@ -278,7 +278,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             ThrottleRates = new ThrottleRates(configSource);
 
             if (UsePools)
+            {
                 m_incomingPacketPool = new Pool<IncomingPacket>(() => new IncomingPacket(), 500);
+
+                StatsManager.RegisterStat(
+                    new Stat(
+                        "IncomingPacketPoolCount",
+                        "Objects within incoming packet pool",
+                        "The number of objects currently stored within the incoming packet pool",
+                        "",
+                        "clientstack",
+                        "packetpool",
+                        StatType.Pull,
+                        stat => stat.Value = m_incomingPacketPool.Count,
+                        StatVerbosity.Debug));
+            }
         }
 
         public void Start()

+ 17 - 0
OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs

@@ -31,6 +31,7 @@ using System.Net.Sockets;
 using System.Threading;
 using log4net;
 using OpenSim.Framework;
+using OpenSim.Framework.Monitoring;
 
 namespace OpenMetaverse
 {
@@ -107,9 +108,25 @@ namespace OpenMetaverse
         public void StartInbound(int recvBufferSize, bool asyncPacketHandling)
         {
             if (UsePools)
+            {
                 m_pool = new Pool<UDPPacketBuffer>(() => new UDPPacketBuffer(), 500);
+
+                StatsManager.RegisterStat(
+                    new Stat(
+                        "UDPPacketBufferPoolCount",
+                        "Objects within the UDPPacketBuffer pool",
+                        "The number of objects currently stored within the UDPPacketBuffer pool",
+                        "",
+                        "clientstack",
+                        "packetpool",
+                        StatType.Pull,
+                        stat => stat.Value = m_pool.Count,
+                        StatVerbosity.Debug));
+            }
             else
+            {
                 m_pool = null;
+            }
 
             m_asyncPacketHandling = asyncPacketHandling;
 

+ 34 - 6
OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs

@@ -47,18 +47,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
         private PercentageStat m_packetsReusedStat = new PercentageStat(
             "PacketsReused",
             "Packets reused",
+            "Number of packets reused out of all requests to the packet pool",
             "clientstack",
             "packetpool",
-            StatVerbosity.Debug,
-            "Number of packets reused out of all requests to the packet pool");
+            StatType.Push,
+            null,
+            StatVerbosity.Debug);
 
         private PercentageStat m_blocksReusedStat = new PercentageStat(
-            "BlocksReused",
-            "Blocks reused",
+            "PacketDataBlocksReused",
+            "Packet data blocks reused",
+            "Number of data blocks reused out of all requests to the packet pool",
             "clientstack",
             "packetpool",
-            StatVerbosity.Debug,
-            "Number of data blocks reused out of all requests to the packet pool");
+            StatType.Push,
+            null,
+            StatVerbosity.Debug);
 
         /// <summary>
         /// Pool of packets available for reuse.
@@ -88,6 +92,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
         {
             StatsManager.RegisterStat(m_packetsReusedStat);
             StatsManager.RegisterStat(m_blocksReusedStat);
+
+            StatsManager.RegisterStat(
+                new Stat(
+                    "PacketsPoolCount",
+                    "Objects within the packet pool",
+                    "The number of objects currently stored within the packet pool",
+                    "",
+                    "clientstack",
+                    "packetpool",
+                    StatType.Pull,
+                    stat => { lock (pool) { stat.Value = pool.Count; } },
+                    StatVerbosity.Debug));
+
+            StatsManager.RegisterStat(
+                new Stat(
+                    "PacketDataBlocksPoolCount",
+                    "Objects within the packet data block pool",
+                    "The number of objects currently stored within the packet data block pool",
+                    "",
+                    "clientstack",
+                    "packetpool",
+                    StatType.Pull,
+                    stat => { lock (DataBlocks) { stat.Value = DataBlocks.Count; } },
+                    StatVerbosity.Debug));
         }
 
         /// <summary>

+ 4 - 2
OpenSim/Region/Framework/Scenes/SimStatsReporter.cs

@@ -245,11 +245,13 @@ namespace OpenSim.Region.Framework.Scenes
                 = new Stat(
                     "SlowFrames",
                     "Slow Frames",
+                    "Number of frames where frame time has been significantly longer than the desired frame time.",
                     " frames",
                     "scene",
                     m_scene.Name,
-                    StatVerbosity.Info,
-                    "Number of frames where frame time has been significantly longer than the desired frame time.");
+                    StatType.Push,
+                    null,
+                    StatVerbosity.Info);
 
             StatsManager.RegisterStat(SlowFramesStat);
         }