Checked LINQ queries and collections for inefficiencies.

- Made Array.IndexOf available via extension method.
- Made ToHashSet extension method.
- Change collections queried often via Contains into sets.
- Avoid Count() extension if Count or Length property exist.
- Made Count() > 0 checks and variations calls to Any() instead.
- Don't call ToList/ToArray if there is no benefit to materializing the sequence.
- If the sequence does benefit from materialization, follow this general pattern:
  - Collection queried often via Contains use ToHashSet to speed up lookups.
  - Short lived variables use ToList. This is because ToArray requires an extra copy to output the final size.
  - Collections persisted into fields or for a long time use ToArray to minimize memory overhead.
This commit is contained in:
RoosterDragon
2014-05-23 19:52:44 +01:00
committed by RoosterDragon
parent f5f3747338
commit 82bea961ba
44 changed files with 151 additions and 126 deletions

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
readonly ContainerWidget chatTemplate;
readonly TextFieldWidget chatText;
readonly List<INotifyChat> chatTraits;
readonly INotifyChat[] chatTraits;
readonly TabCompletionLogic tabCompletion = new TabCompletionLogic();
@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
this.orderManager = orderManager;
this.modRules = modRules;
chatTraits = world.WorldActor.TraitsImplementing<INotifyChat>().ToList();
chatTraits = world.WorldActor.TraitsImplementing<INotifyChat>().ToArray();
var players = world.Players.Where(p => p != world.LocalPlayer && !p.NonCombatant && !p.IsBot);
disableTeamChat = world.LocalPlayer == null || world.LobbyInfo.IsSinglePlayer || !players.Any(p => p.IsAlliedWith(world.LocalPlayer));

View File

@@ -459,10 +459,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var techLevel = optionsBin.GetOrNull<DropDownButtonWidget>("TECHLEVEL_DROPDOWNBUTTON");
if (techLevel != null)
{
var techTraits = modRules.Actors["player"].Traits.WithInterface<ProvidesTechPrerequisiteInfo>().ToArray();
techLevel.IsVisible = () => techTraits.Length > 0;
optionsBin.GetOrNull<LabelWidget>("TECHLEVEL_DESC").IsVisible = () => techTraits.Length > 0;
techLevel.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null || configurationDisabled() || techTraits.Length <= 1;
var techTraits = modRules.Actors["player"].Traits.WithInterface<ProvidesTechPrerequisiteInfo>().ToList();
techLevel.IsVisible = () => techTraits.Count > 0;
optionsBin.GetOrNull<LabelWidget>("TECHLEVEL_DESC").IsVisible = () => techTraits.Count > 0;
techLevel.IsDisabled = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null || configurationDisabled() || techTraits.Count <= 1;
techLevel.GetText = () => Map.Status != MapStatus.Available || Map.Map.Options.TechLevel != null ? "Not Available" : "{0}".F(orderManager.LobbyInfo.GlobalSettings.TechLevel);
techLevel.OnMouseDown = _ =>
{

View File

@@ -156,7 +156,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var spawns = preview.SpawnPoints;
return lobbyInfo.Clients
.Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Count))
.Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Length))
.ToDictionary(c => spawns[c.SpawnPoint - 1], c => new SpawnOccupant(c));
}
@@ -164,7 +164,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var spawns = preview.SpawnPoints;
return players
.Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Count))
.Where(c => (c.SpawnPoint - 1 >= 0) && (c.SpawnPoint - 1 < spawns.Length))
.ToDictionary(c => spawns[c.SpawnPoint - 1], c => new SpawnOccupant(c));
}
@@ -430,7 +430,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
var dropdown = parent.Get<DropDownButtonWidget>("SPAWN");
dropdown.IsDisabled = () => s.LockSpawn || orderManager.LocalClient.IsReady;
dropdown.OnMouseDown = _ => ShowSpawnDropDown(dropdown, c, orderManager, Enumerable.Range(0, map.SpawnPoints.Count + 1).Except(orderManager.LobbyInfo.Clients.Where(client => client != c && client.SpawnPoint != 0).Select(client => client.SpawnPoint)));
dropdown.OnMouseDown = _ =>
{
var spawnPoints = Enumerable.Range(0, map.SpawnPoints.Length + 1).Except(
orderManager.LobbyInfo.Clients.Where(
client => client != c && client.SpawnPoint != 0).Select(client => client.SpawnPoint));
ShowSpawnDropDown(dropdown, c, orderManager, spawnPoints);
};
dropdown.GetText = () => (c.SpawnPoint == 0) ? "-" : Convert.ToChar('A' - 1 + c.SpawnPoint).ToString();
}

View File

@@ -21,7 +21,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
string selectedUid;
// May be a subset of available maps if a mode filter is active
List<string> visibleMaps;
string[] visibleMaps;
ScrollPanelWidget scrollpanel;
ScrollItemWidget itemTemplate;
@@ -103,7 +103,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
selectedUid = uid;
scrollpanel.ScrollToItem(uid, smooth: true);
};
randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Count == 0;
randomMapButton.IsDisabled = () => visibleMaps == null || visibleMaps.Length == 0;
}
EnumerateMaps(onSelect, filter);
@@ -158,7 +158,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
scrollpanel.AddChild(item);
}
visibleMaps = maps.Select(m => m.Uid).ToList();
visibleMaps = maps.Select(m => m.Uid).ToArray();
if (visibleMaps.Contains(selectedUid))
scrollpanel.ScrollToItem(selectedUid);
}

View File

@@ -203,7 +203,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var ddb = panel.GetOrNull<DropDownButtonWidget>("FLT_MAPNAME_DROPDOWNBUTTON");
if (ddb != null)
{
var options = new HashSet<string>(replays.Select(r => r.GameInfo.MapTitle), StringComparer.OrdinalIgnoreCase).ToList();
var options = replays.Select(r => r.GameInfo.MapTitle).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
options.Sort(StringComparer.OrdinalIgnoreCase);
options.Insert(0, null); // no filter
@@ -231,7 +231,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var ddb = panel.GetOrNull<DropDownButtonWidget>("FLT_PLAYER_DROPDOWNBUTTON");
if (ddb != null)
{
var options = new HashSet<string>(replays.SelectMany(r => r.GameInfo.Players.Select(p => p.Name)), StringComparer.OrdinalIgnoreCase).ToList();
var options = replays.SelectMany(r => r.GameInfo.Players.Select(p => p.Name)).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
options.Sort(StringComparer.OrdinalIgnoreCase);
options.Insert(0, null); // no filter
@@ -295,7 +295,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
{
ddb.IsDisabled = () => string.IsNullOrEmpty(filter.PlayerName);
var options = new HashSet<string>(replays.SelectMany(r => r.GameInfo.Players.Select(p => p.FactionName).Where(n => !string.IsNullOrEmpty(n))), StringComparer.OrdinalIgnoreCase).ToList();
var options = replays.SelectMany(r => r.GameInfo.Players.Select(p => p.FactionName).Where(n => !string.IsNullOrEmpty(n))).Distinct(StringComparer.OrdinalIgnoreCase).ToList();
options.Sort(StringComparer.OrdinalIgnoreCase);
options.Insert(0, null); // no filter

View File

@@ -281,7 +281,7 @@ namespace OpenRA.Mods.Common.Widgets
Hotkey = ks.GetProductionHotkey(DisplayedIconCount),
Sprite = icon.Image,
Pos = new float2(rect.Location),
Queued = CurrentQueue.AllQueued().Where(a => a.Item == item.Name).ToList(),
Queued = CurrentQueue.AllQueued().Where(a => a.Item == item.Name).ToList()
};
icons.Add(rect, pi);

View File

@@ -196,7 +196,7 @@ namespace OpenRA.Mods.Common.Widgets
{
var allQueues = a.World.ActorsWithTrait<ProductionQueue>()
.Where(p => p.Actor.Owner == p.Actor.World.LocalPlayer && p.Actor.IsInWorld && p.Trait.Enabled)
.Select(p => p.Trait).ToArray();
.Select(p => p.Trait).ToList();
foreach (var g in Groups.Values)
g.Update(allQueues);