From 238c51329e4ef1359508332271293c64b062cdd8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 13 Aug 2014 22:38:27 +0100 Subject: [PATCH] Terminate 'nothing' behaviour (and potentially others) by signalling using an event rather than polling connection state every 100ms This kind of polling is very expensive with many bots/polling threads and appears to be the primary cause of bot falloff from the client end at higher loads. Where inbound packet threads can't run in time due to contention and simulator disconnect timeout occurs. --- .../pCampBot/Behaviours/AbstractBehaviour.cs | 14 ++++- .../pCampBot/Behaviours/NoneBehaviour.cs | 10 ++++ .../pCampBot/Behaviours/PhysicsBehaviour.cs | 2 + OpenSim/Tools/pCampBot/Bot.cs | 58 ++++++++----------- .../Tools/pCampBot/Interfaces/IBehaviour.cs | 8 +++ 5 files changed, 56 insertions(+), 36 deletions(-) diff --git a/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs index 9bc85124ac..c1ba36b94a 100644 --- a/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs +++ b/OpenSim/Tools/pCampBot/Behaviours/AbstractBehaviour.cs @@ -29,11 +29,12 @@ using OpenMetaverse; using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using pCampBot.Interfaces; namespace pCampBot { - public class AbstractBehaviour : IBehaviour + public abstract class AbstractBehaviour : IBehaviour { /// /// Abbreviated name of this behaviour. @@ -44,13 +45,20 @@ namespace pCampBot public Bot Bot { get; protected set; } - public virtual void Action() {} + public abstract void Action(); + + public virtual void Interrupt() {} + + protected AutoResetEvent m_interruptEvent = new AutoResetEvent(false); public virtual void Initialize(Bot bot) { Bot = bot; } - public virtual void Close() {} + public virtual void Close() + { + Interrupt(); + } } } diff --git a/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs index 9a3075c5c4..4a7237c590 100644 --- a/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs +++ b/OpenSim/Tools/pCampBot/Behaviours/NoneBehaviour.cs @@ -43,5 +43,15 @@ namespace pCampBot AbbreviatedName = "n"; Name = "None"; } + + public override void Action() + { + m_interruptEvent.WaitOne(); + } + + public override void Interrupt() + { + m_interruptEvent.Set(); + } } } \ No newline at end of file diff --git a/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs index 6fd2b7c70b..98ab931441 100644 --- a/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs +++ b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs @@ -82,6 +82,8 @@ namespace pCampBot { if (Bot.ConnectionState == ConnectionState.Connected) Bot.Client.Self.Jump(false); + + base.Close(); } private string[] readexcuses() diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs index 3c07a7ce87..59e168f93c 100644 --- a/OpenSim/Tools/pCampBot/Bot.cs +++ b/OpenSim/Tools/pCampBot/Bot.cs @@ -192,15 +192,15 @@ namespace pCampBot public bool AddBehaviour(IBehaviour behaviour) { - lock (Behaviours) - { - if (!Behaviours.ContainsKey(behaviour.AbbreviatedName)) - { - behaviour.Initialize(this); - Behaviours.Add(behaviour.AbbreviatedName, behaviour); + Dictionary updatedBehaviours = new Dictionary(Behaviours); - return true; - } + if (!updatedBehaviours.ContainsKey(behaviour.AbbreviatedName)) + { + behaviour.Initialize(this); + updatedBehaviours.Add(behaviour.AbbreviatedName, behaviour); + Behaviours = updatedBehaviours; + + return true; } return false; @@ -208,18 +208,17 @@ namespace pCampBot public bool RemoveBehaviour(string abbreviatedName) { - lock (Behaviours) - { - IBehaviour behaviour; + Dictionary updatedBehaviours = new Dictionary(Behaviours); + IBehaviour behaviour; - if (!Behaviours.TryGetValue(abbreviatedName, out behaviour)) - return false; + if (!updatedBehaviours.TryGetValue(abbreviatedName, out behaviour)) + return false; - behaviour.Close(); - Behaviours.Remove(abbreviatedName); + behaviour.Close(); + updatedBehaviours.Remove(abbreviatedName); + Behaviours = updatedBehaviours; - return true; - } + return true; } private void CreateLibOmvClient() @@ -279,24 +278,17 @@ namespace pCampBot { while (ConnectionState == ConnectionState.Connected) { - lock (Behaviours) + foreach (IBehaviour behaviour in Behaviours.Values) { - foreach (IBehaviour behaviour in Behaviours.Values) - { // Thread.Sleep(Random.Next(3000, 10000)); - - // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType()); - behaviour.Action(); - } + + // m_log.DebugFormat("[pCAMPBOT]: For {0} performing action {1}", Name, b.GetType()); + behaviour.Action(); } - - // XXX: This is a really shitty way of yielding so that behaviours can be added/removed - Thread.Sleep(100); } - lock (Behaviours) - foreach (IBehaviour b in Behaviours.Values) - b.Close(); + foreach (IBehaviour b in Behaviours.Values) + b.Close(); } /// @@ -305,9 +297,9 @@ namespace pCampBot public void Disconnect() { ConnectionState = ConnectionState.Disconnecting; - -// if (m_actionThread != null) -// m_actionThread.Abort(); + + foreach (IBehaviour behaviour in Behaviours.Values) + behaviour.Interrupt(); Client.Network.Logout(); } diff --git a/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs b/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs index 0ed48256c1..660c630468 100644 --- a/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs +++ b/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs @@ -50,6 +50,14 @@ namespace pCampBot.Interfaces /// void Initialize(Bot bot); + /// + /// Interrupt the behaviour. + /// + /// + /// This should cause the current Action call() to terminate if this is active. + /// + void Interrupt(); + /// /// Close down this behaviour. ///