Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Licho1 committed Dec 23, 2017
2 parents 67d1741 + 3297dbc commit b877087
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 62 deletions.
1 change: 1 addition & 0 deletions Shared/PlasmaShared/PlasmaShared.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
<Compile Include="EventArgs.cs" />
<Compile Include="EventExtensions.cs" />
<Compile Include="GlobalConst.cs" />
<Compile Include="PriorityScheduler.cs" />
<Compile Include="Hash.cs" />
<Compile Include="IContentService\AccountInfo.cs" />
<Compile Include="IContentService\ClientMissionInfo.cs" />
Expand Down
64 changes: 64 additions & 0 deletions Shared/PlasmaShared/PriorityScheduler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace ZkData
{
//Priority Scheduler implementation from https://stackoverflow.com/a/9056702/ by Roman Starkov
public class PriorityScheduler : TaskScheduler
{
public static PriorityScheduler AboveNormal = new PriorityScheduler(ThreadPriority.AboveNormal);
public static PriorityScheduler BelowNormal = new PriorityScheduler(ThreadPriority.BelowNormal);
public static PriorityScheduler Lowest = new PriorityScheduler(ThreadPriority.Lowest);

private BlockingCollection<Task> _tasks = new BlockingCollection<Task>();
private Thread[] _threads;
private ThreadPriority _priority;
private readonly int _maximumConcurrencyLevel = Math.Max(1, Environment.ProcessorCount);

public PriorityScheduler(ThreadPriority priority)
{
_priority = priority;
}

public override int MaximumConcurrencyLevel
{
get { return _maximumConcurrencyLevel; }
}

protected override IEnumerable<Task> GetScheduledTasks()
{
return _tasks;
}

protected override void QueueTask(Task task)
{
_tasks.Add(task);

if (_threads == null)
{
_threads = new Thread[_maximumConcurrencyLevel];
for (int i = 0; i < _threads.Length; i++)
{
int local = i;
_threads[i] = new Thread(() =>
{
foreach (Task t in _tasks.GetConsumingEnumerable())
base.TryExecuteTask(t);
});
_threads[i].Name = string.Format("PriorityScheduler: ", i);
_threads[i].Priority = _priority;
_threads[i].IsBackground = true;
_threads[i].Start();
}
}
}

protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
{
return false; // we might not want to execute task that should schedule as high or low priority inline
}
}
}
30 changes: 16 additions & 14 deletions ZkData/Ef/WHR/RatingSystems.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,26 @@ public static void Init()
{
try
{
ZkDataContext data = new ZkDataContext();
for (int year = 10; year > 0; year--)
using (ZkDataContext data = new ZkDataContext())
{
DateTime minStartTime = DateTime.Now.AddYears(-year);
DateTime maxStartTime = DateTime.Now.AddYears(-year + 1);
foreach (SpringBattle b in data.SpringBattles
.Where(x => x.StartTime > minStartTime && x.StartTime < maxStartTime)
.Include(x => x.ResourceByMapResourceID)
.Include(x => x.SpringBattlePlayers)
.Include(x => x.SpringBattleBots)
.AsNoTracking()
.OrderBy(x => x.StartTime))
for (int year = 10; year > 0; year--)
{
ProcessBattle(b);
DateTime minStartTime = DateTime.Now.AddYears(-year);
DateTime maxStartTime = DateTime.Now.AddYears(-year + 1);
foreach (SpringBattle b in data.SpringBattles
.Where(x => x.StartTime > minStartTime && x.StartTime < maxStartTime)
.Include(x => x.ResourceByMapResourceID)
.Include(x => x.SpringBattlePlayers)
.Include(x => x.SpringBattleBots)
.AsNoTracking()
.OrderBy(x => x.StartTime))
{
ProcessBattle(b);
}
}
Initialized = true;
whr.Values.ForEach(w => w.UpdateRatings());
}
Initialized = true;
whr.Values.ForEach(w => w.UpdateRatings());
}
catch (Exception ex)
{
Expand Down
136 changes: 88 additions & 48 deletions ZkData/Ef/WHR/WholeHistoryRating.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics;
using System.IO;
using System.Linq;
Expand Down Expand Up @@ -106,27 +107,60 @@ public void ProcessBattle(SpringBattle battle)
}
}

private List<Account> laddersCache = new List<Account>();

public List<Account> GetTopPlayers(int count)
{
ZkDataContext db = new ZkDataContext();
List<int> retIDs = topPlayers.Take(count).ToList();
return db.Accounts.Where(a => retIDs.Contains(a.AccountID)).OrderByDescending(x => x.AccountRatings.Where(r => r.RatingCategory == category).Select(r => r.Elo).DefaultIfEmpty(-1).FirstOrDefault()).ToList();
if (count > 200)
{
using (ZkDataContext db = new ZkDataContext())
{
laddersCache = db.Accounts
.Include(a => a.Clan)
.Include(a => a.Faction)
.OrderByDescending(x => x.AccountRatings.Where(r => r.RatingCategory == category).Select(r => r.Elo).DefaultIfEmpty(-1).FirstOrDefault())
.Take(count)
.ToList();
}
}
if (laddersCache.Count < count)
{

using (ZkDataContext db = new ZkDataContext())
{
List<int> retIDs = topPlayers.Take(count).ToList();
laddersCache = db.Accounts
.Where(a => retIDs.Contains(a.AccountID))
.Include(a => a.Clan)
.Include(a => a.Faction)
.OrderByDescending(x => x.AccountRatings.Where(r => r.RatingCategory == category).Select(r => r.Elo).DefaultIfEmpty(-1).FirstOrDefault())
.ToList();
}
}
return laddersCache.Take(count).ToList();
}

public List<Account> GetTopPlayers(int count, Func<Account, bool> selector)
{
lock (updateLockInternal)
{
int counter = 0;
ZkDataContext db = new ZkDataContext();
List<Account> retval = new List<Account>();
foreach (var pair in sortedPlayers)

using (ZkDataContext db = new ZkDataContext())
{
Account acc = db.Accounts.Where(a => a.AccountID == pair.Value).FirstOrDefault();
if (playerRatings[acc.AccountID].Rank < int.MaxValue && selector.Invoke(acc))
foreach (var pair in sortedPlayers)
{
if (counter++ >= count) break;
retval.Add(acc);
Account acc = db.Accounts
.Where(a => a.AccountID == pair.Value)
.Include(a => a.Clan)
.Include(a => a.Faction)
.FirstOrDefault();
if (playerRatings[acc.AccountID].Rank < int.MaxValue && selector.Invoke(acc))
{
if (counter++ >= count) break;
retval.Add(acc);
}
}
}
return retval;
Expand Down Expand Up @@ -168,7 +202,7 @@ public void UpdateRatings()
{
updateAction = (() => {
Trace.TraceInformation("Initializing WHR " + category +" ratings for " + battlesRegistered + " battles, this will take some time.. From B" + firstBattle?.SpringBattleID + " to B" + latestBattle?.SpringBattleID);
runIterations(50);
runIterations(75);
UpdateRankings(players.Values);
playerOldRatings = new Dictionary<int, PlayerRating>(playerRatings);
});
Expand Down Expand Up @@ -224,7 +258,7 @@ public void UpdateRatings()
{
Trace.TraceError("Thread error while updating WHR " + category +" " + ex);
}
});
}, CancellationToken.None, TaskCreationOptions.None, PriorityScheduler.BelowNormal);
lastUpdate = latestBattle;
}

Expand All @@ -235,22 +269,24 @@ public void SaveToDB(IEnumerable<int> players)
lock (dbLock)
{

var db = new ZkDataContext();
foreach (int player in players)
using (var db = new ZkDataContext())
{
var accountRating = db.AccountRatings.Where(x => x.RatingCategory == category && x.AccountID == player).FirstOrDefault();
if (accountRating == null)
{
accountRating = new AccountRating(player, category);
accountRating.UpdateFromRatingSystem(playerRatings[player]);
db.AccountRatings.InsertOnSubmit(accountRating);
}
else
foreach (int player in players)
{
accountRating.UpdateFromRatingSystem(playerRatings[player]);
var accountRating = db.AccountRatings.Where(x => x.RatingCategory == category && x.AccountID == player).FirstOrDefault();
if (accountRating == null)
{
accountRating = new AccountRating(player, category);
accountRating.UpdateFromRatingSystem(playerRatings[player]);
db.AccountRatings.InsertOnSubmit(accountRating);
}
else
{
accountRating.UpdateFromRatingSystem(playerRatings[player]);
}
}
db.SaveChanges();
}
db.SaveChanges();
}
}

Expand All @@ -259,37 +295,39 @@ public void SaveToDB()
lock (dbLock)
{
DateTime start = DateTime.Now;
var db = new ZkDataContext();
HashSet<int> processedPlayers = new HashSet<int>();
int deleted = 0;
int added = 0;
foreach (var accountRating in db.AccountRatings.Where(x => x.RatingCategory == category))
using (var db = new ZkDataContext())
{
if (!playerRatings.ContainsKey(accountRating.AccountID))
HashSet<int> processedPlayers = new HashSet<int>();
int deleted = 0;
int added = 0;
foreach (var accountRating in db.AccountRatings.Where(x => x.RatingCategory == category))
{
deleted++;
db.AccountRatings.DeleteOnSubmit(accountRating);
continue;
}
processedPlayers.Add(accountRating.AccountID);
if (Math.Abs(playerRatings[accountRating.AccountID].Elo - accountRating.Elo) > 1)
{
accountRating.UpdateFromRatingSystem(playerRatings[accountRating.AccountID]);
if (!playerRatings.ContainsKey(accountRating.AccountID))
{
deleted++;
db.AccountRatings.DeleteOnSubmit(accountRating);
continue;
}
processedPlayers.Add(accountRating.AccountID);
if (Math.Abs(playerRatings[accountRating.AccountID].Elo - accountRating.Elo) > 1)
{
accountRating.UpdateFromRatingSystem(playerRatings[accountRating.AccountID]);
}
}
}
foreach (int player in playerRatings.Keys)
{
if (!processedPlayers.Contains(player))
foreach (int player in playerRatings.Keys)
{
var accountRating = new AccountRating(player, category);
accountRating.UpdateFromRatingSystem(playerRatings[player]);
db.AccountRatings.InsertOnSubmit(accountRating);
added++;
if (!processedPlayers.Contains(player))
{
var accountRating = new AccountRating(player, category);
accountRating.UpdateFromRatingSystem(playerRatings[player]);
db.AccountRatings.InsertOnSubmit(accountRating);
added++;
}
}
}

db.SaveChanges();
Trace.TraceInformation("WHR " + category +" Ratings saved to DB in " + DateTime.Now.Subtract(start).TotalSeconds + " seconds, " + added + " entries added, " + deleted + " entries removed, " + (GC.GetTotalMemory(false) / (1 << 20)) + "MiB total memory allocated");
db.SaveChanges();
Trace.TraceInformation("WHR " + category + " Ratings saved to DB in " + DateTime.Now.Subtract(start).TotalSeconds + " seconds, " + added + " entries added, " + deleted + " entries removed, " + (GC.GetTotalMemory(false) / (1 << 20)) + "MiB total memory allocated");
}
}
}

Expand Down Expand Up @@ -375,6 +413,7 @@ private void UpdateRankings(IEnumerable<Player> players)
}
}
topPlayers = newTopPlayers;
laddersCache = new List<Account>();
Trace.TraceInformation("WHR " + category +" Ladders updated with " + topPlayers.Count + "/" + this.players.Count + " entries, max uncertainty selected: " + DynamicMaxUncertainty);

var playerIds = players.Select(x => x.id).ToList();
Expand All @@ -387,6 +426,7 @@ private void UpdateRankings(IEnumerable<Player> players)
}

//check for topX updates
GetTopPlayers(GlobalConst.LadderSize);
foreach (var listener in topPlayersUpdateListeners)
{
if (matched < listener.Value)
Expand Down

0 comments on commit b877087

Please sign in to comment.