[Opensim-dev] [Opensim-commits] r9924 - in trunk: OpenSim/Region/ClientStack/LindenUDP bin

John Sheridan john at pseudospace.net
Wed Jul 1 05:28:33 UTC 2009


I'm sitting here clearing up a few scrap prims to make one of my builds 
a bit more efficient (changing from 15 prim factory windows to 5 for 
example) when it occurred to me.  I've noticed that while opensim is 
chugging along, updating the sim database and sending stuff back to my 
inventory, movement in-world starts to lag and studder a bit.  Once its 
done things understandably go back to normal.  I wonder a change similar 
to Dr. Scofield's texture handler only for the database / prim storage 
routines could make even further of a difference?  I'd imagine if so, 
the initial rez-in for example when an avi is wearing 300 some-odd prims 
in attachments would have less of an impact.  Just a thought...  :)

Thanks,

 - John / Orion Pseudo


drscofield at opensimulator.org wrote:
> Author: drscofield
> Date: 2009-06-25 00:42:06 -0700 (Thu, 25 Jun 2009)
> New Revision: 9924
>
> Modified:
>    trunk/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
>    trunk/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
>    trunk/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
>    trunk/bin/OpenSim.ini.example
> Log:
> From: Alan Webb <alan_webb at us.ibm.com>
>
>   This change moves texture send processing out of the main
>   packet processing loop and moves it to a timer based
>   processing cycle.
>
>   Texture packets are sent to the client consistently over
>   time. The timer is discontinued whenever there are no
>   textures to transmit.
>
>   The behavior of the texture sending mechanism is controlled
>   by three variables in the LLCLient section of the config
>   file:
>
>    [1] TextureRequestRate (mS) determines how many times per second
>        texture send processing will occur. The default is 100mS.
>    [2] TextureSendLimit determines how many different textures
>        will be considered on each cycle. Textures are selected
>        by priority. The old mechanism specified a value of 10 for
>        this parameter and this is the default
>    [3] TextureDataLimit determines how many packets will be sent for
>        each of the selected textures. The old mechanism specified a
>        value of 5, so this is the default.
>
>   So the net effect is that TextureSendLimit*TextureDataLimit
>   packets will be sent every TextureRequestRate mS.
>
>   Once we have gotten a reasonable feeling for how these parameters
>   affect overall processing, it would be nice to autonmically manage
>   these values using information about the current status of the
>   region and network.
>
>   Note that this also resolves the pathologcal problem that
>   previously existed which was that a seated avatar generated very
>   few in-bound packets (theoretically) and would therefore be the
>   least able to retrieve the images being displayed by a
>   projector script.
>
> Modified: trunk/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
> ===================================================================
> --- trunk/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs	2009-06-25 07:39:48 UTC (rev 9923)
> +++ trunk/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs	2009-06-25 07:42:06 UTC (rev 9924)
> @@ -260,7 +260,7 @@
>                  return false;
>              }
>          }
> -        public bool SendPackets(LLClientView client)
> +        public bool SendPackets(LLClientView client, int maxpack)
>          {
>  
>              if (!m_completedSendAtCurrentDiscardLevel)
> @@ -284,7 +284,7 @@
>                      }
>  
>                      int count = 0;
> -                    while (SendMore && count < 5 && m_packetNumber <= m_stopPacket)
> +                    while (SendMore && count < maxpack && m_packetNumber <= m_stopPacket)
>                      {
>                          count++;
>                          SendMore = SendPacket(client);
> @@ -391,6 +391,10 @@
>                              }
>                          }
>                      }
> +                    else
> +                    {
> +                        m_packetNumber = m_stopPacket;
> +                    }
>                  }
>              }
>          }
>
> Modified: trunk/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
> ===================================================================
> --- trunk/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs	2009-06-25 07:39:48 UTC (rev 9923)
> +++ trunk/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs	2009-06-25 07:42:06 UTC (rev 9924)
> @@ -80,6 +80,8 @@
>          private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates =
>                  new List<ObjectUpdatePacket.ObjectDataBlock>();
>  
> +        private Timer m_textureRequestTimer;
> +
>          private bool m_clientBlocked;
>  
>          private int m_probesWithNoIngressPackets;
> @@ -140,6 +142,10 @@
>          protected int m_primTerseUpdateRate = 10;
>          protected int m_primFullUpdateRate = 14;
>  
> +        protected int m_textureRequestRate  = 100;
> +        protected int m_textureSendLimit   = 10;
> +        protected int m_textureDataLimit   = 5;
> +
>          protected int m_packetMTU = 1400;
>  
>          protected IAssetService m_assetService;
> @@ -344,6 +350,8 @@
>  
>          private readonly IGroupsModule m_GroupsModule;
>  
> +        private AgentUpdateArgs lastarg = null;
> +
>          //private TerrainUnacked handlerUnackedTerrain = null;
>  
>          //**
> @@ -544,6 +552,15 @@
>                      m_primFullUpdateRate = clientConfig.GetInt("FullUpdateRate",
>                                                                 m_primFullUpdateRate);
>  
> +                    m_textureRequestRate = clientConfig.GetInt("TextureRequestRate",
> +                                                               m_textureRequestRate);
> +
> +                    m_textureSendLimit = clientConfig.GetInt("TextureSendLimit",
> +                                                               m_textureSendLimit);
> +
> +                    m_textureDataLimit = clientConfig.GetInt("TextureDataLimit",
> +                                                               m_textureDataLimit);
> +
>                      m_packetMTU = clientConfig.GetInt("PacketMTU", 1400);
>                  }
>              }
> @@ -577,6 +594,7 @@
>              m_avatarTerseUpdateTimer.Stop();
>              m_primTerseUpdateTimer.Stop();
>              m_primFullUpdateTimer.Stop();
> +            m_textureRequestTimer.Stop();
>  
>              // This is just to give the client a reasonable chance of
>              // flushing out all it's packets.  There should probably
> @@ -660,6 +678,7 @@
>              m_avatarTerseUpdateTimer.Stop();
>              m_primTerseUpdateTimer.Stop();
>              m_primFullUpdateTimer.Stop();
> +            m_textureRequestTimer.Stop();
>          }
>  
>          public void Restart()
> @@ -682,6 +701,11 @@
>              m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
>              m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
>              m_primFullUpdateTimer.AutoReset = false;
> +
> +            m_textureRequestTimer = new Timer(m_textureRequestRate);
> +            m_textureRequestTimer.Elapsed += new ElapsedEventHandler(ProcessTextureRequests);
> +            m_textureRequestTimer.AutoReset = false;
> +
>          }
>  
>          public void Terminate()
> @@ -914,6 +938,11 @@
>              m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
>              m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
>              m_primFullUpdateTimer.AutoReset = false;
> +
> +            m_textureRequestTimer = new Timer(m_textureRequestRate);
> +            m_textureRequestTimer.Elapsed += new ElapsedEventHandler(ProcessTextureRequests);
> +            m_textureRequestTimer.AutoReset = false;
> +
>              m_scene.AddNewClient(this);
>  
>              RefreshGroupMembership();
> @@ -985,6 +1014,26 @@
>              }
>          }
>  
> +        protected virtual void TextureRequestHandler()
> +        {
> +            m_log.DebugFormat("[TRH] Thread started");
> +           while (m_imageManager != null)
> +            {
> +                try
> +                {
> +                   while (m_imageManager != null)
> +                    {
> +                    }
> +                }
> +               catch (Exception e)
> +                {
> +                    m_log.WarnFormat("[TRH] Exception in handler loop: {0}", e.Message);
> +                    m_log.Debug(e);
> +                }
> +            }
> +            m_log.DebugFormat("[TRH] Thread terminated");
> +        }
> +
>          # endregion
>  
>          // Previously ClientView.API partial class
> @@ -3032,6 +3081,21 @@
>              }
>          }
>  
> +        // Unlike the other timers, this one is only started after
> +        // the first request is seen.
> +
> +        void ProcessTextureRequests(object sender, ElapsedEventArgs e)
> +        {
> +            if (m_imageManager != null)
> +            {
> +                if (m_imageManager.ProcessImageQueue(m_textureSendLimit, 
> +                                                     m_textureDataLimit))
> +                {
> +                    m_textureRequestTimer.Start();
> +                }
> +            }
> +        }
> +
>          void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e)
>          {
>              lock (m_primFullUpdates)
> @@ -3237,7 +3301,7 @@
>              ushort numParts, UUID ImageUUID, uint ImageSize, byte[] ImageData, byte imageCodec)
>          {
>              ImageDataPacket im = new ImageDataPacket();
> -            im.Header.Reliable = true;
> +            im.Header.Reliable = false;
>              im.ImageID.Packets = numParts;
>              im.ImageID.ID = ImageUUID;
>  
> @@ -3253,7 +3317,7 @@
>          public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData)
>          {
>              ImagePacketPacket im = new ImagePacketPacket();
> -            im.Header.Reliable = true;
> +            im.Header.Reliable = false;
>              im.ImageID.Packet = partNumber;
>              im.ImageID.ID = imageUuid;
>              im.ImageData.Data = imageData;
> @@ -4727,14 +4791,9 @@
>          /// <param name="Pack">OpenMetaverse.packet</param>
>          public void ProcessInPacket(Packet Pack)
>          {
> -            // check if we've got a local packet handler for this packet.type.   See RegisterLocalPacketHandlers()
> +
>              if (ProcessPacketMethod(Pack))
>              {
> -                //there is a handler registered that handled this packet type
> -
> -                // in the end, we dereference this, so we have to check if it's null
> -                if (m_imageManager != null)
> -                    m_imageManager.ProcessImageQueue(5);
>                  return;
>              }
>  
> @@ -5303,6 +5362,7 @@
>                  case PacketType.AgentUpdate:
>                      if (OnAgentUpdate != null)
>                      {
> +                        bool update = false;
>                          AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack;
>  
>                          #region Packet Session and User Check
> @@ -5315,26 +5375,58 @@
>                          #endregion
>  
>                          AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData;
> -                        AgentUpdateArgs arg = new AgentUpdateArgs();
> -                        arg.AgentID = x.AgentID;
> -                        arg.BodyRotation = x.BodyRotation;
> -                        arg.CameraAtAxis = x.CameraAtAxis;
> -                        arg.CameraCenter = x.CameraCenter;
> -                        arg.CameraLeftAxis = x.CameraLeftAxis;
> -                        arg.CameraUpAxis = x.CameraUpAxis;
> -                        arg.ControlFlags = x.ControlFlags;
> -                        arg.Far = x.Far;
> -                        arg.Flags = x.Flags;
> -                        arg.HeadRotation = x.HeadRotation;
> -                        arg.SessionID = x.SessionID;
> -                        arg.State = x.State;
>  
> -                        handlerAgentUpdate = OnAgentUpdate;
> -                        if (handlerAgentUpdate != null)
> -                            OnAgentUpdate(this, arg);
> +                        // We can only check when we have something to check
> +                        // against.
>  
> -                        handlerAgentUpdate = null;
> -                        //agenUpdate.AgentData.ControlFlags, agenUpdate.AgentData.BodyRotationa);
> +                        if (lastarg != null)
> +                        {
> +                            update = 
> +                               (
> +                                (x.BodyRotation != lastarg.BodyRotation) ||
> +                                (x.CameraAtAxis != lastarg.CameraAtAxis) ||
> +                                (x.CameraCenter != lastarg.CameraCenter) ||
> +                                (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
> +                                (x.CameraUpAxis != lastarg.CameraUpAxis) ||
> +                                (x.ControlFlags != lastarg.ControlFlags) ||
> +                                (x.Far != lastarg.Far) ||
> +                                (x.Flags != lastarg.Flags) ||
> +                                (x.State != lastarg.State) ||
> +                                (x.HeadRotation != lastarg.HeadRotation) ||
> +                                (x.SessionID != lastarg.SessionID) ||
> +                                (x.AgentID != lastarg.AgentID)
> +                               );
> +                        }
> +                        else
> +                            update = true;
> +
> +                        // These should be ordered from most-likely to
> +                        // least likely to change. I've made an initial
> +                        // guess at that.
> +
> +                        if (update)
> +                        {
> +                            AgentUpdateArgs arg = new AgentUpdateArgs();
> +                            arg.AgentID = x.AgentID;
> +                            arg.BodyRotation = x.BodyRotation;
> +                            arg.CameraAtAxis = x.CameraAtAxis;
> +                            arg.CameraCenter = x.CameraCenter;
> +                            arg.CameraLeftAxis = x.CameraLeftAxis;
> +                            arg.CameraUpAxis = x.CameraUpAxis;
> +                            arg.ControlFlags = x.ControlFlags;
> +                            arg.Far = x.Far;
> +                            arg.Flags = x.Flags;
> +                            arg.HeadRotation = x.HeadRotation;
> +                            arg.SessionID = x.SessionID;
> +                            arg.State = x.State;
> +                            handlerAgentUpdate = OnAgentUpdate;
> +                            lastarg = arg; // save this set of arguments for nexttime
> +                            if (handlerAgentUpdate != null)
> +                                OnAgentUpdate(this, arg);
> +
> +                            handlerAgentUpdate = null;
> +                        }
> +
>                      }
>                      break;
>  
> @@ -6392,10 +6484,14 @@
>  
>                              // in the end, we null this, so we have to check if it's null
>                              if (m_imageManager != null)
> +                            {
>                                  m_imageManager.EnqueueReq(args);
> +                                m_textureRequestTimer.Start();
> +                            }
>                          }
>                      }
>                      break;
> +
>                  case PacketType.TransferRequest:
>                      //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
>  
> @@ -9502,10 +9598,8 @@
>                      #endregion
>              }
>  
> -            // in the end, we dereference this, so we have to check if it's null
> -            if (m_imageManager != null)
> -                m_imageManager.ProcessImageQueue(10);
>              PacketPool.Instance.ReturnPacket(Pack);
> +
>          }
>  
>          private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket)
>
> Modified: trunk/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
> ===================================================================
> --- trunk/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs	2009-06-25 07:39:48 UTC (rev 9923)
> +++ trunk/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs	2009-06-25 07:42:06 UTC (rev 9924)
> @@ -26,6 +26,7 @@
>   */
>  
>  using System;
> +using System.Threading;
>  using System.Collections.Generic;
>  using OpenMetaverse;
>  using OpenMetaverse.Imaging;
> @@ -96,46 +97,42 @@
>  
>                      J2KImage imgrequest = m_imagestore[newRequest.RequestedAssetID];
>  
> +                    // This is the inbound request sequence number. We can ignore
> +                    // "old" ones.
> +
>                      if (newRequest.requestSequence > imgrequest.m_lastSequence)
>                      {
> +
>                          imgrequest.m_lastSequence = newRequest.requestSequence;
>  
> -                        //First of all, is this being killed?
> -                        //if (newRequest.Priority == 0.0f && newRequest.DiscardLevel == -1)
> -                        //{
> -                            //Do nothing (leaving the if for future use)
> -                        //}
> -                        //else
> -                        //{
> +                        //Check the priority
>  
> +                        double priority = imgrequest.m_requestedPriority;
> +                        if (priority != newRequest.Priority)
> +                        {
> +                            //Remove the old priority
> +                            m_priorities.Remove(imgrequest.m_designatedPriorityKey);
> +                            //Assign a new unique priority
> +                            imgrequest.m_requestedPriority = newRequest.Priority;
> +                            imgrequest.m_designatedPriorityKey = AssignPriority(newRequest.RequestedAssetID, newRequest.Priority);
> +                        }
>  
> -                            //Check the priority
> -                            double priority = imgrequest.m_requestedPriority;
> -                            if (priority != newRequest.Priority)
> -                            {
> -                                //Remove the old priority
> -                                m_priorities.Remove(imgrequest.m_designatedPriorityKey);
> -                                //Assign a new unique priority
> -                                imgrequest.m_requestedPriority = newRequest.Priority;
> -                                imgrequest.m_designatedPriorityKey = AssignPriority(newRequest.RequestedAssetID, newRequest.Priority);
> -                            }
> +                        //Update the requested discard level
> +                        imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel;
>  
> -                            //Update the requested discard level
> -                            imgrequest.m_requestedDiscardLevel = newRequest.DiscardLevel;
> +                        //Update the requested packet number
> +                        imgrequest.m_requestedPacketNumber = newRequest.PacketNumber;
>  
> -                            //Update the requested packet number
> -                            imgrequest.m_requestedPacketNumber = newRequest.PacketNumber;
> +                        //Check if this will create an outstanding texture request
> +                        bool activated = imgrequest.m_completedSendAtCurrentDiscardLevel;
> +                        //Run an update
>  
> -                             //Check if this will create an outstanding texture request
> -                             bool activated = imgrequest.m_completedSendAtCurrentDiscardLevel;
> -                             //Run an update
> -                             imgrequest.RunUpdate();
> -                             if (activated && !imgrequest.m_completedSendAtCurrentDiscardLevel && imgrequest.m_decoded)
> -                             {
> -                                 m_outstandingtextures++;
> -                             }
> +                        imgrequest.RunUpdate();
>  
> -                        //}
> +                        if (activated && !imgrequest.m_completedSendAtCurrentDiscardLevel && imgrequest.m_decoded)
> +                        {
> +                            Interlocked.Increment(ref m_outstandingtextures);
> +                        }
>                      }
>                  }
>                  else
> @@ -198,10 +195,12 @@
>  
>          }
>  
> -        public void ProcessImageQueue(int count)
> +        public bool ProcessImageQueue(int count, int maxpack)
>          {
> +
>              // this can happen during Close()
> -            if (m_client == null) return;
> +            if (m_client == null)
> +                return false;
>              
>              //Count is the number of textures we want to process in one go.
>              //As part of this class re-write, that number will probably rise
> @@ -214,7 +213,7 @@
>               if (m_lastloopprocessed == 0)
>               {
>                    if (m_client.PacketHandler == null || m_client.PacketHandler.PacketQueue == null || m_client.PacketHandler.PacketQueue.TextureThrottle == null)
> -                      return;
> +                      return false;
>                   //This is decent for a semi fast machine, but we'll calculate it more accurately based on time below
>                    threshold = m_client.PacketHandler.PacketQueue.TextureThrottle.Current / 6300;
>                    m_lastloopprocessed = DateTime.Now.Ticks;
> @@ -239,10 +238,10 @@
>               }
>  
>               if (m_client.PacketHandler == null)
> -                 return;
> +                 return false;
>  
>               if (m_client.PacketHandler.PacketQueue == null)
> -                 return;
> +                 return false;
>  
>              //First of all make sure our packet queue isn't above our threshold 
>  
> @@ -252,24 +251,21 @@
>               {
>                  bool justreset = false;
>              
> -
> -
>                  for (int x = m_priorities.Count - 1; x > -1; x--)
>                  {
>                      
>                      J2KImage imagereq = m_imagestore[m_priorities.Values[x]];
>                      if (imagereq.m_decoded == true && !imagereq.m_completedSendAtCurrentDiscardLevel)
>                      {
> -
>                          numCollected++;
>                          //SendPackets will send up to ten packets per cycle
> -                        if (imagereq.SendPackets(m_client))
> +                        if (imagereq.SendPackets(m_client, maxpack))
>                          {
>                              //Send complete
>                              if (!imagereq.m_completedSendAtCurrentDiscardLevel)
>                              {
>                                  imagereq.m_completedSendAtCurrentDiscardLevel = true;
> -                                m_outstandingtextures--;
> +                                Interlocked.Decrement(ref m_outstandingtextures);
>                                  //Re-assign priority to bottom
>                                  //Remove the old priority
>                                  m_priorities.Remove(imagereq.m_designatedPriorityKey);
> @@ -310,13 +306,10 @@
>  
>                          justreset = true; //prevents us from getting stuck in a loop
>                      }
> -
> -
>                  }
>              }
>  
> -
> -
> +            return m_outstandingtextures != 0;
>          }
>  
>          //Faux destructor
>
> Modified: trunk/bin/OpenSim.ini.example
> ===================================================================
> --- trunk/bin/OpenSim.ini.example	2009-06-25 07:39:48 UTC (rev 9923)
> +++ trunk/bin/OpenSim.ini.example	2009-06-25 07:42:06 UTC (rev 9924)
> @@ -1208,12 +1208,15 @@
>  
>  [LLClient]
>      ; Resend packets markes as reliable until they are received
> +    ;
>      ;ReliableIsImportant = false
>  
>      ; Maximum number of times to resend packets marked reliable
> +    ;
>      ;MaxReliableResends = 3
>  
>      ; Configures how ObjectUpdates are compressed.
> +    ;
>      ;TerseUpdatesPerPacket=10
>      ;FullUpdatesPerPacket=14
>      ;TerseUpdateRate=10
> @@ -1221,7 +1224,23 @@
>  
>      ;PacketMTU = 1400
>      
> +    ; TextureUpdateRate (mS) determines how many times per second
> +    ; texture send processing will occur. The default is 100mS.
> +    ;
> +    ;TextureRequestRate = 100
>  
> +    ; TextureSendLimit determines how many different textures
> +    ; will be considered on each cycle. Textures are selected
> +    ; by priority. The old mechanism specified a value of 10 for
> +    ; this parameter.
> +    ;
> +    ;TextureSendLimit = 10
> +
> +    ; TextureDataLimit determines how many packets will be sent for
> +    ; each of the selected textures. Default is 5.
> +    ;
> +    ;TextureDataLimit = 5
> +
>  ;;
>  ;; These are defatuls that are overwritten below in [Architecture].
>  ;; These defaults allow OpenSim to work out of the box with
>
> _______________________________________________
> Opensim-commits mailing list
> Opensim-commits at lists.berlios.de
> https://lists.berlios.de/mailman/listinfo/opensim-commits
>
>   




More information about the Opensim-dev mailing list