From fe1f40f92722c647cbae6c32d3ecf0eab194d11d Mon Sep 17 00:00:00 2001 From: Mark Sturgill Date: Thu, 17 Oct 2013 20:25:11 -0700 Subject: [PATCH] parallelization isn't worth it unless we can reasonably estimate our workload before initiating implement double checked locking change active solution to x64 map thread-safety --- RunUO.sln | 3 +- Server/Item.cs | 74 ++++++++++++++++------- Server/Map.cs | 3 +- Server/Mobile.cs | 117 ++++++++++++++----------------------- Server/Network/NetState.cs | 33 ++++++----- Server/Timer.cs | 29 +-------- 6 files changed, 121 insertions(+), 138 deletions(-) diff --git a/RunUO.sln b/RunUO.sln index ac2fd394f..b83979d40 100644 --- a/RunUO.sln +++ b/RunUO.sln @@ -232,8 +232,7 @@ Global {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|Any CPU.ActiveCfg = Debug|x86 {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|Mixed Platforms.Build.0 = Debug|x86 - {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x64.ActiveCfg = Debug|x64 - {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x64.Build.0 = Debug|x64 + {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x64.ActiveCfg = Debug|x86 {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x86.ActiveCfg = Debug|x86 {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Debug|x86.Build.0 = Debug|x86 {0B33CEEB-88E1-49A6-8D7D-AF6A5A357087}.Release|Any CPU.ActiveCfg = Release|x86 diff --git a/Server/Item.cs b/Server/Item.cs index d29609f6f..7c8555d23 100644 --- a/Server/Item.cs +++ b/Server/Item.cs @@ -1615,10 +1615,15 @@ namespace Server { get { - lock (_rpl) { - if ( m_RemovePacket == null ) { - m_RemovePacket = new RemoveItem( this ); - m_RemovePacket.SetStatic(); + if (m_RemovePacket == null) + { + lock (_rpl) + { + if (m_RemovePacket == null) + { + m_RemovePacket = new RemoveItem(this); + m_RemovePacket.SetStatic(); + } } } @@ -1632,10 +1637,15 @@ namespace Server { get { - lock (_opll) { - if ( m_OPLPacket == null ) { - m_OPLPacket = new OPLInfo( PropertyList ); - m_OPLPacket.SetStatic(); + if (m_OPLPacket == null) + { + lock (_opll) + { + if (m_OPLPacket == null) + { + m_OPLPacket = new OPLInfo(PropertyList); + m_OPLPacket.SetStatic(); + } } } @@ -1723,10 +1733,15 @@ namespace Server // - Packet Flags // - Direction - lock (_wpl) { - if ( m_WorldPacket == null ) { - m_WorldPacket = new WorldItem( this ); - m_WorldPacket.SetStatic(); + if (m_WorldPacket == null) + { + lock (_wpl) + { + if (m_WorldPacket == null) + { + m_WorldPacket = new WorldItem(this); + m_WorldPacket.SetStatic(); + } } } @@ -1746,10 +1761,15 @@ namespace Server // - Packet Flags // - Direction - lock (_wplsa) { - if ( m_WorldPacketSA == null ) { - m_WorldPacketSA = new WorldItemSA( this ); - m_WorldPacketSA.SetStatic(); + if (m_WorldPacketSA == null) + { + lock (_wplsa) + { + if (m_WorldPacketSA == null) + { + m_WorldPacketSA = new WorldItemSA(this); + m_WorldPacketSA.SetStatic(); + } } } @@ -1769,10 +1789,15 @@ namespace Server // - Packet Flags // - Direction - lock (_wplhs) { - if ( m_WorldPacketHS == null ) { - m_WorldPacketHS = new WorldItemHS( this ); - m_WorldPacketHS.SetStatic(); + if (m_WorldPacketHS == null) + { + lock (_wplhs) + { + if (m_WorldPacketHS == null) + { + m_WorldPacketHS = new WorldItemHS(this); + m_WorldPacketHS.SetStatic(); + } } } @@ -3282,8 +3307,15 @@ namespace Server { #if Framework_4_0 _processing = true; - Parallel.ForEach( m_DeltaQueue, i => i.ProcessDelta() ); + + if (m_DeltaQueue.Count >= 64) { + Parallel.ForEach(m_DeltaQueue, i => i.ProcessDelta()); + } else { + for (int i = 0; i < m_DeltaQueue.Count; i++) m_DeltaQueue[i].ProcessDelta(); + } + m_DeltaQueue.Clear(); + _processing = false; #else int count = m_DeltaQueue.Count; diff --git a/Server/Map.cs b/Server/Map.cs index 1a8d717f5..b8837713e 100644 --- a/Server/Map.cs +++ b/Server/Map.cs @@ -1845,7 +1845,7 @@ namespace Server int height; bool found; Point3D p; - Point3DList path = m_PathList; + Point3DList path = new Point3DList(); TileFlag flags; if( org == dest ) @@ -2087,7 +2087,6 @@ namespace Server set { m_InvalidLandTiles = value; } } - private static Point3DList m_PathList = new Point3DList(); public int CompareTo( Map other ) { if ( other == null ) diff --git a/Server/Mobile.cs b/Server/Mobile.cs index 7b8a53ec7..a5fb2cdb9 100644 --- a/Server/Mobile.cs +++ b/Server/Mobile.cs @@ -3317,41 +3317,31 @@ namespace Server for( int j = 0; j < cache[i].Length; ++j ) Packet.Release( ref cache[i][j] );*/ - 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 (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]; + p = cache[0][noto]; + + if (p == null) + cache[0][noto] = p = Packet.Acquire(new MobileMoving(this, noto)); - 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]; + 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); } } } -#if Framework_4_0 - ); -#endif for (int i = 0; i < cache.Length; ++i) for (int j = 0; j < cache[i].Length; ++j) @@ -4692,8 +4682,7 @@ namespace Server Item item = cont.Items[i]; if(item.HandlesOnSpeech) - lock (list) - list.Add( item ); + list.Add( item ); if(item is Container) AddSpeechItemsFrom(list, (Container)item); @@ -4841,31 +4830,24 @@ namespace Server { IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, range ); -#if Framework_4_0 - Parallel.ForEach(eable, 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 ) - lock (hears) - hears.Add( heard ); + hears.Add( heard ); if( heard.HandlesOnSpeech( this ) ) - lock (onSpeech) - onSpeech.Add( heard ); + onSpeech.Add( heard ); for( int i = 0; i < heard.Items.Count; ++i ) { Item item = heard.Items[i]; if( item.HandlesOnSpeech ) - lock (onSpeech) - onSpeech.Add( item ); + onSpeech.Add( item ); if( item is Container ) AddSpeechItemsFrom( onSpeech, (Container)item ); @@ -4875,16 +4857,12 @@ namespace Server else if( o is Item ) { if( ((Item)o).HandlesOnSpeech ) - lock (onSpeech) - onSpeech.Add(o); + onSpeech.Add(o); if( o is Container ) AddSpeechItemsFrom( onSpeech, (Container)o ); } } -#if Framework_4_0 - ); -#endif eable.Free(); @@ -6576,11 +6554,8 @@ namespace Server if( m_Map != null && ns != null ) { IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, Core.GlobalMaxUpdateRange ); -#if Framework_4_0 - Parallel.ForEach(eable, o => { -#else + foreach ( IEntity o in eable ) { -#endif if( o is Mobile ) { Mobile m = (Mobile)o; @@ -6593,9 +6568,6 @@ namespace Server ns.Send( item.RemovePacket ); } } -#if Framework_4_0 - ); -#endif eable.Free(); } @@ -6781,11 +6753,8 @@ namespace Server if( m_Map != null && ns != null ) { IPooledEnumerable eable = m_Map.GetObjectsInRange( m_Location, Core.GlobalMaxUpdateRange ); -#if Framework_4_0 - Parallel.ForEach(eable, o => { -#else + foreach ( IEntity o in eable ) { -#endif if( o is Item ) { Item item = (Item)o; @@ -6819,9 +6788,6 @@ namespace Server } } } -#if Framework_4_0 - ); -#endif eable.Free(); } @@ -8850,10 +8816,15 @@ namespace Server { get { - lock (rpLock) { - if (m_RemovePacket == null) { - m_RemovePacket = new RemoveMobile(this); - m_RemovePacket.SetStatic(); + if (m_RemovePacket == null) + { + lock (rpLock) + { + if (m_RemovePacket == null) + { + m_RemovePacket = new RemoveMobile(this); + m_RemovePacket.SetStatic(); + } } } @@ -8868,10 +8839,15 @@ namespace Server { get { - lock (oplLock) { - if( m_OPLPacket == null ) { - m_OPLPacket = new OPLInfo( PropertyList ); - m_OPLPacket.SetStatic(); + if (m_OPLPacket == null) + { + lock (oplLock) + { + if (m_OPLPacket == null) + { + m_OPLPacket = new OPLInfo(PropertyList); + m_OPLPacket.SetStatic(); + } } } @@ -9109,11 +9085,8 @@ namespace Server IPooledEnumerable eeable = map.GetObjectsInRange( newLocation, Core.GlobalMaxUpdateRange ); // We are attached to a client, so it's a bit more complex. We need to send new items and people to ourself, and ourself to other clients -#if Framework_4_0 - Parallel.ForEach(eeable, o => { -#else + foreach ( IEntity o in eeable ) { -#endif if( o is Item ) { Item item = (Item)o; @@ -9129,11 +9102,8 @@ namespace Server Mobile m = (Mobile)o; if( !Utility.InUpdateRange( newLocation, m.m_Location ) ) -#if Framework_4_0 - return; -#else continue; -#endif + bool inOldRange = Utility.InUpdateRange( oldLocation, m.m_Location ); if( m.m_NetState != null && ( ( isTeleport && ( !m.m_NetState.HighSeas || !m_NoMoveHS ) ) || !inOldRange ) && m.CanSee( this ) ) @@ -9185,9 +9155,6 @@ namespace Server } } } -#if Framework_4_0 - ); -#endif eeable.Free(); } @@ -10360,11 +10327,17 @@ namespace Server { #if Framework_4_0 _processing = true; - Parallel.ForEach( m_DeltaQueue, m => m.ProcessDelta() ); - m_DeltaQueue.Clear(); + + if (m_DeltaQueue.Count >= 64) { + Parallel.ForEach(m_DeltaQueue, m => m.ProcessDelta()); + m_DeltaQueue.Clear(); + } else { + while (m_DeltaQueueR.Count > 0) m_DeltaQueueR.Dequeue().ProcessDelta(); + } + _processing = false; - Parallel.ForEach( m_DeltaQueueR, m => m.ProcessDelta() ); - m_DeltaQueueR.Clear(); + + while (m_DeltaQueueR.Count > 0) m_DeltaQueueR.Dequeue().ProcessDelta(); #else int count = m_DeltaQueue.Count; int index = 0; diff --git a/Server/Network/NetState.cs b/Server/Network/NetState.cs index 4549800d9..70d57cebb 100644 --- a/Server/Network/NetState.cs +++ b/Server/Network/NetState.cs @@ -1052,12 +1052,13 @@ namespace Server.Network { public static void FlushAll() { #if Framework_4_0 - Parallel.ForEach( m_Instances, ns => ns.Flush() ); -#else - for ( int i = 0; i < m_Instances.Count; ++i ) { - m_Instances[i].Flush(); - } + if (m_Instances.Count >= 128) + Parallel.ForEach(m_Instances, ns => ns.Flush()); + else #endif + for ( int i = 0; i < m_Instances.Count; ++i ) { + m_Instances[i].Flush(); + } } private static int m_CoalesceSleep = -1; @@ -1073,18 +1074,18 @@ namespace Server.Network { private long m_NextCheckActivity; - public bool CheckAlive() { + public void CheckAlive(long curTicks) { if ( m_Socket == null ) - return false; + return; - if (m_NextCheckActivity - Core.TickCount >= 0) { - return true; + if (m_NextCheckActivity - curTicks >= 0) { + return; } Console.WriteLine( "Client: {0}: Disconnecting due to inactivity...", this ); Dispose(); - return false; + return; } public static void TraceException( Exception ex ) { @@ -1172,13 +1173,15 @@ namespace Server.Network { public static void CheckAllAlive() { try { + long curTicks = Core.TickCount; #if Framework_4_0 - Parallel.ForEach( m_Instances, ns => ns.CheckAlive() ); -#else - for ( int i = 0; i < m_Instances.Count; ++i ) { - m_Instances[i].CheckAlive(); - } + if (m_Instances.Count >= 512) + Parallel.ForEach(m_Instances, ns => ns.CheckAlive(curTicks)); + else #endif + for ( int i = 0; i < m_Instances.Count; ++i ) { + m_Instances[i].CheckAlive(curTicks); + } } catch ( Exception ex ) { TraceException( ex ); } diff --git a/Server/Timer.cs b/Server/Timer.cs index 281283871..07bd95f77 100644 --- a/Server/Timer.cs +++ b/Server/Timer.cs @@ -276,31 +276,8 @@ namespace Server private static void ProcessChanged() { lock (m_Changed) { -#if Framework_4_0 - Parallel.ForEach(m_Changed.Values, tce => { - Timer timer = tce.m_Timer; - int newIndex = tce.m_NewIndex; + long curTicks = Core.TickCount; - if (timer.m_List != null) - lock (timer.m_List) - timer.m_List.Remove(timer); - - if (tce.m_IsAdd) { - timer.m_Next = Core.TickCount + timer.m_Delay; - timer.m_Index = 0; - } - - if (newIndex >= 0) { - timer.m_List = m_Timers[newIndex]; - lock (timer.m_List) - timer.m_List.Add(timer); - } else { - timer.m_List = null; - } - - tce.Free(); - }); -#else foreach (TimerChangeEntry tce in m_Changed.Values) { Timer timer = tce.m_Timer; int newIndex = tce.m_NewIndex; @@ -309,7 +286,7 @@ namespace Server timer.m_List.Remove(timer); if (tce.m_IsAdd) { - timer.m_Next = Core.TickCount + timer.m_Delay; + timer.m_Next = curTicks + timer.m_Delay; timer.m_Index = 0; } @@ -322,7 +299,7 @@ namespace Server tce.Free(); } -#endif + m_Changed.Clear(); } }