Optimize property param decoding

This commit is contained in:
Crypto137 2024-08-26 15:28:43 +03:00
parent efa892a1bc
commit 17a014ee00
4 changed files with 40 additions and 36 deletions

View file

@ -196,8 +196,10 @@ namespace MHServerEmu.Games.GameData.Calligraphy
{
if (paramsSetMask == 0xff) return left == right;
var leftParams = left.GetParams();
var rightParams = right.GetParams();
Span<PropertyParam> leftParams = stackalloc PropertyParam[Property.MaxParamCount];
Span<PropertyParam> rightParams = stackalloc PropertyParam[Property.MaxParamCount];
left.GetParams(ref leftParams);
right.GetParams(ref rightParams);
for (int i = 0; i < Property.MaxParamCount; i++)
{
@ -218,8 +220,10 @@ namespace MHServerEmu.Games.GameData.Calligraphy
{
if (paramsSetMask == 0xff) return;
PropertyParam[] destParams = destId.GetParams();
PropertyParam[] sourceParams = sourceId.GetParams();
Span<PropertyParam> destParams = stackalloc PropertyParam[Property.MaxParamCount];
Span<PropertyParam> sourceParams = stackalloc PropertyParam[Property.MaxParamCount];
destId.GetParams(ref destParams);
sourceId.GetParams(ref sourceParams);
for (int i = 0; i < Property.MaxParamCount; i++)
{

View file

@ -2425,7 +2425,10 @@ namespace MHServerEmu.Games.Properties.Evals
PropertyInfoTable propInfoTable = GameDatabase.PropertyInfoTable;
PropertyEnum propEnum = propInfoTable.GetPropertyEnumFromPrototype(assignPropEvalParamsProto.Prop);
PropertyInfo propInfo = propInfoTable.LookupPropertyInfo(propEnum);
PropertyParam[] paramValues = propInfo.DefaultParamValues;
Span<PropertyParam> paramValues = stackalloc PropertyParam[Property.MaxParamCount];
propInfo.DefaultParamValues.CopyTo(paramValues);
for (int i = 0; i < propInfo.ParamCount; i++)
{
if (i >= 4) break;
@ -2462,7 +2465,7 @@ namespace MHServerEmu.Games.Properties.Evals
}
}
PropertyId propId = new (propEnum, paramValues);
PropertyId propId = new(propEnum, paramValues);
switch (propInfo.DataType)
{
@ -2629,7 +2632,7 @@ namespace MHServerEmu.Games.Properties.Evals
if (propInfoParams.ParamCount != propInfoValue.ParamCount)
return evalVar;
PropertyParam[] paramValues = new PropertyParam[propInfoParams.ParamCount];
Span<PropertyParam> paramValues = stackalloc PropertyParam[propInfoParams.ParamCount];
for (int i = 0; i < propInfoParams.ParamCount; ++i)
{
if (propInfoParams.GetParamType(i) != propInfoValue.GetParamType(i)) return evalVar;
@ -2653,7 +2656,7 @@ namespace MHServerEmu.Games.Properties.Evals
}
}
PropertyId propIdValue = new (propEnum, paramValues);
PropertyId propIdValue = new(propEnum, paramValues);
switch (propInfoValue.DataType)
{
@ -2704,7 +2707,9 @@ namespace MHServerEmu.Games.Properties.Evals
PropertyInfoTable propInfoTable = GameDatabase.PropertyInfoTable;
PropertyEnum propEnum = propInfoTable.GetPropertyEnumFromPrototype(loadPropEvalParamsProto.Prop);
PropertyInfo propInfo = propInfoTable.LookupPropertyInfo(propEnum);
PropertyParam[] paramValues = propInfo.DefaultParamValues;
Span<PropertyParam> paramValues = stackalloc PropertyParam[Property.MaxParamCount];
propInfo.DefaultParamValues.CopyTo(paramValues);
for (int i = 0; i < propInfo.ParamCount; ++i)
{
@ -2742,7 +2747,7 @@ namespace MHServerEmu.Games.Properties.Evals
}
}
PropertyId propId = new (propEnum, paramValues);
PropertyId propId = new(propEnum, paramValues);
switch (propInfo.DataType)
{

View file

@ -40,13 +40,13 @@ namespace MHServerEmu.Games.Properties
public PropertyId(PropertyEnum propertyEnum, PropertyParam[] @params)
{
PropertyInfo info = GameDatabase.PropertyInfoTable.LookupPropertyInfo(propertyEnum);
Raw = info.EncodeParameters(propertyEnum, @params).Raw;
Raw = info.EncodeParameters(propertyEnum, @params.AsSpan()).Raw;
}
/// <summary>
/// Constructs a <see cref="PropertyId"/> with the provided params
/// </summary>
public PropertyId(PropertyEnum propertyEnum, ReadOnlySpan<PropertyParam> @params)
public PropertyId(PropertyEnum propertyEnum, in ReadOnlySpan<PropertyParam> @params)
{
PropertyInfo info = GameDatabase.PropertyInfoTable.LookupPropertyInfo(propertyEnum);
Raw = info.EncodeParameters(propertyEnum, @params).Raw;
@ -189,16 +189,18 @@ namespace MHServerEmu.Games.Properties
/// </summary>
public PropertyParam GetParam(int index)
{
return GetParams()[index];
Span<PropertyParam> @params = stackalloc PropertyParam[Property.MaxParamCount];
GetParams(ref @params);
return @params[index];
}
/// <summary>
/// Decodes and returns encoded param values.
/// Decodes encoded param values to a <see cref="Span{T}"/>.
/// </summary>
public PropertyParam[] GetParams()
public void GetParams(ref Span<PropertyParam> @params)
{
PropertyInfo info = GameDatabase.PropertyInfoTable.LookupPropertyInfo(Enum);
return info.DecodeParameters(this);
info.DecodeParameters(this, ref @params);
}
}
}

View file

@ -68,36 +68,27 @@ namespace MHServerEmu.Games.Properties
}
}
public PropertyParam[] DecodeParameters(PropertyId propertyId)
public void DecodeParameters(PropertyId propertyId, ref Span<PropertyParam> @params)
{
if (ParamCount == 0) return new PropertyParam[Property.MaxParamCount];
if (ParamCount == 0)
{
@params.Clear();
return;
}
ulong encodedParams = propertyId.Raw & Property.ParamMask;
PropertyParam[] decodedParams = new PropertyParam[Property.MaxParamCount];
for (int i = 0; i < ParamCount; i++)
decodedParams[i] = (PropertyParam)(int)((encodedParams >> _paramOffsets[i]) & ((1ul << _paramBitCounts[i]) - 1));
@params[i] = (PropertyParam)(int)((encodedParams >> _paramOffsets[i]) & ((1ul << _paramBitCounts[i]) - 1));
return decodedParams;
for (int i = ParamCount; i < Property.MaxParamCount; i++)
@params[i] = 0;
}
// There's a bunch of (client-accurate) copypasted code here for encoding that allows us to avoid allocating param arrays in some cases.
// Feel free to make this more DRY if there is a smarter way of doing this without losing performance.
public PropertyId EncodeParameters(PropertyEnum propertyEnum, PropertyParam[] @params)
{
switch (ParamCount)
{
case 0: return new(propertyEnum);
case 1: return EncodeParameters(propertyEnum, @params[0]);
case 2: return EncodeParameters(propertyEnum, @params[0], @params[1]);
case 3: return EncodeParameters(propertyEnum, @params[0], @params[1], @params[2]);
case 4: return EncodeParameters(propertyEnum, @params[0], @params[1], @params[2], @params[3]);
default: return Logger.WarnReturn(new PropertyId(propertyEnum), $"EncodeParameters(): Invalid param count {ParamCount}");
}
}
public PropertyId EncodeParameters(PropertyEnum propertyEnum, ReadOnlySpan<PropertyParam> @params)
public PropertyId EncodeParameters(PropertyEnum propertyEnum, in ReadOnlySpan<PropertyParam> @params)
{
switch (ParamCount)
{
@ -166,7 +157,9 @@ namespace MHServerEmu.Games.Properties
{
StringBuilder sb = new();
sb.Append(PropertyName);
var @params = id.GetParams();
Span<PropertyParam> @params = stackalloc PropertyParam[Property.MaxParamCount];
id.GetParams(ref @params);
for (int i = 0; i < ParamCount; i++)
{