From 28baea049cee3370cc698b993aa13fa848523c1e Mon Sep 17 00:00:00 2001 From: Garry Newman Date: Thu, 6 Oct 2016 12:00:08 +0100 Subject: [PATCH] Sped up ServerList.Custom using multiple queries (16 seconds+ to 2 seconds) --- .../Client/Serverlist.cs | 4 +- .../Client/ServerList.Request.cs | 205 ++++++++++-------- Facepunch.Steamworks/Client/ServerList.cs | 7 +- 3 files changed, 119 insertions(+), 97 deletions(-) diff --git a/Facepunch.Steamworks.Test/Client/Serverlist.cs b/Facepunch.Steamworks.Test/Client/Serverlist.cs index 031141f..0322f4a 100644 --- a/Facepunch.Steamworks.Test/Client/Serverlist.cs +++ b/Facepunch.Steamworks.Test/Client/Serverlist.cs @@ -273,7 +273,7 @@ public void CustomList() for ( int i = 0; i < 1000; i++ ) { client.Update(); - System.Threading.Thread.Sleep( 10 ); + System.Threading.Thread.Sleep( 20 ); if ( query.Finished ) break; @@ -284,7 +284,7 @@ public void CustomList() foreach ( var s in query.Responded ) { - Console.WriteLine( s.Name ); + Console.WriteLine( "{0} - {1}", s.AddressString, s.Name ); } query.Dispose(); diff --git a/Facepunch.Steamworks/Client/ServerList.Request.cs b/Facepunch.Steamworks/Client/ServerList.Request.cs index 5f0463e..9f382ba 100644 --- a/Facepunch.Steamworks/Client/ServerList.Request.cs +++ b/Facepunch.Steamworks/Client/ServerList.Request.cs @@ -12,7 +12,77 @@ public partial class ServerList public class Request : IDisposable { internal Client client; - internal IntPtr Id; + + internal List Requests = new List(); + + internal class SubRequest + { + internal IntPtr Request; + internal int Pointer = 0; + internal List WatchList = new List(); + + internal bool Update( ISteamMatchmakingServers servers, Action OnServer, Action OnUpdate ) + { + if ( Request == IntPtr.Zero ) + return true; + + bool changes = false; + + // + // Add any servers we're not watching to our watch list + // + var count = servers.GetServerCount( Request ); + if ( count != Pointer ) + { + for ( int i = Pointer; i < count; i++ ) + { + WatchList.Add( i ); + } + } + Pointer = count; + + // + // Remove any servers that respond successfully + // + WatchList.RemoveAll( x => + { + var info = servers.GetServerDetails( Request, x ); + if ( info.m_bHadSuccessfulResponse ) + { + OnServer( info ); + changes = true; + return true; + } + + return false; + } ); + + // + // If we've finished refreshing + // + if ( servers.IsRefreshing( Request ) == false ) + { + // + // Put any other servers on the 'no response' list + // + WatchList.RemoveAll( x => + { + var info = servers.GetServerDetails( Request, x ); + OnServer( info ); + return true; + } ); + + servers.CancelQuery( Request ); + Request = IntPtr.Zero; + changes = true; + } + + if ( changes && OnUpdate != null ) + OnUpdate(); + + return Request == IntPtr.Zero; + } + } public Action OnUpdate; @@ -43,118 +113,69 @@ internal Request( Client c ) { Dispose(); } - - int lastCount = 0; - - internal List watchlist = new List(); - + internal IEnumerable ServerList { get; set; } - internal int ServerListPointer = 0; - void UpdateCustomQuery() + internal void StartCustomQuery() { if ( ServerList == null ) return; - if ( Id != IntPtr.Zero ) - return; + int blockSize = 16; + int Pointer = 0; - var sublist = ServerList.Skip( ServerListPointer ).Take( 10 ); - - if ( sublist.Count() == 0 ) + while ( true ) { - ServerList = null; - ServerListPointer = 0; - Finished = true; - return; + var sublist = ServerList.Skip( Pointer ).Take( blockSize ); + + if ( sublist.Count() == 0 ) + break; + + Pointer += sublist.Count(); + + var filter = new Filter(); + filter.Add( "or", sublist.Count().ToString() ); + + foreach ( var server in sublist ) + { + filter.Add( "gameaddr", server ); + } + + filter.Start(); + var id = client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, filter.Count, IntPtr.Zero ); + filter.Free(); + + AddRequest( id ); } - ServerListPointer += sublist.Count(); + ServerList = null; + } - var filter = new Filter(); - filter.Add( "or", sublist.Count().ToString() ); - - foreach ( var server in sublist ) - { - filter.Add( "gameaddr", server ); - } - - filter.Start(); - Id = client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, filter.Count, IntPtr.Zero ); - filter.Free(); + internal void AddRequest( IntPtr id ) + { + Requests.Add( new SubRequest() { Request = id } ); } private void Update() { - UpdateCustomQuery(); - - if ( Id == IntPtr.Zero ) + if ( Requests.Count == 0 ) return; - bool changes = false; - - // - // Add any servers we're not watching to our watch list - // - var count = client.native.servers.GetServerCount( Id ); - if ( count != lastCount ) + for( int i=0; i< Requests.Count(); i++ ) { - for ( int i = lastCount; i < count; i++ ) + if ( Requests[i].Update( client.native.servers, OnServer, OnUpdate ) ) { - watchlist.Add( i ); + Requests.RemoveAt( i ); + i--; } - - lastCount = count; } - // - // Remove any servers that respond successfully - // - watchlist.RemoveAll( x => + if ( Requests.Count == 0 ) { - var info = client.native.servers.GetServerDetails( Id, x ); - if ( info.m_bHadSuccessfulResponse ) - { - OnServer( info ); - changes = true; - return true; - } - - return false; - } ); - - // - // If we've finished refreshing - // - if ( client.native.servers.IsRefreshing( Id ) == false ) - { - // - // Put any other servers on the 'no response' list - // - watchlist.RemoveAll( x => - { - var info = client.native.servers.GetServerDetails( Id, x ); - OnServer( info ); - return true; - } ); - - // - // We have more to process - // - if ( ServerList == null ) - { - Finished = true; - client.OnUpdate -= Update; - } - - client.native.servers.CancelQuery( Id ); - Id = IntPtr.Zero; - changes = true; + Finished = true; + client.OnUpdate -= Update; } - - if ( changes && OnUpdate != null) - OnUpdate(); } private void OnServer( gameserveritem_t info ) @@ -180,13 +201,13 @@ public void Dispose() // // Cancel the query if it's still running // - if ( Id != IntPtr.Zero ) + foreach( var subRequest in Requests ) { if ( client.IsValid ) - client.native.servers.CancelQuery( Id ); - - Id = IntPtr.Zero; + client.native.servers.CancelQuery( subRequest.Request ); } + Requests.Clear(); + } } diff --git a/Facepunch.Steamworks/Client/ServerList.cs b/Facepunch.Steamworks/Client/ServerList.cs index 6f81f55..d2d151c 100644 --- a/Facepunch.Steamworks/Client/ServerList.cs +++ b/Facepunch.Steamworks/Client/ServerList.cs @@ -90,7 +90,7 @@ public Request Internet( Filter filter ) filter.Start(); var request = new Request( client ); - request.Id = client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, filter.Count, IntPtr.Zero ); + request.AddRequest( client.native.servers.RequestInternetServerList( client.AppId, filter.NativeArray, filter.Count, IntPtr.Zero ) ); filter.Free(); @@ -101,6 +101,7 @@ public Request Custom( IEnumerable serverList ) { var request = new Request( client ); request.ServerList = serverList; + request.StartCustomQuery(); return request; } @@ -111,7 +112,7 @@ public Request Custom( IEnumerable serverList ) public Request History() { var request = new Request( client ); - request.Id = client.native.servers.RequestHistoryServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero ); + request.AddRequest( client.native.servers.RequestHistoryServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero ) ); return request; } @@ -123,7 +124,7 @@ public Request History() public Request Favourites() { var request = new Request( client ); - request.Id = client.native.servers.RequestFavoritesServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero ); + request.AddRequest( client.native.servers.RequestFavoritesServerList( client.AppId, new IntPtr[] { }, IntPtr.Zero ) ); return request; }