Introduce IdentifierManager to improve PDT evaluator performance.

This commit is contained in:
2022-11-01 13:47:04 +08:00
parent 3bfc7eb643
commit 2c9be2ef1e
12 changed files with 229 additions and 145 deletions

View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using Cryville.Common;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
@@ -112,19 +113,19 @@ namespace Cryville.Crtr {
}
[JsonIgnore]
public Dictionary<string, PropSrc> PropSrcs { get; private set; }
public Dictionary<int, PropSrc> PropSrcs { get; private set; }
protected void SubmitPropSrc(string name, PropSrc property) {
PropSrcs.Add(name, property);
PropSrcs.Add(IdentifierManager.SharedInstance.Request(name), property);
}
[JsonIgnore]
public Dictionary<string, PropOp> PropOps { get; private set; }
public Dictionary<int, PropOp> PropOps { get; private set; }
protected void SubmitPropOp(string name, PropOp property) {
PropOps.Add(name, property);
PropOps.Add(IdentifierManager.SharedInstance.Request(name), property);
}
protected ChartEvent() {
PropSrcs = new Dictionary<string, PropSrc>();
PropOps = new Dictionary<string, PropOp>();
PropSrcs = new Dictionary<int, PropSrc>();
PropOps = new Dictionary<int, PropOp>();
SubmitPropSrc("long", new PropSrc.Boolean(() => IsLong));
SubmitPropSrc("time", new PropSrc.BeatTime(() => time.Value));
SubmitPropSrc("endtime", new PropSrc.BeatTime(() => endtime.Value));

View File

@@ -115,12 +115,12 @@ namespace Cryville.Crtr {
cbus.ForwardByTime(dt);
bbus.ForwardByTime(dt);
UnityEngine.Profiling.Profiler.BeginSample("ChartPlayer.FeedJudge");
judge.StartFrame();
/*judge.StartFrame();
Game.InputManager.EnumerateEvents(ev => {
// Logger.Log("main", 0, "Input", ev.ToString());
judge.Feed(ev);
});
judge.EndFrame();
judge.EndFrame();*/
UnityEngine.Profiling.Profiler.EndSample();
UnityEngine.Profiling.Profiler.BeginSample("ChartPlayer.Forward");
UnityEngine.Profiling.Profiler.BeginSample("EventBus.Copy");

View File

@@ -1,3 +1,4 @@
using Cryville.Common;
using Cryville.Common.Pdt;
using Cryville.Common.Unity.Input;
using System.Collections.Generic;
@@ -7,24 +8,22 @@ namespace Cryville.Crtr {
readonly PdtRuleset _rs;
public Judge(PdtRuleset rs) {
_rs = rs;
foreach (var s in rs.scores)
scores.Add(s.Key, s.Value.init);
}
public void StartFrame() {
foreach (var s in rs.scores) {
var name = IdentifierManager.SharedInstance.Request(s.Key);
scoreDefs.Add(name, s.Value);
scores.Add(name, s.Value.init);
}
}
public void Feed(InputEvent ev) {
}
public void EndFrame() {
}
public readonly Dictionary<string, float> scores = new Dictionary<string, float>();
readonly Dictionary<string, string> ScoreCache = new Dictionary<string, string>();
public Dictionary<string, string> GetFormattedScoreStrings() {
public readonly Dictionary<int, ScoreDefinition> scoreDefs = new Dictionary<int, ScoreDefinition>();
public readonly Dictionary<int, float> scores = new Dictionary<int, float>();
readonly Dictionary<int, string> ScoreCache = new Dictionary<int, string>();
public Dictionary<int, string> GetFormattedScoreStrings() {
if (ScoreCache.Count == 0) {
foreach (var s in scores)
ScoreCache.Add(s.Key, s.Value.ToString(_rs.scores[s.Key].format));
ScoreCache.Add(s.Key, s.Value.ToString(scoreDefs[s.Key].format));
}
return ScoreCache;
}
@@ -51,7 +50,7 @@ namespace Cryville.Crtr {
public Dictionary<string, PdtExpression> scores;
}
public class ScoreOperation {
public string name;
public int name;
public PdtOperator op;
}
public class ScoreDefinition {

View File

@@ -1,66 +1,54 @@
using Cryville.Common.Pdt;
using Cryville.Common;
using Cryville.Common.Pdt;
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Cryville.Crtr {
public class PdtEvaluator : PdtEvaluatorBase {
static readonly Dictionary<OperatorSignature, PdtOperator> _shortops = new Dictionary<OperatorSignature, PdtOperator>();
static readonly Dictionary<string, PdtOperator> _longops = new Dictionary<string, PdtOperator>();
readonly Dictionary<string, PdtOperator> _ctxops = new Dictionary<string, PdtOperator>();
struct OperatorSignature : IEquatable<OperatorSignature> {
public string Name { get; private set; }
public int ParamCount { get; private set; }
readonly int _hash;
public OperatorSignature(string name, int paramCount) {
Name = name;
ParamCount = paramCount;
_hash = name.GetHashCode() ^ paramCount;
}
public override bool Equals(object obj) {
if (!(obj is OperatorSignature)) return false;
return Equals((OperatorSignature)obj);
}
public bool Equals(OperatorSignature other) {
return Name == other.Name && ParamCount == other.ParamCount;
}
public override int GetHashCode() {
return _hash;
}
}
static readonly Dictionary<PdtOperatorSignature, PdtOperator> _shortops = new Dictionary<PdtOperatorSignature, PdtOperator>();
static readonly Dictionary<int, PdtOperator> _longops = new Dictionary<int, PdtOperator>();
readonly Dictionary<int, PdtOperator> _ctxops = new Dictionary<int, PdtOperator>();
readonly byte[] _numbuf = new byte[4];
protected override void GetVariable(string name, out int type, out byte[] value) {
switch (name) {
case "w": LoadNum(ChartPlayer.hitRect.width); type = PdtInternalType.Number; value = _numbuf; return;
case "h": LoadNum(ChartPlayer.hitRect.height); type = PdtInternalType.Number; value = _numbuf; return;
case "true": LoadNum(1); type = PdtInternalType.Number; value = _numbuf; return;
case "false": LoadNum(0); type = PdtInternalType.Number; value = _numbuf; return;
default:
PropSrc prop;
string str;
if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) {
prop.Get(out type, out value);
}
else if (ContextJudge != null && ContextJudge.GetFormattedScoreStrings().TryGetValue(name, out str)) {
type = PdtInternalType.String;
value = GetBytes(str);
RevokePotentialConstant();
}
else {
PropSrc.Arbitrary result;
foreach (var cas in ContextCascade) {
if (cas.TryGetValue(name, out result)) {
result.Get(out type, out value);
return;
}
static int _var_w = IdentifierManager.SharedInstance.Request("w");
static int _var_h = IdentifierManager.SharedInstance.Request("h");
static int _var_true = IdentifierManager.SharedInstance.Request("true");
static int _var_false = IdentifierManager.SharedInstance.Request("false");
protected override void GetVariable(int name, out int type, out byte[] value) {
if (name == _var_w) { LoadNum(ChartPlayer.hitRect.width); type = PdtInternalType.Number; value = _numbuf; }
else if (name == _var_h) { LoadNum(ChartPlayer.hitRect.height); type = PdtInternalType.Number; value = _numbuf; }
else if (name == _var_true) { LoadNum(1); type = PdtInternalType.Number; value = _numbuf; }
else if (name == _var_false) { LoadNum(0); type = PdtInternalType.Number; value = _numbuf; }
else {
PropSrc prop;
string str;
if (ContextEvent != null && ContextEvent.PropSrcs.TryGetValue(name, out prop)) {
prop.Get(out type, out value);
}
else if (ContextJudge != null && ContextJudge.GetFormattedScoreStrings().TryGetValue(name, out str)) {
type = PdtInternalType.String;
value = GetBytes(str);
RevokePotentialConstant();
}
else {
PropSrc.Arbitrary result;
foreach (var cas in ContextCascade) {
if (cas.TryGetValue(name, out result)) {
result.Get(out type, out value);
return;
}
type = PdtInternalType.Undefined;
value = GetBytes(name);
}
return;
type = PdtInternalType.Undefined;
LoadNum(name);
value = _numbuf;
}
return;
}
}
unsafe void LoadNum(int value) {
fixed (byte* ptr = _numbuf) *(int*)ptr = value;
}
unsafe void LoadNum(float value) {
fixed (byte* ptr = _numbuf) *(float*)ptr = value;
}
@@ -75,31 +63,32 @@ namespace Cryville.Crtr {
}
return result;
}
protected override PdtOperator GetOperator(string name, int pc) {
static int _op_sep = IdentifierManager.SharedInstance.Request(",");
protected override PdtOperator GetOperator(PdtOperatorSignature sig) {
PdtOperator result;
if (name.Length == 1 && _shortops.TryGetValue(new OperatorSignature(name, pc), out result)) {
if (_shortops.TryGetValue(sig, out result)) {
return result;
}
else if (name == ",") {
result = new op_arr(pc);
_shortops.Add(new OperatorSignature(",", pc), result);
else if (sig.Name == _op_sep) {
result = new op_arr(sig.ParamCount);
_shortops.Add(new PdtOperatorSignature(",", sig.ParamCount), result);
return result;
}
else if (_longops.TryGetValue(name, out result)) {
else if (_longops.TryGetValue(sig.Name, out result)) {
return result;
}
else if (_ctxops.TryGetValue(name, out result)) {
else if (_ctxops.TryGetValue(sig.Name, out result)) {
return result;
}
else throw new KeyNotFoundException(string.Format("Undefined operator {0}({1})", name, pc));
else throw new KeyNotFoundException(string.Format("Undefined operator {0}", sig));
}
protected override bool Collapse(string name, PdtVariableMemory param) {
switch (name) {
case "&": return param.AsNumber() == 0;
case "|": return param.AsNumber() != 0;
default: throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", name));
}
static int _colop_and = IdentifierManager.SharedInstance.Request("&");
static int _colop_or = IdentifierManager.SharedInstance.Request("|");
protected override bool Collapse(int name, PdtVariableMemory param) {
if (name == _colop_and) return param.AsNumber() == 0;
else if(name == _colop_or) return param.AsNumber() != 0;
else throw new KeyNotFoundException(string.Format("Undefined collapse operator {0}", name));
}
public ChartEvent ContextEvent { private get; set; }
@@ -107,11 +96,11 @@ namespace Cryville.Crtr {
public Judge ContextJudge { private get; set; }
public PropSrc ContextSelfValue { private get; set; }
readonly List<Dictionary<string, PropSrc.Arbitrary>> ContextCascade = new List<Dictionary<string, PropSrc.Arbitrary>>();
readonly List<Dictionary<int, PropSrc.Arbitrary>> ContextCascade = new List<Dictionary<int, PropSrc.Arbitrary>>();
public void ContextCascadeInsert() {
ContextCascade.Add(new Dictionary<string, PropSrc.Arbitrary>());
ContextCascade.Add(new Dictionary<int, PropSrc.Arbitrary>());
}
public void ContextCascadeUpdate(string key, PropSrc.Arbitrary value) {
public void ContextCascadeUpdate(int key, PropSrc.Arbitrary value) {
ContextCascade[ContextCascade.Count - 1][key] = value;
}
public void ContextCascadeDiscard() {
@@ -119,29 +108,29 @@ namespace Cryville.Crtr {
}
public PdtEvaluator() {
_ctxops.Add("screen_edge", new func_screen_edge(() => ContextTransform));
_ctxops.Add("int", new func_int(() => ContextSelfValue));
_ctxops.Add("clamp", new func_clamp(() => ContextSelfValue));
_ctxops.Add("min", new func_min(() => ContextSelfValue));
_ctxops.Add("max", new func_max(() => ContextSelfValue));
_ctxops.Add(IdentifierManager.SharedInstance.Request("screen_edge"), new func_screen_edge(() => ContextTransform));
_ctxops.Add(IdentifierManager.SharedInstance.Request("int"), new func_int(() => ContextSelfValue));
_ctxops.Add(IdentifierManager.SharedInstance.Request("clamp"), new func_clamp(() => ContextSelfValue));
_ctxops.Add(IdentifierManager.SharedInstance.Request("min"), new func_min(() => ContextSelfValue));
_ctxops.Add(IdentifierManager.SharedInstance.Request("max"), new func_max(() => ContextSelfValue));
}
static PdtEvaluator() {
_shortops.Add(new OperatorSignature("*", 2), new op_mul_2());
_shortops.Add(new OperatorSignature("/", 2), new op_div_2());
_shortops.Add(new OperatorSignature("%", 2), new op_mod_2());
_shortops.Add(new PdtOperatorSignature("*", 2), new op_mul_2());
_shortops.Add(new PdtOperatorSignature("/", 2), new op_div_2());
_shortops.Add(new PdtOperatorSignature("%", 2), new op_mod_2());
_shortops.Add(new OperatorSignature("+", 1), new op_add_1());
_shortops.Add(new OperatorSignature("+", 2), new op_add_2());
_shortops.Add(new OperatorSignature("-", 1), new op_sub_1());
_shortops.Add(new OperatorSignature("-", 2), new op_sub_2());
_shortops.Add(new PdtOperatorSignature("+", 1), new op_add_1());
_shortops.Add(new PdtOperatorSignature("+", 2), new op_add_2());
_shortops.Add(new PdtOperatorSignature("-", 1), new op_sub_1());
_shortops.Add(new PdtOperatorSignature("-", 2), new op_sub_2());
_shortops.Add(new OperatorSignature("=", 2), new op_eq_2());
_shortops.Add(new OperatorSignature("<", 2), new op_lt_2());
_shortops.Add(new OperatorSignature(">", 2), new op_gt_2());
_shortops.Add(new PdtOperatorSignature("=", 2), new op_eq_2());
_shortops.Add(new PdtOperatorSignature("<", 2), new op_lt_2());
_shortops.Add(new PdtOperatorSignature(">", 2), new op_gt_2());
_shortops.Add(new OperatorSignature("!", 1), new op_not_1());
_shortops.Add(new PdtOperatorSignature("!", 1), new op_not_1());
_longops.Add("frame_seq", new func_frame_seq());
_longops.Add(IdentifierManager.SharedInstance.Request("frame_seq"), new func_frame_seq());
}
#region Operators
#pragma warning disable IDE1006

View File

@@ -1,4 +1,5 @@
using Cryville.Common.Pdt;
using Cryville.Common;
using Cryville.Common.Pdt;
using System;
using System.Collections.Generic;
using System.Reflection;
@@ -36,14 +37,14 @@ namespace Cryville.Crtr {
}
}
public class Enum<T> : PropOp {
readonly static Dictionary<string, int> _cache = new Dictionary<string, int>();
readonly static Dictionary<int, int> _cache = new Dictionary<int, int>();
readonly Action<T> _cb;
public Enum(Action<T> cb) {
if (!typeof(T).IsEnum)
throw new ArgumentException("Type is not enum");
var names = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Static);
for (int i = 0; i < names.Length; i++)
_cache[names[i].Name] = Convert.ToInt32(names[i].GetValue(null));
_cache[IdentifierManager.SharedInstance.Request(names[i].Name)] = Convert.ToInt32(names[i].GetValue(null));
_cb = cb;
}
protected override void Execute() {

View File

@@ -59,7 +59,7 @@ namespace Cryville.Crtr {
}
public class Constraint {
class ArbitraryOp : PropOp {
public string name;
public int name;
protected override void Execute() {
var op = GetOperand(0);
var value = new byte[op.Length];
@@ -114,15 +114,15 @@ namespace Cryville.Crtr {
}
public class PropertyKey {
public PropertyType Type { get; private set; }
public string Name { get; private set; }
public int Name { get; private set; }
public PropertyKey(PropertyType type, string name) {
Type = type;
Name = name;
Name = IdentifierManager.SharedInstance.Request(name);
}
public override string ToString() {
switch (Type) {
case PropertyType.Property: return Name;
case PropertyType.Variable: return "@var " + Name;
case PropertyType.Property: return Name.ToString();
case PropertyType.Variable: return string.Format("@var {0}", Name);
default: return string.Format("<{0}> {1}", Type, Name);
}
}
@@ -169,7 +169,7 @@ namespace Cryville.Crtr {
public pop_identstr(Action<string> cb) { _cb = cb; }
protected override void Execute() {
var op = GetOperand(0);
if (op.Type == PdtInternalType.Undefined) _cb(op.AsIdentifier());
if (op.Type == PdtInternalType.Undefined) _cb((string)IdentifierManager.SharedInstance.Retrieve(op.AsIdentifier()));
else if (op.Type == PdtInternalType.String) _cb(op.AsString());
else throw new InvalidCastException("Not an identifier or string");
}
@@ -183,7 +183,7 @@ namespace Cryville.Crtr {
var op = GetOperand(i);
if (op.Type != PdtInternalType.Undefined)
throw new InvalidCastException("Not an identifier");
result[i] = op.AsIdentifier();
result[i] = (string)IdentifierManager.SharedInstance.Retrieve(op.AsIdentifier());
}
_cb(result);
}