From 587ec6fa1399bb1b4377fe2093819105ac9ac4b4 Mon Sep 17 00:00:00 2001 From: RogueException Date: Sat, 2 Jan 2016 02:36:17 -0400 Subject: [PATCH] Improved load performance when in many servers --- src/Discord.Net/DiscordClient.cs | 8 +-- src/Discord.Net/Models/Server.cs | 92 +++++++++++++++++++++++++------- 2 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/Discord.Net/DiscordClient.cs b/src/Discord.Net/DiscordClient.cs index 47897ed10..cf8533ba2 100644 --- a/src/Discord.Net/DiscordClient.cs +++ b/src/Discord.Net/DiscordClient.cs @@ -415,7 +415,9 @@ namespace Discord #region Servers private Server AddServer(ulong id) - => _servers.GetOrAdd(id, x => new Server(this, x)); + => _servers.GetOrAdd(id, x => new Server(this, id)); + private Server AddServer(API.Client.ExtendedGuild model) + => _servers.GetOrAdd(model.Id, x => new Server(this, model)); private Server RemoveServer(ulong id) { Server server; @@ -481,7 +483,7 @@ namespace Discord { if (model.Unavailable != true) { - var server = AddServer(model.Id); + var server = AddServer(model); server.Update(model); } } @@ -505,7 +507,7 @@ namespace Discord var data = e.Payload.ToObject(_serializer); if (data.Unavailable != true) { - var server = AddServer(data.Id); + var server = AddServer(data); server.Update(data); if (Config.LogEvents) diff --git a/src/Discord.Net/Models/Server.cs b/src/Discord.Net/Models/Server.cs index e54680d34..605357e4d 100644 --- a/src/Discord.Net/Models/Server.cs +++ b/src/Discord.Net/Models/Server.cs @@ -29,9 +29,9 @@ namespace Discord } } - private readonly ConcurrentDictionary _roles; - private readonly ConcurrentDictionary _users; - private readonly ConcurrentDictionary _channels; + private ConcurrentDictionary _roles; + private ConcurrentDictionary _users; + private ConcurrentDictionary _channels; private ulong _ownerId; private ulong? _afkChannelId; @@ -39,11 +39,6 @@ namespace Discord /// Gets the unique identifier for this server. public ulong Id { get; } - /// Gets the default channel for this server. - public Channel DefaultChannel { get; } - /// Gets the the role representing all users in a server. - public Role EveryoneRole { get; } - /// Gets the name of this server. public string Name { get; private set; } /// Gets the voice region for this server. @@ -54,6 +49,10 @@ namespace Discord public int AFKTimeout { get; private set; } /// Gets the date and time you joined this server. public DateTime JoinedAt { get; private set; } + /// Gets the default channel for this server. + public Channel DefaultChannel { get; private set; } + /// Gets the the role representing all users in a server. + public Role EveryoneRole { get; private set; } /// Gets the user that created this server. public User Owner => GetUser(_ownerId); @@ -76,17 +75,23 @@ namespace Discord public IEnumerable Users => _users.Select(x => x.Value.User); /// Gets a collection of all roles in this server. public IEnumerable Roles => _roles.Select(x => x.Value); - + internal Server(DiscordClient client, ulong id) { Client = client; Id = id; - _channels = new ConcurrentDictionary(); _roles = new ConcurrentDictionary(); _users = new ConcurrentDictionary(); - DefaultChannel = AddChannel(id); - EveryoneRole = AddRole(id); + + EveryoneRole = new Role(id, this); + DefaultChannel = new Channel(client, id, this); + } + internal Server(DiscordClient client, ExtendedGuild model) + { + Client = client; + Id = model.Id; + Update(model); } internal void Update(GuildReference model) @@ -118,28 +123,78 @@ namespace Discord } internal void Update(ExtendedGuild model) { - Update(model as Guild); + var everyone = EveryoneRole; + var defaultChannel = DefaultChannel; + //Bulk create dictionary items + if (model.Members != null) + { + _users = new ConcurrentDictionary( + model.Members.Select(x => new KeyValuePair(x.User.Id, new Member(new User(Client, x.User.Id, this))))); + } + else + _users = new ConcurrentDictionary(); + if (model.Channels != null) + { + _channels = new ConcurrentDictionary( + model.Channels.Select(x => new KeyValuePair(x.Id, new Channel(Client, x.Id, this)))); + } + else + _channels = new ConcurrentDictionary(); + if (model.Roles != null) + { + _roles = new ConcurrentDictionary( + model.Roles.Select(x => new KeyValuePair(x.Id, new Role(x.Id, this)))); + } + else + _roles = new ConcurrentDictionary(); + + //Preserve old models + if (everyone != null) + _roles[Id] = everyone; + else + EveryoneRole = _roles[Id]; + if (defaultChannel != null) + _channels[Id] = defaultChannel; + else + DefaultChannel = _channels[Id]; + + //Update models if (model.Channels != null) { foreach (var subModel in model.Channels) - AddChannel(subModel.Id).Update(subModel); + { + var channel = _channels[subModel.Id]; + channel.Update(subModel); + Client.AddChannel(channel); + } } if (model.Members != null) { foreach (var subModel in model.Members) - AddUser(subModel.User.Id).Update(subModel); + _users[subModel.User.Id].User.Update(subModel); } if (model.VoiceStates != null) { foreach (var subModel in model.VoiceStates) - GetUser(subModel.UserId)?.Update(subModel); + _users[subModel.UserId].User.Update(subModel); } if (model.Presences != null) { foreach (var subModel in model.Presences) - GetUser(subModel.User.Id)?.Update(subModel); + { + if (subModel.User.Username != null) + _users[subModel.User.Id].User.Update(subModel); + } + } + if (model.Roles != null) + { + foreach (var subModel in model.Roles) + _roles[subModel.Id].Update(subModel); } + + model.Roles = null; //Don't double-process roles + Update(model as Guild); } /// Edits this server, changing only non-null attributes. @@ -207,8 +262,7 @@ namespace Discord { var channel = new Channel(Client, id, this); Client.AddChannel(channel); - channel = _channels.GetOrAdd(id, x => channel); - return channel; + return _channels.GetOrAdd(id, x => channel); } internal Channel RemoveChannel(ulong id) {