1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class StartupTimer
{
private static readonly StartupTimer instance;
static StartupTimer() => instance = new StartupTimer();
private StartupTimer() => steps = new List<Step>();
public static StartupTimer Instance => instance;
private struct Step
{
public string name;
public double time; // 秒(从启动开始)
}
private List<Step> steps;
public void Mark(string step) => steps.Add(new Step { name = step, time = Time.realtimeSinceStartupAsDouble });
public void PrintSummary()
{
if (steps.Count == 0)
{
Debug.Log("没有记录任何步骤,无法生成总结。");
return;
}
double totalSeconds = steps[^1].time; // 最后一个步骤的绝对时间即为总耗时
long totalMs = (long)Math.Round(totalSeconds * 1000.0, MidpointRounding.AwayFromZero);
Debug.Log($"=== 启动时间总结 ===");
Debug.Log($"总启动耗时: {totalMs} ms\n");
// 计算最大名称长度(考虑步骤名、表头“步骤名称”和汇总行“总用时”)
int maxNameLength = steps.Max(s => s.name.Length);
int nameWidth = Math.Max(maxNameLength, "步骤名称".Length);
nameWidth = Math.Max(nameWidth, "总用时".Length) + 4;
// 准备数据列表
var rows = new List<(string name, long timeMs, long deltaMs, string ratioStr)>();
long prevTimeMs = 0;
for (int i = 0; i < steps.Count; i++)
{
long timeMs = (long)Math.Round(steps[i].time * 1000.0, MidpointRounding.AwayFromZero);
long deltaMs = i == 0 ? 0 : timeMs - prevTimeMs;
// 占比 = 增量 / 总耗时 * 100%
double ratio = totalMs > 0 ? (deltaMs / (double)totalMs) * 100.0 : 0;
string ratioStr = ratio.ToString("F1") + "%";
rows.Add((steps[i].name, timeMs, deltaMs, ratioStr));
prevTimeMs = timeMs;
}
// 表头
string header = $"{"步骤名称",-nameWidth} {"耗时(ms)",8} {"增量(ms)",8} {"占比",6}";
Debug.Log(header);
// 输出每一行
foreach (var row in rows)
{
string line = $"{row.name,-nameWidth} {row.timeMs,8} {row.deltaMs,8} {row.ratioStr,6}";
Debug.Log(line);
}
// 汇总行(总用时)
Debug.Log(new string('-', header.Length)); // 分隔线
string totalLine = $"{"总用时",-nameWidth} {totalMs,8} {"",8} {"",6}";
Debug.Log(totalLine);
// 步骤间耗时明细(可选)
if (steps.Count > 1)
{
Debug.Log("\n--- 步骤间耗时明细 ---");
for (int i = 1; i < steps.Count; i++)
{
double elapsedSeconds = steps[i].time - steps[i - 1].time;
Debug.Log($"{steps[i - 1].name} → {steps[i].name}: {FormatMilliseconds(elapsedSeconds)} ms");
}
}
}
public void Reset() => steps.Clear();
private string FormatMilliseconds(double seconds)
{
long ms = (long)Math.Round(seconds * 1000.0, MidpointRounding.AwayFromZero);
return ms.ToString();
}
// 静态便捷方法
public static void Mark(string step) => Instance.Mark(step);
public static void PrintSummary() => Instance.PrintSummary();
public static void Reset() => Instance.Reset();
}
|