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 IGDB.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
namespace gaseous_server.Classes
@@ -220,7 +221,10 @@ namespace gaseous_server.Classes
} else {
// get all platforms to pull from
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

View File

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

View File

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

View File

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

View File

@@ -13,7 +13,7 @@ namespace gaseous_server
{
_ItemType = ItemType;
_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;
_AllowManualStart = AllowManualStart;
_RemoveWhenStopped = RemoveWhenStopped;
@@ -23,7 +23,7 @@ namespace gaseous_server
{
_ItemType = ItemType;
_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;
_AllowManualStart = AllowManualStart;
_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-1006.sql" />
<None Remove="Support\Database\MySQL\gaseous-1007.sql" />
<None Remove="Support\Database\MySQL\gaseous-1008.sql" />
<None Remove="Classes\Metadata\" />
<None Remove="Assets\" />
<None Remove="Assets\Ratings\" />
@@ -178,5 +179,6 @@
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1005.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1006.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1007.sql" />
<EmbeddedResource Include="Support\Database\MySQL\gaseous-1008.sql" />
</ItemGroup>
</Project>

View File

@@ -90,17 +90,36 @@ function formatGamesPanel(targetElement, result, pageNumber, pageSize) {
}
// add page numbers
var pageEitherSide = 4;
var currentPage = Number(pagerCheck.innerHTML);
var pageNumbers = document.createElement('span');
for (var i = 1; i <= pageCount; i++) {
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 + ');');
if (
(
(i >= currentPage - pageEitherSide) &&
(i <= currentPage + pageEitherSide)
) ||
(
(
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

View File

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