handle speech events with some parallelism

limit pooled enumerables and timerchangeentries to 200 (arbitrary)
dont place disposed items back in the pool
This commit is contained in:
Mark Sturgill 2013-10-14 21:24:09 -07:00
parent 710c600b65
commit 20635cc8ee
3 changed files with 131 additions and 110 deletions

View file

@ -1142,13 +1142,21 @@ namespace Server
m_Enumerator = null; m_Enumerator = null;
} }
lock (m_InstancePool) lock (m_InstancePool) {
if (m_InstancePool.Count < 200) // Arbitrary
m_InstancePool.Enqueue( this ); m_InstancePool.Enqueue( this );
}
} }
public void Dispose() 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 #endregion
@ -1214,8 +1222,10 @@ namespace Server
m_Enumerator = null; m_Enumerator = null;
} }
lock (m_InstancePool) lock (m_InstancePool) {
m_InstancePool.Enqueue( this ); if (m_InstancePool.Count < 200) // Arbitrary
m_InstancePool.Enqueue( this );
}
} }
public TypedEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type ) public TypedEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type )
@ -1364,7 +1374,9 @@ namespace Server
return; return;
lock (m_InstancePool) { lock (m_InstancePool) {
m_InstancePool.Enqueue( this ); if (m_InstancePool.Count < 200) // Arbitrary
m_InstancePool.Enqueue( this );
m_List = null; m_List = null;
} }
} }
@ -1428,8 +1440,10 @@ namespace Server
m_Enumerator = null; m_Enumerator = null;
} }
lock (m_InstancePool) lock (m_InstancePool) {
m_InstancePool.Enqueue( this ); if (m_InstancePool.Count < 200) // Arbitrary
m_InstancePool.Enqueue( this );
}
} }
private ObjectEnumerator( Map map, Rectangle2D bounds ) private ObjectEnumerator( Map map, Rectangle2D bounds )
@ -1567,8 +1581,10 @@ namespace Server
if ( m_Enumerable != null ) if ( m_Enumerable != null )
m_Enumerable.Free(); m_Enumerable.Free();
lock (m_InstancePool) lock (m_InstancePool) {
m_InstancePool.Enqueue( this ); if (m_InstancePool.Count < 200) // Arbitrary
m_InstancePool.Enqueue( this );
}
} }
private SectorEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type ) private SectorEnumerator( Map map, Rectangle2D bounds, SectorEnumeratorType type )

View file

@ -3084,7 +3084,8 @@ namespace Server
private long m_EndQueue; private long m_EndQueue;
private static ArrayList m_MoveList = new ArrayList(); private static List<IEntity> m_MoveList = new List<IEntity>();
private static List<Mobile> m_MoveClientList = new List<Mobile>();
private static AccessLevel m_FwdAccessOverride = AccessLevel.Counselor; private static AccessLevel m_FwdAccessOverride = AccessLevel.Counselor;
private static bool m_FwdEnabled = true; private static bool m_FwdEnabled = true;
@ -3315,21 +3316,20 @@ namespace Server
{ {
IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, Core.GlobalMaxUpdateRange ); IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, Core.GlobalMaxUpdateRange );
foreach( object o in eable ) foreach(IEntity o in eable) {
{ if(o == this)
if( o == this )
continue; continue;
if( o is Mobile ) if(o is Mobile) {
{ Mobile mob = o as Mobile;
m_MoveList.Add( o ); if (mob.NetState != null)
} m_MoveClientList.Add(mob);
else if( o is Item ) m_MoveList.Add(o);
{ } else if(o is Item) {
Item item = (Item)o; Item item = (Item)o;
if( item.HandlesOnMovement ) if(item.HandlesOnMovement)
m_MoveList.Add( item ); m_MoveList.Add(item);
} }
} }
@ -3337,54 +3337,65 @@ namespace Server
Packet[][] cache = m_MovingPacketCache; 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 ) 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 cacheSync = new object();
{ #if Framework_4_0
object o = m_MoveList[i]; Parallel.ForEach(m_MoveClientList, m => {
#else
foreach(Mobile m in m_MoveClientList) {
#endif
NetState ns = m.NetState;
if( o is Mobile ) if (ns != null && Utility.InUpdateRange(m_Location, m.m_Location) && m.CanSee(this)) {
{ if (ns.StygianAbyss) {
Mobile m = (Mobile)m_MoveList[i]; Packet p;
NetState ns = m.NetState; int noto = Notoriety.Compute(m, this);
lock (cacheSync) {
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 );
p = cache[0][noto]; p = cache[0][noto];
if( p == null ) if (p == null)
cache[0][noto] = p = Packet.Acquire( new MobileMoving( this, noto ) ); cache[0][noto] = p = Packet.Acquire(new MobileMoving(this, noto));
} else { }
int noto = Notoriety.Compute( m, this ); ns.Send(p);
} else {
Packet p;
int noto = Notoriety.Compute(m, this);
lock (cacheSync) {
p = cache[1][noto]; p = cache[1][noto];
if( p == null ) if (p == null)
cache[1][noto] = p = Packet.Acquire( new MobileMovingOld( this, noto ) ); 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 ); ((Item)o).OnMovement( this, oldLocation );
} }
} }
for( int i = 0; i < cache.Length; ++i ) if (m_MoveList.Count > 0)
for( int j = 0; j < cache[i].Length; ++j )
Packet.Release( ref cache[i][j] );
if( m_MoveList.Count > 0 )
m_MoveList.Clear(); m_MoveList.Clear();
if (m_MoveClientList.Count > 0)
m_MoveClientList.Clear();
} }
OnAfterMove( oldLocation ); OnAfterMove( oldLocation );
@ -4731,21 +4742,21 @@ namespace Server
return true; return true;
} }
private void AddSpeechItemsFrom( ArrayList list, Container cont ) private void AddSpeechItemsFrom(List<IEntity> 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]; Item item = cont.Items[i];
if( item.HandlesOnSpeech ) if(item.HandlesOnSpeech)
list.Add( item ); lock (list)
list.Add( item );
if( item is Container ) if(item is Container)
AddSpeechItemsFrom( list, (Container)item ); AddSpeechItemsFrom(list, (Container)item);
} }
} }
private class LocationComparer : IComparer private class LocationComparer : IComparer<IPoint3D>
{ {
private static LocationComparer m_Instance; private static LocationComparer m_Instance;
@ -4784,12 +4795,9 @@ namespace Server
return (x * x) + (y * y) + (z * z); 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; return GetDistance(x) - GetDistance(y);
IPoint3D b = y as IPoint3D;
return GetDistance( a ) - GetDistance( b );
} }
} }
@ -4837,8 +4845,8 @@ namespace Server
#endregion #endregion
private static List<Mobile> m_Hears; private static List<Mobile> m_Hears = new List<Mobile>();
private static ArrayList m_OnSpeech; private static List<IEntity> m_OnSpeech = new List<IEntity>();
public virtual void DoSpeech( string text, int[] keywords, MessageType type, int hue ) public virtual void DoSpeech( string text, int[] keywords, MessageType type, int hue )
{ {
@ -4882,43 +4890,38 @@ namespace Server
if( string.IsNullOrEmpty( text ) ) if( string.IsNullOrEmpty( text ) )
return; return;
if( m_Hears == null )
m_Hears = new List<Mobile>();
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<Mobile> hears = m_Hears; List<Mobile> hears = m_Hears;
ArrayList onSpeech = m_OnSpeech; List<IEntity> onSpeech = m_OnSpeech;
if( m_Map != null ) if( m_Map != null )
{ {
IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, range ); IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, range );
foreach( object o in eable ) #if Framework_4_0
{ Parallel.ForEach(eable.Cast<IEntity>(), o => {
if( o is Mobile ) #else
{ foreach(IEntity o in eable) {
#endif
if( o is Mobile ) {
Mobile heard = (Mobile)o; Mobile heard = (Mobile)o;
if( heard.CanSee( this ) && (m_NoSpeechLOS || !heard.Player || heard.InLOS( this )) ) if( heard.CanSee( this ) && (m_NoSpeechLOS || !heard.Player || heard.InLOS( this )) )
{ {
if( heard.m_NetState != null ) if( heard.m_NetState != null )
hears.Add( heard ); lock (hears)
hears.Add( heard );
if( heard.HandlesOnSpeech( this ) ) if( heard.HandlesOnSpeech( this ) )
onSpeech.Add( heard ); lock (onSpeech)
onSpeech.Add( heard );
for( int i = 0; i < heard.Items.Count; ++i ) for( int i = 0; i < heard.Items.Count; ++i )
{ {
Item item = heard.Items[i]; Item item = heard.Items[i];
if( item.HandlesOnSpeech ) if( item.HandlesOnSpeech )
onSpeech.Add( item ); lock (onSpeech)
onSpeech.Add( item );
if( item is Container ) if( item is Container )
AddSpeechItemsFrom( onSpeech, (Container)item ); AddSpeechItemsFrom( onSpeech, (Container)item );
@ -4928,12 +4931,16 @@ namespace Server
else if( o is Item ) else if( o is Item )
{ {
if( ((Item)o).HandlesOnSpeech ) if( ((Item)o).HandlesOnSpeech )
onSpeech.Add( o ); lock (onSpeech)
onSpeech.Add(o);
if( o is Container ) if( o is Container )
AddSpeechItemsFrom( onSpeech, (Container)o ); AddSpeechItemsFrom( onSpeech, (Container)o );
} }
} }
#if Framework_4_0
);
#endif
eable.Free(); eable.Free();
@ -4951,32 +4958,28 @@ namespace Server
Packet regp = null; Packet regp = null;
Packet mutp = 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]; Mobile heard = hears[i];
if( mutatedArgs == null || !CheckHearsMutatedSpeech( heard, mutateContext ) ) if( mutatedArgs == null || !CheckHearsMutatedSpeech( heard, mutateContext ) ) {
{
heard.OnSpeech( regArgs ); heard.OnSpeech( regArgs );
NetState ns = heard.NetState; NetState ns = heard.NetState;
if( ns != null ) if( ns != null ) {
{
if( regp == null ) if( regp == null )
regp = Packet.Acquire( new UnicodeMessage( m_Serial, Body, type, hue, 3, m_Language, Name, text ) ); regp = Packet.Acquire( new UnicodeMessage( m_Serial, Body, type, hue, 3, m_Language, Name, text ) );
ns.Send( regp ); ns.Send( regp );
} }
} } else {
else
{
heard.OnSpeech( mutatedArgs ); heard.OnSpeech( mutatedArgs );
NetState ns = heard.NetState; NetState ns = heard.NetState;
if( ns != null ) if( ns != null ) {
{
if( mutp == null ) if( mutp == null )
mutp = Packet.Acquire( new UnicodeMessage( m_Serial, Body, type, hue, 3, m_Language, Name, mutatedText ) ); 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 ) if( onSpeech.Count > 1 )
onSpeech.Sort( LocationComparer.GetInstance( this ) ); onSpeech.Sort( LocationComparer.GetInstance( this ) );
for( int i = 0; i < onSpeech.Count; ++i ) for( int i = 0; i < onSpeech.Count; ++i ) {
{ IEntity obj = onSpeech[i];
object obj = onSpeech[i];
if( obj is Mobile ) if( obj is Mobile ) {
{
Mobile heard = (Mobile)obj; Mobile heard = (Mobile)obj;
if( mutatedArgs == null || !CheckHearsMutatedSpeech( heard, mutateContext ) ) if( mutatedArgs == null || !CheckHearsMutatedSpeech( heard, mutateContext ) )
heard.OnSpeech( regArgs ); heard.OnSpeech( regArgs );
else else
heard.OnSpeech( mutatedArgs ); heard.OnSpeech( mutatedArgs );
} } else {
else
{
Item item = (Item)obj; Item item = (Item)obj;
item.OnSpeech( regArgs ); 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 #else
Packet[][] cache = m_MovingPacketCache; Packet[][] cache = m_MovingPacketCache;
if( sendMoving || sendNonlocalMoving || sendHealthbarPoison || sendHealthbarYellow ) /*if( sendMoving || sendNonlocalMoving || sendHealthbarPoison || sendHealthbarYellow )
{ {
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 ) for( int j = 0; j < cache[i].Length; ++j )
Packet.Release( ref cache[i][j] ); Packet.Release( ref cache[i][j] );
} }*/
#endif #endif
NetState ourState = m.m_NetState; NetState ourState = m.m_NetState;

View file

@ -218,7 +218,7 @@ namespace Server
public void Free() public void Free()
{ {
lock (m_InstancePool) { lock (m_InstancePool) {
if (m_InstancePool.Count <= 200) // Arbitrary if (m_InstancePool.Count < 200) // Arbitrary
m_InstancePool.Enqueue( this ); m_InstancePool.Enqueue( this );
} }
} }