From 20635cc8eefe130805dfd4b0333be78c80211afb Mon Sep 17 00:00:00 2001 From: Mark Sturgill Date: Mon, 14 Oct 2013 21:24:09 -0700 Subject: [PATCH] handle speech events with some parallelism limit pooled enumerables and timerchangeentries to 200 (arbitrary) dont place disposed items back in the pool --- Server/Map.cs | 34 +++++--- Server/Mobile.cs | 205 ++++++++++++++++++++++++----------------------- Server/Timer.cs | 2 +- 3 files changed, 131 insertions(+), 110 deletions(-) diff --git a/Server/Map.cs b/Server/Map.cs index 27b99fe7f..203a0eaf8 100644 --- a/Server/Map.cs +++ b/Server/Map.cs @@ -1142,13 +1142,21 @@ namespace Server m_Enumerator = null; } - lock (m_InstancePool) + lock (m_InstancePool) { + if (m_InstancePool.Count < 200) // Arbitrary m_InstancePool.Enqueue( this ); + } } public void Dispose() { - Free(); + // Don't return disposed objects to the instance pool + //Free(); + + if (m_Enumerator != null) { + m_Enumerator.Free(); + m_Enumerator = null; + } } } #endregion @@ -1214,8 +1222,10 @@ namespace Server m_Enumerator = null; } - lock (m_InstancePool) - m_InstancePool.Enqueue( this ); + lock (m_InstancePool) { + if (m_InstancePool.Count < 200) // Arbitrary + m_InstancePool.Enqueue( this ); + } } public TypedEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type ) @@ -1364,7 +1374,9 @@ namespace Server return; lock (m_InstancePool) { - m_InstancePool.Enqueue( this ); + if (m_InstancePool.Count < 200) // Arbitrary + m_InstancePool.Enqueue( this ); + m_List = null; } } @@ -1428,8 +1440,10 @@ namespace Server m_Enumerator = null; } - lock (m_InstancePool) - m_InstancePool.Enqueue( this ); + lock (m_InstancePool) { + if (m_InstancePool.Count < 200) // Arbitrary + m_InstancePool.Enqueue( this ); + } } private ObjectEnumerator( Map map, Rectangle2D bounds ) @@ -1567,8 +1581,10 @@ namespace Server if ( m_Enumerable != null ) m_Enumerable.Free(); - lock (m_InstancePool) - m_InstancePool.Enqueue( this ); + lock (m_InstancePool) { + if (m_InstancePool.Count < 200) // Arbitrary + m_InstancePool.Enqueue( this ); + } } private SectorEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type ) diff --git a/Server/Mobile.cs b/Server/Mobile.cs index 0556792e3..4d7ac80a9 100644 --- a/Server/Mobile.cs +++ b/Server/Mobile.cs @@ -3084,7 +3084,8 @@ namespace Server private long m_EndQueue; - private static ArrayList m_MoveList = new ArrayList(); + private static List m_MoveList = new List(); + private static List m_MoveClientList = new List(); private static AccessLevel m_FwdAccessOverride = AccessLevel.Counselor; private static bool m_FwdEnabled = true; @@ -3315,21 +3316,20 @@ namespace Server { IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, Core.GlobalMaxUpdateRange ); - foreach( object o in eable ) - { - if( o == this ) + foreach(IEntity o in eable) { + if(o == this) continue; - if( o is Mobile ) - { - m_MoveList.Add( o ); - } - else if( o is Item ) - { + if(o is Mobile) { + Mobile mob = o as Mobile; + if (mob.NetState != null) + m_MoveClientList.Add(mob); + m_MoveList.Add(o); + } else if(o is Item) { Item item = (Item)o; - if( item.HandlesOnMovement ) - m_MoveList.Add( item ); + if(item.HandlesOnMovement) + m_MoveList.Add(item); } } @@ -3337,54 +3337,65 @@ namespace Server Packet[][] cache = m_MovingPacketCache; - for( int i = 0; i < cache.Length; ++i ) + /*for( int i = 0; i < cache.Length; ++i ) for( int j = 0; j < cache[i].Length; ++j ) - Packet.Release( ref cache[i][j] ); + Packet.Release( ref cache[i][j] );*/ - for( int i = 0; i < m_MoveList.Count; ++i ) - { - object o = m_MoveList[i]; + object cacheSync = new object(); +#if Framework_4_0 + Parallel.ForEach(m_MoveClientList, m => { +#else + foreach(Mobile m in m_MoveClientList) { +#endif + NetState ns = m.NetState; - if( o is Mobile ) - { - Mobile m = (Mobile)m_MoveList[i]; - NetState ns = m.NetState; - - if( ns != null && Utility.InUpdateRange( m_Location, m.m_Location ) && m.CanSee( this ) ) - { - Packet p = null; - - if ( ns.StygianAbyss ) { - int noto = Notoriety.Compute( m, this ); + if (ns != null && Utility.InUpdateRange(m_Location, m.m_Location) && m.CanSee(this)) { + if (ns.StygianAbyss) { + Packet p; + int noto = Notoriety.Compute(m, this); + lock (cacheSync) { p = cache[0][noto]; - if( p == null ) - cache[0][noto] = p = Packet.Acquire( new MobileMoving( this, noto ) ); - } else { - int noto = Notoriety.Compute( m, this ); + if (p == null) + cache[0][noto] = p = Packet.Acquire(new MobileMoving(this, noto)); + } + ns.Send(p); + } else { + Packet p; + int noto = Notoriety.Compute(m, this); + lock (cacheSync) { p = cache[1][noto]; - if( p == null ) - cache[1][noto] = p = Packet.Acquire( new MobileMovingOld( this, noto ) ); + if (p == null) + cache[1][noto] = p = Packet.Acquire(new MobileMovingOld(this, noto)); } - - ns.Send( p ); + ns.Send(p); } - - m.OnMovement( this, oldLocation ); } - else if( o is Item ) - { + } +#if Framework_4_0 + ); +#endif + + for (int i = 0; i < cache.Length; ++i) + for (int j = 0; j < cache[i].Length; ++j) + Packet.Release(ref cache[i][j]); + + for( int i = 0; i < m_MoveList.Count; ++i ) { + IEntity o = m_MoveList[i]; + + if(o is Mobile) { + ((Mobile)o).OnMovement( this, oldLocation ); + } else if( o is Item ) { ((Item)o).OnMovement( this, oldLocation ); } } - for( int i = 0; i < cache.Length; ++i ) - for( int j = 0; j < cache[i].Length; ++j ) - Packet.Release( ref cache[i][j] ); - - if( m_MoveList.Count > 0 ) + if (m_MoveList.Count > 0) m_MoveList.Clear(); + + if (m_MoveClientList.Count > 0) + m_MoveClientList.Clear(); } OnAfterMove( oldLocation ); @@ -4731,21 +4742,21 @@ namespace Server return true; } - private void AddSpeechItemsFrom( ArrayList list, Container cont ) + private void AddSpeechItemsFrom(List list, Container cont) { - for( int i = 0; i < cont.Items.Count; ++i ) - { + for(int i = 0; i < cont.Items.Count; ++i) { Item item = cont.Items[i]; - if( item.HandlesOnSpeech ) - list.Add( item ); + if(item.HandlesOnSpeech) + lock (list) + list.Add( item ); - if( item is Container ) - AddSpeechItemsFrom( list, (Container)item ); + if(item is Container) + AddSpeechItemsFrom(list, (Container)item); } } - private class LocationComparer : IComparer + private class LocationComparer : IComparer { private static LocationComparer m_Instance; @@ -4784,12 +4795,9 @@ namespace Server return (x * x) + (y * y) + (z * z); } - public int Compare( object x, object y ) + public int Compare(IPoint3D x, IPoint3D y) { - IPoint3D a = x as IPoint3D; - IPoint3D b = y as IPoint3D; - - return GetDistance( a ) - GetDistance( b ); + return GetDistance(x) - GetDistance(y); } } @@ -4837,8 +4845,8 @@ namespace Server #endregion - private static List m_Hears; - private static ArrayList m_OnSpeech; + private static List m_Hears = new List(); + private static List m_OnSpeech = new List(); public virtual void DoSpeech( string text, int[] keywords, MessageType type, int hue ) { @@ -4882,43 +4890,38 @@ namespace Server if( string.IsNullOrEmpty( text ) ) return; - if( m_Hears == null ) - m_Hears = new List(); - else if( m_Hears.Count > 0 ) - m_Hears.Clear(); - - if( m_OnSpeech == null ) - m_OnSpeech = new ArrayList(); - else if( m_OnSpeech.Count > 0 ) - m_OnSpeech.Clear(); - List hears = m_Hears; - ArrayList onSpeech = m_OnSpeech; + List onSpeech = m_OnSpeech; if( m_Map != null ) { IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, range ); - foreach( object o in eable ) - { - if( o is Mobile ) - { +#if Framework_4_0 + Parallel.ForEach(eable.Cast(), o => { +#else + foreach(IEntity o in eable) { +#endif + if( o is Mobile ) { Mobile heard = (Mobile)o; if( heard.CanSee( this ) && (m_NoSpeechLOS || !heard.Player || heard.InLOS( this )) ) { if( heard.m_NetState != null ) - hears.Add( heard ); + lock (hears) + hears.Add( heard ); if( heard.HandlesOnSpeech( this ) ) - onSpeech.Add( heard ); + lock (onSpeech) + onSpeech.Add( heard ); for( int i = 0; i < heard.Items.Count; ++i ) { Item item = heard.Items[i]; if( item.HandlesOnSpeech ) - onSpeech.Add( item ); + lock (onSpeech) + onSpeech.Add( item ); if( item is Container ) AddSpeechItemsFrom( onSpeech, (Container)item ); @@ -4928,12 +4931,16 @@ namespace Server else if( o is Item ) { if( ((Item)o).HandlesOnSpeech ) - onSpeech.Add( o ); + lock (onSpeech) + onSpeech.Add(o); if( o is Container ) AddSpeechItemsFrom( onSpeech, (Container)o ); } } +#if Framework_4_0 + ); +#endif eable.Free(); @@ -4951,32 +4958,28 @@ namespace Server Packet regp = null; Packet mutp = null; - for( int i = 0; i < hears.Count; ++i ) - { + // TODO: Should this be sorted like onSpeech is below? + + for( int i = 0; i < hears.Count; ++i ) { Mobile heard = hears[i]; - if( mutatedArgs == null || !CheckHearsMutatedSpeech( heard, mutateContext ) ) - { + if( mutatedArgs == null || !CheckHearsMutatedSpeech( heard, mutateContext ) ) { heard.OnSpeech( regArgs ); NetState ns = heard.NetState; - if( ns != null ) - { + if( ns != null ) { if( regp == null ) regp = Packet.Acquire( new UnicodeMessage( m_Serial, Body, type, hue, 3, m_Language, Name, text ) ); ns.Send( regp ); } - } - else - { + } else { heard.OnSpeech( mutatedArgs ); NetState ns = heard.NetState; - if( ns != null ) - { + if( ns != null ) { if( mutp == null ) mutp = Packet.Acquire( new UnicodeMessage( m_Serial, Body, type, hue, 3, m_Language, Name, mutatedText ) ); @@ -4991,26 +4994,28 @@ namespace Server if( onSpeech.Count > 1 ) onSpeech.Sort( LocationComparer.GetInstance( this ) ); - for( int i = 0; i < onSpeech.Count; ++i ) - { - object obj = onSpeech[i]; + for( int i = 0; i < onSpeech.Count; ++i ) { + IEntity obj = onSpeech[i]; - if( obj is Mobile ) - { + if( obj is Mobile ) { Mobile heard = (Mobile)obj; if( mutatedArgs == null || !CheckHearsMutatedSpeech( heard, mutateContext ) ) heard.OnSpeech( regArgs ); else heard.OnSpeech( mutatedArgs ); - } - else - { + } else { Item item = (Item)obj; item.OnSpeech( regArgs ); } } + + if(m_Hears.Count > 0) + m_Hears.Clear(); + + if(m_OnSpeech.Count > 0) + m_OnSpeech.Clear(); } } @@ -10228,12 +10233,12 @@ namespace Server #else Packet[][] cache = m_MovingPacketCache; - if( sendMoving || sendNonlocalMoving || sendHealthbarPoison || sendHealthbarYellow ) + /*if( sendMoving || sendNonlocalMoving || sendHealthbarPoison || sendHealthbarYellow ) { for( int i = 0; i < cache.Length; ++i ) for( int j = 0; j < cache[i].Length; ++j ) Packet.Release( ref cache[i][j] ); - } + }*/ #endif NetState ourState = m.m_NetState; diff --git a/Server/Timer.cs b/Server/Timer.cs index edfcf5493..281283871 100644 --- a/Server/Timer.cs +++ b/Server/Timer.cs @@ -218,7 +218,7 @@ namespace Server public void Free() { lock (m_InstancePool) { - if (m_InstancePool.Count <= 200) // Arbitrary + if (m_InstancePool.Count < 200) // Arbitrary m_InstancePool.Enqueue( this ); } }