暫無描述
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BottleneckControl.cs 6.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using UnityEngine;
  5. using UnityEngine.AdaptivePerformance;
  6. using UnityEngine.UI;
  7. public class BottleneckControl : MonoBehaviour
  8. {
  9. class Marker
  10. {
  11. public float time;
  12. public string label;
  13. public int objectCount;
  14. }
  15. IAdaptivePerformance ap;
  16. SampleFactory factory;
  17. public GameObject cpuLoader;
  18. public GameObject gpuLoader;
  19. float timer = 0;
  20. bool switching = false;
  21. public float timeOut = 40;
  22. float timeOuttimer = 0;
  23. public float waitTimeBeforeSwitch = 5;
  24. public float waitTimeAfterTargetReached = 3;
  25. string state = "Waiting for Target FPS";
  26. public Text bottleneckStatus;
  27. PerformanceBottleneck targetBottleneck = PerformanceBottleneck.CPU;
  28. BottleneckUI bottleneckUI;
  29. System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
  30. List<Marker> markers = new List<Marker>();
  31. public int stateChangeIterations = 3;
  32. void Start()
  33. {
  34. StartCoroutine(Begin());
  35. }
  36. IEnumerator Begin()
  37. {
  38. yield return new WaitForSeconds(1);
  39. factory = FindObjectOfType<SampleFactory>();
  40. bottleneckUI = FindObjectOfType<BottleneckUI>();
  41. factory.RunTest = false;
  42. timer = waitTimeBeforeSwitch;
  43. ap = Holder.Instance;
  44. if (ap == null || !ap.Active)
  45. {
  46. state = "Adaptive Performance not active";
  47. Debug.Log("[AP Bottleneck] Adaptive Performance not active");
  48. FinishTest();
  49. }
  50. else
  51. {
  52. timeOuttimer = timeOut;
  53. watch.Start();
  54. factory.prefab = cpuLoader;
  55. factory.RunTest = true;
  56. state = "Ramping up CPU load";
  57. StartCoroutine(ObserveBottleneck());
  58. markers.Add(new Marker { label = state, time = watch.ElapsedMilliseconds, objectCount = factory.internalObjs });
  59. Debug.Log("[AP Bottleneck] Starting Test");
  60. }
  61. bottleneckStatus.text = state;
  62. }
  63. IEnumerator ObserveBottleneck()
  64. {
  65. while (true)
  66. {
  67. if (timer < 0)
  68. {
  69. timer = waitTimeBeforeSwitch;
  70. StartCoroutine(NextBottleneck());
  71. }
  72. yield return new WaitForEndOfFrame();
  73. }
  74. }
  75. void FinishTest()
  76. {
  77. markers.Add(new Marker { time = watch.ElapsedMilliseconds, label = "Test Finish", objectCount = factory.internalObjs });
  78. foreach (var t in markers)
  79. {
  80. Debug.LogFormat("Timestamp : {0} s , Label : {1} , Objects : {2} \n", t.time / 1000f, t.label, t.objectCount);
  81. }
  82. #if UNITY_EDITOR
  83. UnityEditor.EditorApplication.isPlaying = false;
  84. #else
  85. Application.Quit();
  86. #endif
  87. }
  88. IEnumerator NextBottleneck(bool timeout = false)
  89. {
  90. switching = true;
  91. stateChangeIterations--;
  92. timeOuttimer = timeOut;
  93. Debug.Log($"State change = {stateChangeIterations}");
  94. switch (targetBottleneck)
  95. {
  96. case PerformanceBottleneck.CPU:
  97. yield return StartCoroutine(LogResult("GPU", timeout));
  98. factory.FlushObjects();
  99. factory.RunTest = true;
  100. state = "Ramping up GPU Load";
  101. factory.prefab = gpuLoader;
  102. factory.spawnAmount = 0.1f;
  103. targetBottleneck = PerformanceBottleneck.GPU;
  104. break;
  105. case PerformanceBottleneck.GPU:
  106. yield return StartCoroutine(LogResult("TargetFrameRate", timeout));
  107. factory.FlushObjects();
  108. factory.RunTest = false;
  109. state = "Waiting for TargetFrameRate";
  110. targetBottleneck = PerformanceBottleneck.TargetFrameRate;
  111. break;
  112. case PerformanceBottleneck.TargetFrameRate:
  113. yield return StartCoroutine(LogResult("CPU", timeout));
  114. factory.FlushObjects();
  115. factory.RunTest = true;
  116. state = "Ramping up CPU Load";
  117. factory.prefab = cpuLoader;
  118. factory.spawnAmount = 1;
  119. targetBottleneck = PerformanceBottleneck.CPU;
  120. break;
  121. }
  122. switching = false;
  123. }
  124. IEnumerator LogResult(string nextBottleneck, bool timeout = false)
  125. {
  126. if (timeout)
  127. {
  128. markers.Add(new Marker { time = watch.ElapsedMilliseconds, label = $"Timed out before reaching {targetBottleneck} Bottleneck, switching to {nextBottleneck} in 3 seconds", objectCount = factory.internalObjs});
  129. }
  130. else
  131. {
  132. markers.Add(new Marker { time = watch.ElapsedMilliseconds, label = $"{targetBottleneck} Bottleneck reached, switching to {nextBottleneck} in 3 seconds", objectCount = factory.internalObjs });
  133. }
  134. state = $"Waiting {waitTimeAfterTargetReached}s before changing to {nextBottleneck}";
  135. yield return new WaitForSeconds(waitTimeAfterTargetReached);
  136. if (stateChangeIterations <= 0)
  137. {
  138. FinishTest();
  139. }
  140. state = $"Changed to {nextBottleneck} target bottleneck";
  141. markers.Add(new Marker { time = watch.ElapsedMilliseconds, label = state, objectCount = factory.internalObjs });
  142. }
  143. void Update()
  144. {
  145. bottleneckStatus.text = $"{state} {Environment.NewLine} Timeout in {timeOuttimer:F2}s";
  146. if (bottleneckUI != null)
  147. bottleneckUI.targetBottleneck = targetBottleneck;
  148. if (ap == null || !ap.Active)
  149. return;
  150. if (switching)
  151. return;
  152. if (ap.PerformanceStatus.PerformanceMetrics.PerformanceBottleneck == targetBottleneck)
  153. {
  154. state = $"Changing in {timer:F2}s...";
  155. timer -= Time.deltaTime;
  156. }
  157. else
  158. {
  159. timer = waitTimeBeforeSwitch;
  160. }
  161. timeOuttimer -= Time.deltaTime;
  162. if (timeOuttimer < 0)
  163. {
  164. StartCoroutine(NextBottleneck(true));
  165. timeOuttimer = timeOut;
  166. }
  167. }
  168. }