Optimize GC for status info.

This commit is contained in:
2023-01-31 22:56:06 +08:00
parent cbc874dd72
commit 969fdc8069
6 changed files with 75 additions and 36 deletions

View File

@@ -0,0 +1,23 @@
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using IFont = UnityEngine.Font;
namespace Cryville.Common.Unity.UI {
[RequireComponent(typeof(TextMeshProUGUI))]
public class TMPAutoFont : MonoBehaviour {
public static readonly List<string> Fonts = new List<string> {
"Arial",
};
static TMP_FontAsset _font;
TextMeshProUGUI _text;
void Awake() {
_text = GetComponent<TextMeshProUGUI>();
if (_font == null) {
var _ifont = new IFont("C:/Windows/Fonts/arial.ttf");
_font = TMP_FontAsset.CreateFontAsset(_ifont);
}
_text.font = _font;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 57404eb6519ecae44b051485280e879f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,6 +1,7 @@
#define BUILD #define BUILD
using Cryville.Common; using Cryville.Common;
using Cryville.Common.Buffers;
using Cryville.Crtr.Config; using Cryville.Crtr.Config;
using Cryville.Crtr.Event; using Cryville.Crtr.Event;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -8,7 +9,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Text.Formatting;
using System.Threading; using System.Threading;
using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.Networking; using UnityEngine.Networking;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
@@ -45,7 +48,9 @@ namespace Cryville.Crtr {
static bool initialized; static bool initialized;
static Text logs; static Text logs;
Text status; TextMeshProUGUI status;
readonly TargetString statusstr = new TargetString();
readonly StringBuffer statusbuf = new StringBuffer();
static Vector2 screenSize; static Vector2 screenSize;
public static Rect hitRect; public static Rect hitRect;
@@ -81,7 +86,7 @@ namespace Cryville.Crtr {
} }
OnSettingsUpdate(); OnSettingsUpdate();
status = GameObject.Find("Status").GetComponent<Text>(); status = GameObject.Find("Status").GetComponent<TextMeshProUGUI>();
texHandler = new DownloadHandlerTexture(); texHandler = new DownloadHandlerTexture();
#if BUILD #if BUILD
@@ -107,7 +112,6 @@ namespace Cryville.Crtr {
if (texLoader != null) texLoader.Dispose(); if (texLoader != null) texLoader.Dispose();
if (inputProxy != null) inputProxy.Dispose(); if (inputProxy != null) inputProxy.Dispose();
if (texs != null) foreach (var t in texs) Texture.Destroy(t.Value); if (texs != null) foreach (var t in texs) Texture.Destroy(t.Value);
Camera.onPostRender -= OnCameraPostRender;
GC.Collect(); GC.Collect();
} }
@@ -216,7 +220,6 @@ namespace Cryville.Crtr {
} }
} }
} }
string timetext = string.Empty;
void LogUpdate() { void LogUpdate() {
string _logs = logs.text; string _logs = logs.text;
Game.MainLogger.Enumerate((level, module, msg) => { Game.MainLogger.Enumerate((level, module, msg) => {
@@ -236,7 +239,8 @@ namespace Cryville.Crtr {
); );
}); });
logs.text = _logs.Substring(Mathf.Max(0, _logs.IndexOf('\n', Mathf.Max(0, _logs.Length - 4096)))); logs.text = _logs.Substring(Mathf.Max(0, _logs.IndexOf('\n', Mathf.Max(0, _logs.Length - 4096))));
var sttext = string.Format( statusbuf.Clear();
statusbuf.AppendFormat(
"FPS: i{0:0} / s{1:0}\nSMem: {2:N0} / {3:N0}\nIMem: {4:N0} / {5:N0}", "FPS: i{0:0} / s{1:0}\nSMem: {2:N0} / {3:N0}\nIMem: {4:N0} / {5:N0}",
1 / Time.deltaTime, 1 / Time.deltaTime,
1 / Time.smoothDeltaTime, 1 / Time.smoothDeltaTime,
@@ -253,25 +257,27 @@ namespace Cryville.Crtr {
#endif #endif
); );
if (started) { if (started) {
sttext += string.Format( statusbuf.AppendFormat(
"\nStates: c{0} / b{1}", "\nStates: c{0} / b{1}",
cbus.ActiveStateCount, bbus.ActiveStateCount cbus.ActiveStateCount, bbus.ActiveStateCount
); );
sttext += timetext; statusbuf.AppendFormat(
if (judge != null) sttext += "\n== Scores ==\n" + judge.GetFullFormattedScoreString(); "\nSTime: {0:G17}s {3}\ndATime: {1:+0.0ms;-0.0ms;0} {3}\ndITime: {2:+0.0ms;-0.0ms;0} {3}",
cbus.Time,
(Game.AudioClient.Position - atime0 - cbus.Time) * 1e3,
(inputProxy.GetTimestampAverage() - cbus.Time) * 1e3,
forceSyncFrames != 0 ? "(force sync)" : ""
);
if (judge != null) {
statusbuf.Append("\n== Scores ==\n");
var fullScoreStr = judge.GetFullFormattedScoreString();
statusbuf.Append(fullScoreStr.TrustedAsArray(), 0, fullScoreStr.Length);
}
} }
status.text = sttext; statusstr.Length = statusbuf.Count;
} var arr = statusstr.TrustedAsArray();
void OnCameraPostRender(Camera cam) { statusbuf.CopyTo(0, arr, 0, statusbuf.Count);
if (!started) return; status.SetText(arr, 0, statusbuf.Count);
if (!logEnabled) return;
timetext = string.Format(
"\nSTime: {0:R}s {3}\ndATime: {1:+0.0ms;-0.0ms;0} {3}\ndITime: {2:+0.0ms;-0.0ms;0} {3}",
cbus.Time,
(Game.AudioClient.Position - atime0 - cbus.Time) * 1e3,
(inputProxy.GetTimestampAverage() - cbus.Time) * 1e3,
forceSyncFrames != 0 ? "(force sync)" : ""
);
} }
#endregion #endregion
@@ -302,7 +308,7 @@ namespace Cryville.Crtr {
bool logEnabled = true; bool logEnabled = true;
public void ToggleLogs() { public void ToggleLogs() {
logs.text = ""; logs.text = "";
status.text = ""; status.SetText("");
logEnabled = !logEnabled; logEnabled = !logEnabled;
} }
@@ -330,8 +336,6 @@ namespace Cryville.Crtr {
Game.NetworkTaskWorker.SuspendBackgroundTasks(); Game.NetworkTaskWorker.SuspendBackgroundTasks();
Game.AudioSession = Game.AudioSequencer.NewSession(); Game.AudioSession = Game.AudioSequencer.NewSession();
Camera.onPostRender += OnCameraPostRender;
var hitPlane = new Plane(Vector3.forward, Vector3.zero); var hitPlane = new Plane(Vector3.forward, Vector3.zero);
var r0 = Camera.main.ViewportPointToRay(new Vector3(0, 0, 1)); var r0 = Camera.main.ViewportPointToRay(new Vector3(0, 0, 1));
float dist; float dist;

View File

@@ -205,6 +205,9 @@ namespace Cryville.Crtr {
readonly Dictionary<int, string> scoreStringCache = new Dictionary<int, string>(); readonly Dictionary<int, string> scoreStringCache = new Dictionary<int, string>();
readonly Dictionary<int, PropSrc> scoreStringSrcs = new Dictionary<int, PropSrc>(); readonly Dictionary<int, PropSrc> scoreStringSrcs = new Dictionary<int, PropSrc>();
readonly ArrayPool<byte> scoreStringPool = new ArrayPool<byte>(); readonly ArrayPool<byte> scoreStringPool = new ArrayPool<byte>();
readonly Dictionary<int, string> scoreFormatCache = new Dictionary<int, string>();
readonly TargetString scoreFullStr = new TargetString();
readonly StringBuffer scoreFullBuf = new StringBuffer();
void InitScores() { void InitScores() {
foreach (var s in _rs.scores) { foreach (var s in _rs.scores) {
var key = s.Key.Key; var key = s.Key.Key;
@@ -217,6 +220,7 @@ namespace Cryville.Crtr {
scores.Add(key, s.Value.init); scores.Add(key, s.Value.init);
scoreStringCache.Add(scoreStringKeys[key], null); scoreStringCache.Add(scoreStringKeys[key], null);
scoreStringSrcs.Add(scoreStringKeys[key], new ScoreStringSrc(scoreStringPool, () => scores[key], scoreDefs[key].format)); scoreStringSrcs.Add(scoreStringKeys[key], new ScoreStringSrc(scoreStringPool, () => scores[key], scoreDefs[key].format));
scoreFormatCache[key] = string.Format("{{0:{0}}}", s.Value.format);
} }
} }
void InvalidateScore(int key) { void InvalidateScore(int key) {
@@ -224,28 +228,24 @@ namespace Cryville.Crtr {
scoreStringCache[scoreStringKeys[key]] = null; scoreStringCache[scoreStringKeys[key]] = null;
scoreStringSrcs[scoreStringKeys[key]].Invalidate(); scoreStringSrcs[scoreStringKeys[key]].Invalidate();
} }
string GetScoreString(int key) {
var result = scoreStringCache[key];
if (result == null) {
var rkey = scoreStringKeysRev[key];
return scoreStringCache[key] = scores[rkey].ToString(scoreDefs[rkey].format, CultureInfo.InvariantCulture);
}
else return result;
}
public bool TryGetScoreSrc(int key, out PropSrc value) { public bool TryGetScoreSrc(int key, out PropSrc value) {
return scoreSrcs.TryGetValue(key, out value); return scoreSrcs.TryGetValue(key, out value);
} }
public bool TryGetScoreStringSrc(int key, out PropSrc value) { public bool TryGetScoreStringSrc(int key, out PropSrc value) {
return scoreStringSrcs.TryGetValue(key, out value); return scoreStringSrcs.TryGetValue(key, out value);
} }
public string GetFullFormattedScoreString() { public TargetString GetFullFormattedScoreString() {
bool flag = false; bool flag = false;
string result = ""; scoreFullBuf.Clear();
foreach (var s in scores.Keys) { foreach (var s in scores.Keys) {
result += string.Format(flag ? "\n{0}: {1}" : "{0}: {1}", IdentifierManager.SharedInstance.Retrieve(s), GetScoreString(scoreStringKeys[s])); scoreFullBuf.AppendFormat(flag ? "\n{0}: " : "{0}: ", (string)IdentifierManager.SharedInstance.Retrieve(s));
scoreFullBuf.AppendFormat(scoreFormatCache[s], scores[s]);
flag = true; flag = true;
} }
return result; scoreFullStr.Length = scoreFullBuf.Count;
var arr = scoreFullStr.TrustedAsArray();
scoreFullBuf.CopyTo(0, arr, 0, scoreFullBuf.Count);
return scoreFullStr;
} }
class ScoreStringSrc : PropSrc { class ScoreStringSrc : PropSrc {
readonly Func<float> _cb; readonly Func<float> _cb;

View File

@@ -4,7 +4,8 @@
"references": [ "references": [
"GUID:d8ea0e0da3ad53a45b65c912ffcacab0", "GUID:d8ea0e0da3ad53a45b65c912ffcacab0",
"GUID:5686e5ee69d0e084c843d61c240d7fdb", "GUID:5686e5ee69d0e084c843d61c240d7fdb",
"GUID:2922aa74af3b2854e81b8a8b286d8206" "GUID:2922aa74af3b2854e81b8a8b286d8206",
"GUID:6055be8ebefd69e48b49212b09b47b2f"
], ],
"includePlatforms": [], "includePlatforms": [],
"excludePlatforms": [], "excludePlatforms": [],

Binary file not shown.