Filter controller performance improvements (#229)

* Removed perfomance impacting code from filter generation

* Minor pagination fixes
This commit is contained in:
Michael Green
2023-12-13 13:36:10 +11:00
committed by GitHub
parent 789ec7fc17
commit 128bbcc1df
9 changed files with 149 additions and 184 deletions

View File

@@ -10,6 +10,7 @@ using gaseous_server.Controllers;
using gaseous_server.Models; using gaseous_server.Models;
using IGDB.Models; using IGDB.Models;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace gaseous_server.Classes namespace gaseous_server.Classes
@@ -220,7 +221,10 @@ namespace gaseous_server.Classes
} else { } else {
// get all platforms to pull from // get all platforms to pull from
Dictionary<string, object> FilterDict = Filters.Filter(AgeRatings.AgeGroups.AgeRestrictionGroupings.Adult, true); Dictionary<string, object> FilterDict = Filters.Filter(AgeRatings.AgeGroups.AgeRestrictionGroupings.Adult, true);
platforms.AddRange((List<Filters.FilterPlatform>)FilterDict["platforms"]); List<Classes.Filters.FilterItem> filteredPlatforms = (List<Classes.Filters.FilterItem>)FilterDict["platforms"];
foreach (Filters.FilterItem filterItem in filteredPlatforms) {
platforms.Add(Platforms.GetPlatform(filterItem.Id));
}
} }
// build collection // build collection

View File

@@ -14,7 +14,7 @@ namespace gaseous_server.Classes
Dictionary<string, object> FilterSet = new Dictionary<string, object>(); Dictionary<string, object> FilterSet = new Dictionary<string, object>();
// platforms // platforms
List<FilterPlatform> platforms = new List<FilterPlatform>(); List<FilterItem> platforms = new List<FilterItem>();
string ageRestriction_Platform = "Game.AgeGroupId <= " + (int)MaximumAgeRestriction; string ageRestriction_Platform = "Game.AgeGroupId <= " + (int)MaximumAgeRestriction;
string ageRestriction_Generic = "view_Games.AgeGroupId <= " + (int)MaximumAgeRestriction; string ageRestriction_Generic = "view_Games.AgeGroupId <= " + (int)MaximumAgeRestriction;
@@ -30,57 +30,52 @@ namespace gaseous_server.Classes
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
FilterPlatform platformItem = new FilterPlatform(Classes.Metadata.Platforms.GetPlatform((long)dr["id"])); FilterItem platformItem = new FilterItem(dr);
platformItem.GameCount = (int)(long)dr["GameCount"];
platforms.Add(platformItem); platforms.Add(platformItem);
} }
FilterSet.Add("platforms", platforms); FilterSet.Add("platforms", platforms);
// genres // genres
List<FilterGenre> genres = new List<FilterGenre>(); List<FilterItem> genres = new List<FilterItem>();
dbResponse = GetGenericFilterItem(db, "Genre", ageRestriction_Generic); dbResponse = GetGenericFilterItem(db, "Genre", ageRestriction_Generic);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
FilterGenre genreItem = new FilterGenre(Classes.Metadata.Genres.GetGenres((long)dr["id"])); FilterItem genreItem = new FilterItem(dr);
genreItem.GameCount = (int)(long)dr["GameCount"];
genres.Add(genreItem); genres.Add(genreItem);
} }
FilterSet.Add("genres", genres); FilterSet.Add("genres", genres);
// game modes // game modes
List<FilterGameMode> gameModes = new List<FilterGameMode>(); List<FilterItem> gameModes = new List<FilterItem>();
dbResponse = GetGenericFilterItem(db, "GameMode", ageRestriction_Generic); dbResponse = GetGenericFilterItem(db, "GameMode", ageRestriction_Generic);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
FilterGameMode gameModeItem = new FilterGameMode(Classes.Metadata.GameModes.GetGame_Modes((long)dr["id"])); FilterItem gameModeItem = new FilterItem(dr);
gameModeItem.GameCount = (int)(long)dr["GameCount"];
gameModes.Add(gameModeItem); gameModes.Add(gameModeItem);
} }
FilterSet.Add("gamemodes", gameModes); FilterSet.Add("gamemodes", gameModes);
// player perspectives // player perspectives
List<FilterPlayerPerspective> playerPerspectives = new List<FilterPlayerPerspective>(); List<FilterItem> playerPerspectives = new List<FilterItem>();
dbResponse = GetGenericFilterItem(db, "PlayerPerspective", ageRestriction_Generic); dbResponse = GetGenericFilterItem(db, "PlayerPerspective", ageRestriction_Generic);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
FilterPlayerPerspective playerPerspectiveItem = new FilterPlayerPerspective(Classes.Metadata.PlayerPerspectives.GetGame_PlayerPerspectives((long)dr["id"])); FilterItem playerPerspectiveItem = new FilterItem(dr);
playerPerspectiveItem.GameCount = (int)(long)dr["GameCount"];
playerPerspectives.Add(playerPerspectiveItem); playerPerspectives.Add(playerPerspectiveItem);
} }
FilterSet.Add("playerperspectives", playerPerspectives); FilterSet.Add("playerperspectives", playerPerspectives);
// themes // themes
List<FilterTheme> themes = new List<FilterTheme>(); List<FilterItem> themes = new List<FilterItem>();
dbResponse = GetGenericFilterItem(db, "Theme", ageRestriction_Generic); dbResponse = GetGenericFilterItem(db, "Theme", ageRestriction_Generic);
foreach (DataRow dr in dbResponse.Rows) foreach (DataRow dr in dbResponse.Rows)
{ {
FilterTheme themeItem = new FilterTheme(Classes.Metadata.Themes.GetGame_Themes((long)dr["id"])); FilterItem themeItem = new FilterItem(dr);
themeItem.GameCount = (int)(long)dr["GameCount"];
themes.Add(themeItem); themes.Add(themeItem);
} }
FilterSet.Add("themes", themes); FilterSet.Add("themes", themes);
@@ -120,87 +115,18 @@ namespace gaseous_server.Classes
return dbResponse; return dbResponse;
} }
public class FilterPlatform : IGDB.Models.Platform public class FilterItem
{ {
public FilterPlatform(Platform obj) public FilterItem(DataRow dr)
{ {
var properties = obj.GetType().GetProperties(); this.Id = (long)dr["Id"];
foreach (var prop in properties) this.Name = (string)dr["Name"];
{ this.GameCount = (int)(long)dr["GameCount"];
if (prop.GetGetMethod() != null)
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
}
}
} }
public int GameCount { get; set; } public long Id { get; set; }
}
public class FilterGenre : IGDB.Models.Genre public string Name { get; set; }
{
public FilterGenre(Genre obj)
{
var properties = obj.GetType().GetProperties();
foreach (var prop in properties)
{
if (prop.GetGetMethod() != null)
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
}
}
}
public int GameCount { get; set; }
}
public class FilterGameMode : IGDB.Models.GameMode
{
public FilterGameMode(GameMode obj)
{
var properties = obj.GetType().GetProperties();
foreach (var prop in properties)
{
if (prop.GetGetMethod() != null)
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
}
}
}
public int GameCount { get; set; }
}
public class FilterPlayerPerspective : IGDB.Models.PlayerPerspective
{
public FilterPlayerPerspective(PlayerPerspective obj)
{
var properties = obj.GetType().GetProperties();
foreach (var prop in properties)
{
if (prop.GetGetMethod() != null)
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
}
}
}
public int GameCount { get; set; }
}
public class FilterTheme : IGDB.Models.Theme
{
public FilterTheme(Theme obj)
{
var properties = obj.GetType().GetProperties();
foreach (var prop in properties)
{
if (prop.GetGetMethod() != null)
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(obj));
}
}
}
public int GameCount { get; set; } public int GameCount { get; set; }
} }

View File

@@ -16,32 +16,32 @@ namespace gaseous_server.Classes.Metadata
Expired Expired
} }
private static Dictionary<string, MemoryCacheObject> ObjectCache = new Dictionary<string, MemoryCacheObject>(); //private static Dictionary<string, MemoryCacheObject> ObjectCache = new Dictionary<string, MemoryCacheObject>();
public static CacheStatus GetCacheStatus(string Endpoint, string Slug) public static CacheStatus GetCacheStatus(string Endpoint, string Slug)
{ {
CacheClean(); // CacheClean();
if (ObjectCache.ContainsKey(Endpoint + Slug)) // if (ObjectCache.ContainsKey(Endpoint + Slug))
{ // {
return CacheStatus.Current; // return CacheStatus.Current;
} // }
else // else
{ // {
return _GetCacheStatus(Endpoint, "slug", Slug); return _GetCacheStatus(Endpoint, "slug", Slug);
} // }
} }
public static CacheStatus GetCacheStatus(string Endpoint, long Id) public static CacheStatus GetCacheStatus(string Endpoint, long Id)
{ {
CacheClean(); // CacheClean();
if (ObjectCache.ContainsKey(Endpoint + Id)) // if (ObjectCache.ContainsKey(Endpoint + Id))
{ // {
return CacheStatus.Current; // return CacheStatus.Current;
} // }
else // else
{ // {
return _GetCacheStatus(Endpoint, "id", Id); return _GetCacheStatus(Endpoint, "id", Id);
} // }
} }
public static CacheStatus GetCacheStatus(DataRow Row) public static CacheStatus GetCacheStatus(DataRow Row)
@@ -185,20 +185,20 @@ namespace gaseous_server.Classes.Metadata
{ {
string Endpoint = EndpointType.GetType().Name; string Endpoint = EndpointType.GetType().Name;
if (ObjectCache.ContainsKey(Endpoint + SearchValue)) // if (ObjectCache.ContainsKey(Endpoint + SearchValue))
{ // {
MemoryCacheObject cacheObject = ObjectCache[Endpoint + SearchValue]; // MemoryCacheObject cacheObject = ObjectCache[Endpoint + SearchValue];
if (cacheObject.ExpiryTime < DateTime.UtcNow) // if (cacheObject.ExpiryTime < DateTime.UtcNow)
{ // {
// object has expired, remove it // // object has expired, remove it
ObjectCache.Remove(Endpoint + SearchValue); // ObjectCache.Remove(Endpoint + SearchValue);
} // }
else // else
{ // {
// object is valid, return it // // object is valid, return it
return (T)cacheObject.Object; // return (T)cacheObject.Object;
} // }
} // }
Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString); Database db = new Database(Database.databaseType.MySql, Config.DatabaseConfiguration.ConnectionString);
@@ -218,19 +218,19 @@ namespace gaseous_server.Classes.Metadata
{ {
DataRow dataRow = dt.Rows[0]; DataRow dataRow = dt.Rows[0];
object returnObject = BuildCacheObject<T>(EndpointType, dataRow); object returnObject = BuildCacheObject<T>(EndpointType, dataRow);
try { // try {
if (!ObjectCache.ContainsKey(Endpoint + SearchValue)) // if (!ObjectCache.ContainsKey(Endpoint + SearchValue))
{ // {
ObjectCache.Add(Endpoint + SearchValue, new MemoryCacheObject{ // ObjectCache.Add(Endpoint + SearchValue, new MemoryCacheObject{
Object = returnObject // Object = returnObject
}); // });
} // }
} // }
catch // catch
{ // {
// unable add item to cache // // unable add item to cache
ObjectCache.Clear(); // ObjectCache.Clear();
} // }
return (T)returnObject; return (T)returnObject;
} }
} }
@@ -470,28 +470,28 @@ namespace gaseous_server.Classes.Metadata
} }
} }
private static void CacheClean() // private static void CacheClean()
{ // {
try // try
{ // {
if (ObjectCache == null) // if (ObjectCache == null)
{ // {
ObjectCache = new Dictionary<string, MemoryCacheObject>(); // ObjectCache = new Dictionary<string, MemoryCacheObject>();
} // }
Dictionary<string, MemoryCacheObject> workCache = ObjectCache; // Dictionary<string, MemoryCacheObject> workCache = ObjectCache;
foreach (KeyValuePair<string, MemoryCacheObject> objectCache in workCache) // foreach (KeyValuePair<string, MemoryCacheObject> objectCache in workCache)
{ // {
if (objectCache.Value.ExpiryTime < DateTime.UtcNow) // if (objectCache.Value.ExpiryTime < DateTime.UtcNow)
{ // {
ObjectCache.Remove(objectCache.Key); // ObjectCache.Remove(objectCache.Key);
} // }
} // }
} // }
catch // catch
{ // {
ObjectCache = new Dictionary<string, MemoryCacheObject>(); // ObjectCache = new Dictionary<string, MemoryCacheObject>();
} // }
} // }
private class MemoryCacheObject private class MemoryCacheObject
{ {

View File

@@ -450,26 +450,14 @@ namespace gaseous_server.Controllers.v1_1
// compile data for return // compile data for return
int pageOffset = pageSize * (pageNumber - 1); int pageOffset = pageSize * (pageNumber - 1);
for (int i = 0; i < dbResponse.Rows.Count; i++) for (int i = pageOffset; i < dbResponse.Rows.Count; i++)
{ {
DataRow dr = dbResponse.Rows[i]; if (i >= (pageOffset + pageSize))
bool includeGame = false;
if (pageSize == 0)
{ {
// page size is full size include all break;
includeGame = true;
}
else if (i >= pageOffset && i < (pageOffset + pageSize))
{
includeGame = true;
} }
if (includeGame == true) RetVal.Add(Classes.Metadata.Games.GetGame(dbResponse.Rows[i]));
{
RetVal.Add(Classes.Metadata.Games.GetGame(dr));
}
} }
GameReturnPackage gameReturn = new GameReturnPackage(RecordCount, RetVal); GameReturnPackage gameReturn = new GameReturnPackage(RecordCount, RetVal);

View File

@@ -13,7 +13,7 @@ namespace gaseous_server
{ {
_ItemType = ItemType; _ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted; _ItemState = QueueItemState.NeverStarted;
_LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ"))); _LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ"))).AddMinutes(-5);
_Interval = ExecutionInterval; _Interval = ExecutionInterval;
_AllowManualStart = AllowManualStart; _AllowManualStart = AllowManualStart;
_RemoveWhenStopped = RemoveWhenStopped; _RemoveWhenStopped = RemoveWhenStopped;
@@ -23,7 +23,7 @@ namespace gaseous_server
{ {
_ItemType = ItemType; _ItemType = ItemType;
_ItemState = QueueItemState.NeverStarted; _ItemState = QueueItemState.NeverStarted;
_LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ"))); _LastRunTime = DateTime.Parse(Config.ReadSetting("LastRun_" + _ItemType.ToString(), DateTime.UtcNow.ToString("yyyy-MM-ddThh:mm:ssZ"))).AddMinutes(-5);
_Interval = ExecutionInterval; _Interval = ExecutionInterval;
_AllowManualStart = AllowManualStart; _AllowManualStart = AllowManualStart;
_RemoveWhenStopped = RemoveWhenStopped; _RemoveWhenStopped = RemoveWhenStopped;

View File

@@ -0,0 +1,20 @@
ALTER TABLE `ClassificationMap`
ADD INDEX `idx_RatingId` (`RatingId` ASC) VISIBLE;
ALTER TABLE `Relation_Game_AgeRatings`
ADD INDEX `idx_SecondaryColumn` (`AgeRatingsId` ASC) VISIBLE;
ALTER TABLE `Relation_Game_GameModes`
ADD INDEX `idx_SecondaryColumn` (`GameModesId` ASC) VISIBLE;
ALTER TABLE `Relation_Game_Genres`
ADD INDEX `idx_SecondaryColumn` (`GenresId` ASC) VISIBLE;
ALTER TABLE `Relation_Game_Platforms`
ADD INDEX `idx_SecondaryColumn` (`PlatformsId` ASC) VISIBLE;
ALTER TABLE `Relation_Game_PlayerPerspectives`
ADD INDEX `idx_SecondaryColumn` (`PlayerPerspectivesId` ASC) VISIBLE;
ALTER TABLE `Relation_Game_Themes`
ADD INDEX `idx_SecondaryColumn` (`ThemesId` ASC) VISIBLE;

View File

@@ -48,6 +48,7 @@
<None Remove="Support\Database\MySQL\gaseous-1005.sql" /> <None Remove="Support\Database\MySQL\gaseous-1005.sql" />
<None Remove="Support\Database\MySQL\gaseous-1006.sql" /> <None Remove="Support\Database\MySQL\gaseous-1006.sql" />
<None Remove="Support\Database\MySQL\gaseous-1007.sql" /> <None Remove="Support\Database\MySQL\gaseous-1007.sql" />
<None Remove="Support\Database\MySQL\gaseous-1008.sql" />
<None Remove="Classes\Metadata\" /> <None Remove="Classes\Metadata\" />
<None Remove="Assets\" /> <None Remove="Assets\" />
<None Remove="Assets\Ratings\" /> <None Remove="Assets\Ratings\" />
@@ -178,5 +179,6 @@
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1005.sql" /> <EmbeddedResource Include="Support\Database\MySQL\gaseous-1005.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1006.sql" /> <EmbeddedResource Include="Support\Database\MySQL\gaseous-1006.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1007.sql" /> <EmbeddedResource Include="Support\Database\MySQL\gaseous-1007.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1008.sql" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -90,17 +90,36 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize) {
} }
// add page numbers // add page numbers
var pageEitherSide = 4;
var currentPage = Number(pagerCheck.innerHTML);
var pageNumbers = document.createElement('span'); var pageNumbers = document.createElement('span');
for (var i = 1; i <= pageCount; i++) { for (var i = 1; i <= pageCount; i++) {
var pageNum = document.createElement('span'); if (
if (Number(pagerCheck.innerHTML) == i) { (
pageNum.className = 'games_pager_number_disabled'; (i >= currentPage - pageEitherSide) &&
} else { (i <= currentPage + pageEitherSide)
pageNum.className = 'games_pager_number'; ) ||
pageNum.setAttribute('onclick', 'executeFilter1_1(' + i + ');'); (
(
i <= (pageEitherSide * 2 + 1) &&
currentPage <= (pageEitherSide)
) ||
(
i >= (pageCount - (pageEitherSide * 2)) &&
currentPage >= (pageCount - (pageEitherSide))
)
)
) {
var pageNum = document.createElement('span');
if (Number(pagerCheck.innerHTML) == i) {
pageNum.className = 'games_pager_number_disabled';
} else {
pageNum.className = 'games_pager_number';
pageNum.setAttribute('onclick', 'executeFilter1_1(' + i + ');');
}
pageNum.innerHTML = i;
pageNumbers.appendChild(pageNum);
} }
pageNum.innerHTML = i;
pageNumbers.appendChild(pageNum);
} }
// add next page button // add next page button

View File

@@ -316,7 +316,10 @@ input[id='filter_panel_userrating_max'] {
} }
.games_pager_number { .games_pager_number {
display: inline-block;
padding: 5px; padding: 5px;
width: 40px;
text-align: center;
} }
.games_pager_number:hover { .games_pager_number:hover {
@@ -325,7 +328,10 @@ input[id='filter_panel_userrating_max'] {
} }
.games_pager_number_disabled { .games_pager_number_disabled {
display: inline-block;
padding: 5px; padding: 5px;
width: 40px;
text-align: center;
color: grey; color: grey;
} }