mirror of
https://github.com/osukey/osukey.git
synced 2025-07-01 16:29:58 +09:00
Use dictionary to avoid linq overhead
This commit is contained in:
@ -45,15 +45,13 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
private void performLookup()
|
private void performLookup()
|
||||||
{
|
{
|
||||||
// userTasks may exceed 50 elements, indicating the existence of duplicate user IDs. All duplicated user IDs must be fulfilled.
|
// contains at most 50 unique user IDs from userTasks, which is used to perform the lookup.
|
||||||
// userIds contains at most 50 unique user IDs from userTasks, which is used to perform the lookup.
|
var userTasks = new Dictionary<int, List<TaskCompletionSource<User>>>();
|
||||||
var userTasks = new List<(int id, TaskCompletionSource<User> task)>();
|
|
||||||
var userIds = new HashSet<int>();
|
|
||||||
|
|
||||||
// Grab at most 50 unique user IDs from the queue.
|
// Grab at most 50 unique user IDs from the queue.
|
||||||
lock (taskAssignmentLock)
|
lock (taskAssignmentLock)
|
||||||
{
|
{
|
||||||
while (pendingUserTasks.Count > 0 && userIds.Count < 50)
|
while (pendingUserTasks.Count > 0 && userTasks.Count < 50)
|
||||||
{
|
{
|
||||||
(int id, TaskCompletionSource<User> task) next = pendingUserTasks.Dequeue();
|
(int id, TaskCompletionSource<User> task) next = pendingUserTasks.Dequeue();
|
||||||
|
|
||||||
@ -62,14 +60,16 @@ namespace osu.Game.Database
|
|||||||
next.task.SetResult(existing);
|
next.task.SetResult(existing);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
userTasks.Add(next);
|
if (userTasks.TryGetValue(next.id, out var tasks))
|
||||||
userIds.Add(next.id);
|
tasks.Add(next.task);
|
||||||
|
else
|
||||||
|
userTasks[next.id] = new List<TaskCompletionSource<User>> { next.task };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query the users.
|
// Query the users.
|
||||||
var request = new GetUsersRequest(userIds.ToArray());
|
var request = new GetUsersRequest(userTasks.Keys.ToArray());
|
||||||
|
|
||||||
// rather than queueing, we maintain our own single-threaded request stream.
|
// rather than queueing, we maintain our own single-threaded request stream.
|
||||||
api.Perform(request);
|
api.Perform(request);
|
||||||
@ -82,9 +82,23 @@ namespace osu.Game.Database
|
|||||||
createNewTask();
|
createNewTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify of completion.
|
foreach (var user in request.Result.Users)
|
||||||
foreach (var (id, task) in userTasks)
|
{
|
||||||
task.SetResult(request.Result?.Users?.FirstOrDefault(u => u.Id == id));
|
if (userTasks.TryGetValue(user.Id, out var tasks))
|
||||||
|
{
|
||||||
|
foreach (var task in tasks)
|
||||||
|
task.SetResult(user);
|
||||||
|
|
||||||
|
userTasks.Remove(user.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if any tasks remain which were not satisfied, return null.
|
||||||
|
foreach (var tasks in userTasks.Values)
|
||||||
|
{
|
||||||
|
foreach (var task in tasks)
|
||||||
|
task.SetResult(null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createNewTask() => pendingRequestTask = Task.Run(performLookup);
|
private void createNewTask() => pendingRequestTask = Task.Run(performLookup);
|
||||||
|
Reference in New Issue
Block a user