Avoid some allocations during loading.
- In FieldLoader, cache boxed bools and some boxed ints. - In FieldLoader, presize collections when parsing a List, HashSet or Dictionary. - In FieldLoader, don't allocate a list of missing items until required. - In FieldLoader, when a string value is passed, avoid wrapping this in a MiniYaml object by allowing both strings and yaml to be passed in the GetValue overload that does the real work. - In Animation, avoid allocating no-op actions. - In VxlReader, use EnsureCapcity to better size the Dictionary. - In VxlReader change VxlElement to a struct. - In Locomotor, presize TerrainSpeeds dictionary.
This commit is contained in:
@@ -112,10 +112,19 @@ namespace OpenRA
|
|||||||
{ typeof(Nullable<>), ParseNullable },
|
{ typeof(Nullable<>), ParseNullable },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static readonly object BoxedTrue = true;
|
||||||
|
static readonly object BoxedFalse = false;
|
||||||
|
static readonly object[] BoxedInts = Exts.MakeArray(33, i => (object)i);
|
||||||
|
|
||||||
static object ParseInt(string fieldName, Type fieldType, string value, MemberInfo field)
|
static object ParseInt(string fieldName, Type fieldType, string value, MemberInfo field)
|
||||||
{
|
{
|
||||||
if (Exts.TryParseIntegerInvariant(value, out var res))
|
if (Exts.TryParseIntegerInvariant(value, out var res))
|
||||||
|
{
|
||||||
|
if (res >= 0 && res < BoxedInts.Length)
|
||||||
|
return BoxedInts[res];
|
||||||
return res;
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
return InvalidValueAction(value, fieldType, fieldName);
|
return InvalidValueAction(value, fieldType, fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +370,7 @@ namespace OpenRA
|
|||||||
static object ParseBool(string fieldName, Type fieldType, string value, MemberInfo field)
|
static object ParseBool(string fieldName, Type fieldType, string value, MemberInfo field)
|
||||||
{
|
{
|
||||||
if (bool.TryParse(value.ToLowerInvariant(), out var result))
|
if (bool.TryParse(value.ToLowerInvariant(), out var result))
|
||||||
return result;
|
return result ? BoxedTrue : BoxedFalse;
|
||||||
|
|
||||||
return InvalidValueAction(value, fieldType, fieldName);
|
return InvalidValueAction(value, fieldType, fieldName);
|
||||||
}
|
}
|
||||||
@@ -469,11 +478,11 @@ namespace OpenRA
|
|||||||
|
|
||||||
static object ParseHashSetOrList(string fieldName, Type fieldType, string value, MiniYaml yaml, MemberInfo field)
|
static object ParseHashSetOrList(string fieldName, Type fieldType, string value, MiniYaml yaml, MemberInfo field)
|
||||||
{
|
{
|
||||||
var set = Activator.CreateInstance(fieldType);
|
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return set;
|
return Activator.CreateInstance(fieldType);
|
||||||
|
|
||||||
var parts = value.Split(SplitComma, StringSplitOptions.RemoveEmptyEntries);
|
var parts = value.Split(SplitComma, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
var set = Activator.CreateInstance(fieldType, parts.Length);
|
||||||
var arguments = fieldType.GetGenericArguments();
|
var arguments = fieldType.GetGenericArguments();
|
||||||
var addMethod = fieldType.GetMethod(nameof(List<object>.Add), arguments);
|
var addMethod = fieldType.GetMethod(nameof(List<object>.Add), arguments);
|
||||||
var addArgs = new object[1];
|
var addArgs = new object[1];
|
||||||
@@ -488,7 +497,10 @@ namespace OpenRA
|
|||||||
|
|
||||||
static object ParseDictionary(string fieldName, Type fieldType, string value, MiniYaml yaml, MemberInfo field)
|
static object ParseDictionary(string fieldName, Type fieldType, string value, MiniYaml yaml, MemberInfo field)
|
||||||
{
|
{
|
||||||
var dict = Activator.CreateInstance(fieldType);
|
if (yaml == null)
|
||||||
|
return Activator.CreateInstance(fieldType);
|
||||||
|
|
||||||
|
var dict = Activator.CreateInstance(fieldType, yaml.Nodes.Count);
|
||||||
var arguments = fieldType.GetGenericArguments();
|
var arguments = fieldType.GetGenericArguments();
|
||||||
var addMethod = fieldType.GetMethod(nameof(Dictionary<object, object>.Add), arguments);
|
var addMethod = fieldType.GetMethod(nameof(Dictionary<object, object>.Add), arguments);
|
||||||
var addArgs = new object[2];
|
var addArgs = new object[2];
|
||||||
@@ -527,7 +539,7 @@ namespace OpenRA
|
|||||||
public static void Load(object self, MiniYaml my)
|
public static void Load(object self, MiniYaml my)
|
||||||
{
|
{
|
||||||
var loadInfo = TypeLoadInfo[self.GetType()];
|
var loadInfo = TypeLoadInfo[self.GetType()];
|
||||||
var missing = new List<string>();
|
List<string> missing = null;
|
||||||
|
|
||||||
Dictionary<string, MiniYaml> md = null;
|
Dictionary<string, MiniYaml> md = null;
|
||||||
|
|
||||||
@@ -542,6 +554,7 @@ namespace OpenRA
|
|||||||
val = fli.Loader(my);
|
val = fli.Loader(my);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
missing ??= new List<string>();
|
||||||
missing.Add(fli.YamlName);
|
missing.Add(fli.YamlName);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -551,7 +564,11 @@ namespace OpenRA
|
|||||||
if (!TryGetValueFromYaml(fli.YamlName, fli.Field, md, out val))
|
if (!TryGetValueFromYaml(fli.YamlName, fli.Field, md, out val))
|
||||||
{
|
{
|
||||||
if (fli.Attribute.Required)
|
if (fli.Attribute.Required)
|
||||||
|
{
|
||||||
|
missing ??= new List<string>();
|
||||||
missing.Add(fli.YamlName);
|
missing.Add(fli.YamlName);
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -559,7 +576,7 @@ namespace OpenRA
|
|||||||
fli.Field.SetValue(self, val);
|
fli.Field.SetValue(self, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missing.Count > 0)
|
if (missing != null)
|
||||||
throw new MissingFieldsException(missing.ToArray());
|
throw new MissingFieldsException(missing.ToArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,12 +637,17 @@ namespace OpenRA
|
|||||||
|
|
||||||
public static object GetValue(string fieldName, Type fieldType, string value, MemberInfo field)
|
public static object GetValue(string fieldName, Type fieldType, string value, MemberInfo field)
|
||||||
{
|
{
|
||||||
return GetValue(fieldName, fieldType, new MiniYaml(value), field);
|
return GetValue(fieldName, fieldType, value, null, field);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static object GetValue(string fieldName, Type fieldType, MiniYaml yaml, MemberInfo field)
|
public static object GetValue(string fieldName, Type fieldType, MiniYaml yaml, MemberInfo field)
|
||||||
{
|
{
|
||||||
var value = yaml.Value?.Trim();
|
return GetValue(fieldName, fieldType, yaml.Value, yaml, field);
|
||||||
|
}
|
||||||
|
|
||||||
|
static object GetValue(string fieldName, Type fieldType, string value, MiniYaml yaml, MemberInfo field)
|
||||||
|
{
|
||||||
|
value = value?.Trim();
|
||||||
if (fieldType.IsGenericType)
|
if (fieldType.IsGenericType)
|
||||||
{
|
{
|
||||||
if (GenericTypeParsers.TryGetValue(fieldType.GetGenericTypeDefinition(), out var parseFuncGeneric))
|
if (GenericTypeParsers.TryGetValue(fieldType.GetGenericTypeDefinition(), out var parseFuncGeneric))
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace OpenRA.Graphics
|
|||||||
bool backwards;
|
bool backwards;
|
||||||
bool tickAlways;
|
bool tickAlways;
|
||||||
int timeUntilNextFrame;
|
int timeUntilNextFrame;
|
||||||
Action tickFunc = () => { };
|
Action tickFunc;
|
||||||
|
|
||||||
public Animation(World world, string name)
|
public Animation(World world, string name)
|
||||||
: this(world, name, () => WAngle.Zero) { }
|
: this(world, name, () => WAngle.Zero) { }
|
||||||
@@ -164,7 +164,7 @@ namespace OpenRA.Graphics
|
|||||||
if (frame >= CurrentSequence.Length)
|
if (frame >= CurrentSequence.Length)
|
||||||
{
|
{
|
||||||
frame = CurrentSequence.Length - 1;
|
frame = CurrentSequence.Length - 1;
|
||||||
tickFunc = () => { };
|
tickFunc = null;
|
||||||
after?.Invoke();
|
after?.Invoke();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -212,13 +212,13 @@ namespace OpenRA.Graphics
|
|||||||
public void Tick(int t)
|
public void Tick(int t)
|
||||||
{
|
{
|
||||||
if (tickAlways)
|
if (tickAlways)
|
||||||
tickFunc();
|
tickFunc?.Invoke();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
timeUntilNextFrame -= t;
|
timeUntilNextFrame -= t;
|
||||||
while (timeUntilNextFrame <= 0)
|
while (timeUntilNextFrame <= 0)
|
||||||
{
|
{
|
||||||
tickFunc();
|
tickFunc?.Invoke();
|
||||||
timeUntilNextFrame += CurrentSequenceTickOrDefault();
|
timeUntilNextFrame += CurrentSequenceTickOrDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,15 @@ using System.IO;
|
|||||||
namespace OpenRA.Mods.Cnc.FileFormats
|
namespace OpenRA.Mods.Cnc.FileFormats
|
||||||
{
|
{
|
||||||
public enum NormalType { TiberianSun = 2, RedAlert2 = 4 }
|
public enum NormalType { TiberianSun = 2, RedAlert2 = 4 }
|
||||||
public class VxlElement
|
public readonly struct VxlElement
|
||||||
{
|
{
|
||||||
public byte Color;
|
public readonly byte Color;
|
||||||
public byte Normal;
|
public readonly byte Normal;
|
||||||
|
public VxlElement(byte color, byte normal)
|
||||||
|
{
|
||||||
|
Color = color;
|
||||||
|
Normal = normal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class VxlLimb
|
public class VxlLimb
|
||||||
@@ -83,20 +88,17 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
|||||||
var x = (byte)(i % l.Size[0]);
|
var x = (byte)(i % l.Size[0]);
|
||||||
var y = (byte)(i / l.Size[0]);
|
var y = (byte)(i / l.Size[0]);
|
||||||
byte z = 0;
|
byte z = 0;
|
||||||
l.VoxelMap[x, y] = new Dictionary<byte, VxlElement>();
|
var voxelMap = new Dictionary<byte, VxlElement>();
|
||||||
|
l.VoxelMap[x, y] = voxelMap;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
z += s.ReadUInt8();
|
z += s.ReadUInt8();
|
||||||
var count = s.ReadUInt8();
|
var count = s.ReadUInt8();
|
||||||
|
voxelMap.EnsureCapacity(voxelMap.Count + count);
|
||||||
for (var j = 0; j < count; j++)
|
for (var j = 0; j < count; j++)
|
||||||
{
|
{
|
||||||
var v = new VxlElement
|
var v = new VxlElement(s.ReadUInt8(), s.ReadUInt8());
|
||||||
{
|
voxelMap.Add(z, v);
|
||||||
Color = s.ReadUInt8(),
|
|
||||||
Normal = s.ReadUInt8()
|
|
||||||
};
|
|
||||||
|
|
||||||
l.VoxelMap[x, y].Add(z, v);
|
|
||||||
z++;
|
z++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ namespace OpenRA.Mods.Cnc.Graphics
|
|||||||
sheetBuilder = CreateSheetBuilder();
|
sheetBuilder = CreateSheetBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex[] GenerateSlicePlane(int su, int sv, Func<int, int, VxlElement> first, Func<int, int, VxlElement> second, Func<int, int, float3> coord)
|
Vertex[] GenerateSlicePlane(int su, int sv, Func<int, int, VxlElement?> first, Func<int, int, VxlElement?> second, Func<int, int, float3> coord)
|
||||||
{
|
{
|
||||||
var colors = new byte[su * sv];
|
var colors = new byte[su * sv];
|
||||||
var normals = new byte[su * sv];
|
var normals = new byte[su * sv];
|
||||||
@@ -68,8 +68,8 @@ namespace OpenRA.Mods.Cnc.Graphics
|
|||||||
for (var u = 0; u < su; u++)
|
for (var u = 0; u < su; u++)
|
||||||
{
|
{
|
||||||
var voxel = first(u, v) ?? second(u, v);
|
var voxel = first(u, v) ?? second(u, v);
|
||||||
colors[c] = voxel == null ? (byte)0 : voxel.Color;
|
colors[c] = voxel == null ? (byte)0 : voxel.Value.Color;
|
||||||
normals[c] = voxel == null ? (byte)0 : voxel.Normal;
|
normals[c] = voxel == null ? (byte)0 : voxel.Value.Normal;
|
||||||
c++;
|
c++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -99,7 +99,7 @@ namespace OpenRA.Mods.Cnc.Graphics
|
|||||||
|
|
||||||
IEnumerable<Vertex[]> GenerateSlicePlanes(VxlLimb l)
|
IEnumerable<Vertex[]> GenerateSlicePlanes(VxlLimb l)
|
||||||
{
|
{
|
||||||
VxlElement Get(int x, int y, int z)
|
VxlElement? Get(int x, int y, int z)
|
||||||
{
|
{
|
||||||
if (x < 0 || y < 0 || z < 0)
|
if (x < 0 || y < 0 || z < 0)
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -84,8 +84,9 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
protected static object LoadSpeeds(MiniYaml y)
|
protected static object LoadSpeeds(MiniYaml y)
|
||||||
{
|
{
|
||||||
var ret = new Dictionary<string, TerrainInfo>();
|
var speeds = y.ToDictionary()["TerrainSpeeds"].Nodes;
|
||||||
foreach (var t in y.ToDictionary()["TerrainSpeeds"].Nodes)
|
var ret = new Dictionary<string, TerrainInfo>(speeds.Count);
|
||||||
|
foreach (var t in speeds)
|
||||||
{
|
{
|
||||||
var speed = FieldLoader.GetValue<int>("speed", t.Value.Value);
|
var speed = FieldLoader.GetValue<int>("speed", t.Value.Value);
|
||||||
if (speed > 0)
|
if (speed > 0)
|
||||||
@@ -98,6 +99,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret.TrimExcess();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user