Optimize GC for input proxy.

This commit is contained in:
2023-03-11 21:40:34 +08:00
parent 22190a29c1
commit 9aaa96fe10

View File

@@ -5,7 +5,7 @@ using Cryville.Crtr.Config;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using UnityEngine; using RVector3 = UnityEngine.Vector3;
namespace Cryville.Crtr { namespace Cryville.Crtr {
public class InputProxy : IDisposable { public class InputProxy : IDisposable {
@@ -13,12 +13,11 @@ namespace Cryville.Crtr {
readonly PdtRuleset _ruleset; readonly PdtRuleset _ruleset;
readonly Judge _judge; readonly Judge _judge;
public InputProxy(PdtRuleset ruleset, Judge judge) { public InputProxy(PdtRuleset ruleset, Judge judge) {
unsafe { for (int i = 0; i <= MAX_DEPTH; i++) {
fixed (byte* ptr = _vecbuf) { var vecsrc = new InputVectorSrc();
*(int*)(ptr + 3 * sizeof(float)) = PdtInternalType.Number; _vecsrcs[i] = vecsrc;
} _vecops[i] = new InputVectorOp(vecsrc);
} }
_vecsrc = new PropSrc.Arbitrary(PdtInternalType.Vector, _vecbuf);
_etor = ChartPlayer.etor; _etor = ChartPlayer.etor;
_ruleset = ruleset; _ruleset = ruleset;
_judge = judge; _judge = judge;
@@ -175,9 +174,54 @@ namespace Cryville.Crtr {
readonly object _lock = new object(); readonly object _lock = new object();
static readonly int _var_value = IdentifierManager.SharedInstance.Request("value"); static readonly int _var_value = IdentifierManager.SharedInstance.Request("value");
static readonly PropOp.Arbitrary _arbop = new PropOp.Arbitrary(); const int MAX_DEPTH = 15;
readonly byte[] _vecbuf = new byte[3 * sizeof(float) + sizeof(int)]; const int MAX_DIMENSION = 3;
readonly PropSrc.Arbitrary _vecsrc; readonly InputVectorSrc[] _vecsrcs = new InputVectorSrc[MAX_DEPTH + 1];
readonly InputVectorOp[] _vecops = new InputVectorOp[MAX_DEPTH + 1];
unsafe class InputVectorSrc : PropSrc.FixedBuffer {
public InputVectorSrc() : base(PdtInternalType.Vector, MAX_DIMENSION * sizeof(float) + sizeof(int)) {
fixed (byte* ptr = buf) {
*(int*)(ptr + MAX_DIMENSION * sizeof(float)) = PdtInternalType.Number;
}
}
public bool IsNull { get; set; }
public void Set(RVector3 vec) {
fixed (byte* _ptr = buf) {
*(RVector3*)_ptr = vec;
}
Invalidate();
}
}
class InputVectorOp : PropOp {
readonly InputVectorSrc _src;
public InputVectorOp(InputVectorSrc src) {
_src = src;
}
protected override void Execute() {
var op = GetOperand(0);
if (op.Type == PdtInternalType.Null) {
_src.IsNull = true;
}
else {
var vec = new RVector3();
int dim;
if (op.Type == PdtInternalType.Number) dim = 1;
else if (op.Type == PdtInternalType.Vector) {
int arrtype, _;
op.GetArraySuffix(out arrtype, out _);
if (arrtype != PdtInternalType.Number)
throw new InvalidCastException("Not a vector of numbers");
dim = Math.Min(3, (op.Length - sizeof(int)) / sizeof(float));
}
else throw new InvalidCastException("Invalid vector");
for (int i = 0; i < dim; i++) {
vec[i] = op.AsNumber(i * sizeof(float));
}
_src.IsNull = false;
_src.Set(vec);
}
}
}
readonly Dictionary<InputHandler, double> _timeOrigins = new Dictionary<InputHandler, double>(); readonly Dictionary<InputHandler, double> _timeOrigins = new Dictionary<InputHandler, double>();
readonly Dictionary<InputSource, int> _activeCounts = new Dictionary<InputSource, int>(); readonly Dictionary<InputSource, int> _activeCounts = new Dictionary<InputSource, int>();
readonly Dictionary<InputIdentifier, float> _vect = new Dictionary<InputIdentifier, float>(); readonly Dictionary<InputIdentifier, float> _vect = new Dictionary<InputIdentifier, float>();
@@ -195,11 +239,8 @@ namespace Cryville.Crtr {
OnInput(id, proxy.Target, ft, tt, true); OnInput(id, proxy.Target, ft, tt, true);
} }
else { else {
fixed (byte* ptr = _vecbuf) { _vecsrcs[0].Set(vec.Vector);
*(Vector3*)ptr = vec.Vector; _etor.ContextCascadeUpdate(_var_value, _vecsrcs[0]);
}
_vecsrc.Invalidate();
_etor.ContextCascadeUpdate(_var_value, _vecsrc);
OnInput(id, proxy.Target, ft, tt, false); OnInput(id, proxy.Target, ft, tt, false);
} }
_vect[id] = tt; _vect[id] = tt;
@@ -210,14 +251,19 @@ namespace Cryville.Crtr {
static readonly int _var_fv = IdentifierManager.SharedInstance.Request("fv"); static readonly int _var_fv = IdentifierManager.SharedInstance.Request("fv");
static readonly int _var_tv = IdentifierManager.SharedInstance.Request("tv"); static readonly int _var_tv = IdentifierManager.SharedInstance.Request("tv");
unsafe void OnInput(InputIdentifier id, Identifier target, float ft, float tt, bool nullflag, int depth = 0) { unsafe void OnInput(InputIdentifier id, Identifier target, float ft, float tt, bool nullflag, int depth = 0) {
if (depth >= 16) throw new InputProxyException("Input propagation limit reached\nThe ruleset has invalid input definitions"); if (depth >= MAX_DEPTH) throw new InputProxyException("Input propagation limit reached\nThe ruleset has invalid input definitions");
var def = _ruleset.inputs[target]; var def = _ruleset.inputs[target];
if (def.pass != null) { if (def.pass != null) {
foreach (var p in def.pass) { foreach (var p in def.pass) {
_etor.ContextCascadeInsert(); _etor.ContextCascadeInsert();
_arbop.Name = _var_value; bool newNullFlag = nullflag;
if (!nullflag) _etor.Evaluate(_arbop, p.Value); if (!newNullFlag) {
OnInput(id, p.Key, ft, tt, nullflag, depth + 1); ChartPlayer.etor.Evaluate(_vecops[depth + 1], p.Value);
newNullFlag = _vecsrcs[depth + 1].IsNull;
if (newNullFlag) ChartPlayer.etor.ContextCascadeUpdate(_var_value, PropSrc.Null);
else ChartPlayer.etor.ContextCascadeUpdate(_var_value, _vecsrcs[depth + 1]);
}
OnInput(id, p.Key, ft, tt, newNullFlag, depth + 1);
_etor.ContextCascadeDiscard(); _etor.ContextCascadeDiscard();
} }
} }