/Sources/Sandbox.Game/Game/GUI/MyHudNetgraph.cs

https://github.com/KeenSoftwareHouse/SpaceEngineers · C# · 343 lines · 293 code · 46 blank · 4 comment · 21 complexity · eadb9fab7290509d934854383286a08d MD5 · raw file

  1. using Sandbox.Engine.Multiplayer;
  2. using Sandbox.Engine.Networking;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Text;
  7. using VRageMath;
  8. namespace Sandbox.Game.Gui
  9. {
  10. public class MyHudNetgraph
  11. {
  12. public const int NUMBER_OF_VISIBLE_PACKETS = 1500; // px count on x
  13. public static readonly Vector2 OPTIMAL_LENGTH_BAR_NORMALIZED = new Vector2(0, 0.25f); // normalized size of bar height
  14. // scale constants (progressive)
  15. public const int PACKET_SCALE_MAXIMUM = 25600; // Bytes
  16. public const int PACKET_SCALE_MINIMUM = 100; // Bytes
  17. public static readonly int PACKET_SCALE_MAXIMUM_MULTIPLIER = MathHelper.Log2(PACKET_SCALE_MAXIMUM / PACKET_SCALE_MINIMUM);
  18. public const float AVERAGE_SCALE_MAXIMUM = 20000.0f; // B/s
  19. public const float AVERAGE_SCALE_MINIMUM = 100.0f; // B/s
  20. public static readonly int AVERAGE_SCALE_MAXIMUM_MULTIPLIER = MathHelper.Log2((int)(AVERAGE_SCALE_MAXIMUM / AVERAGE_SCALE_MINIMUM));
  21. public const float SCALE_CHANGE_DELAY = 3.0f; // seconds
  22. // for average per bar
  23. public const int LINE_AVERAGE_COUNT = 30;
  24. // calculation constants
  25. internal const float REAL_SECONDS_MULTIPLIER = 1000.0f / (MyNetworkStats.NETGRAPH_UPDATE_TIME_MS * NUMBER_OF_VISIBLE_PACKETS);
  26. internal const float ONE_OVER_KB = 1.0f / 1024.0f;
  27. public class NetgraphLineData
  28. {
  29. public long ByteCountReliableReceived;
  30. public long ByteCountUnreliableReceived;
  31. public long ByteCountSent;
  32. public float AverageReceivedOnThisLine;
  33. public float AverageSentOnThisLine;
  34. public long TotalByteCountReceived
  35. {
  36. get { return ByteCountReliableReceived + ByteCountUnreliableReceived; }
  37. }
  38. public void Clear()
  39. {
  40. ByteCountReliableReceived = ByteCountUnreliableReceived = 0;
  41. ByteCountSent = 0;
  42. AverageReceivedOnThisLine = 0;
  43. AverageSentOnThisLine = 0;
  44. }
  45. }
  46. private int m_previousIndex;
  47. private int m_currentFirstIndex;
  48. private NetgraphLineData[] m_linesData;
  49. private long m_currentByteCountReceived;
  50. private long m_currentByteCountSent;
  51. private long m_lastPacketScaleChange;
  52. private long m_lastAverageScaleChange;
  53. private long m_byteMaximumForPacketScale;
  54. private float m_averageMaximum;
  55. private int m_overPacketScaleCounter;
  56. public int CurrentFirstIndex
  57. {
  58. get { return m_currentFirstIndex; }
  59. }
  60. public float AverageIncomingKBytes
  61. {
  62. get;
  63. private set;
  64. }
  65. public float AverageOutgoingKBytes
  66. {
  67. get;
  68. private set;
  69. }
  70. public long LastPacketBytesReceived
  71. {
  72. get { return m_linesData[m_previousIndex].TotalByteCountReceived; }
  73. }
  74. public long LastPacketBytesSent
  75. {
  76. get { return m_linesData[m_previousIndex].ByteCountSent; }
  77. }
  78. public long UpdatesPerSecond
  79. {
  80. get;
  81. set;
  82. }
  83. public long FramesPerSecond
  84. {
  85. get;
  86. set;
  87. }
  88. public long Ping
  89. {
  90. get;
  91. set;
  92. }
  93. public int CurrentPacketScaleMultiplier
  94. {
  95. get;
  96. private set;
  97. }
  98. public int CurrentAverageScaleMultiplier
  99. {
  100. get;
  101. private set;
  102. }
  103. public int CurrentPacketScaleMaximumValue
  104. {
  105. get { return MyHudNetgraph.PACKET_SCALE_MINIMUM * (1 << CurrentPacketScaleMultiplier); }
  106. }
  107. public float CurrentPacketScaleInvertedMaximumValue
  108. {
  109. get { return 1.0f / CurrentPacketScaleMaximumValue; }
  110. }
  111. public int CurrentPacketScaleMinimumValue
  112. {
  113. get { return MyHudNetgraph.PACKET_SCALE_MINIMUM * (1 << (CurrentPacketScaleMultiplier - 1)); }
  114. }
  115. public float CurrentAverageScaleMaximumValue
  116. {
  117. get { return MyHudNetgraph.AVERAGE_SCALE_MINIMUM * (1 << CurrentAverageScaleMultiplier); }
  118. }
  119. public float CurrentAverageScaleInvertedMaximumValue
  120. {
  121. get { return 1.0f / CurrentAverageScaleMaximumValue; }
  122. }
  123. public float CurrentAverageScaleMinimumValue
  124. {
  125. get { return MyHudNetgraph.AVERAGE_SCALE_MINIMUM * (1 << (CurrentAverageScaleMultiplier - 1)); }
  126. }
  127. public MyHudNetgraph()
  128. {
  129. m_currentFirstIndex = m_previousIndex = 0;
  130. AverageIncomingKBytes = AverageOutgoingKBytes = 0;
  131. UpdatesPerSecond = 0;
  132. m_lastAverageScaleChange = m_lastPacketScaleChange = Stopwatch.GetTimestamp();
  133. m_averageMaximum = 0;
  134. m_linesData = new NetgraphLineData[NUMBER_OF_VISIBLE_PACKETS];
  135. for (int i = 0; i < NUMBER_OF_VISIBLE_PACKETS; i++)
  136. {
  137. m_linesData[i] = new NetgraphLineData();
  138. }
  139. }
  140. public void UpdateNextBar(long byteCountReceived, long byteCountSent, List<Tuple<string, NetworkStat>> data)
  141. {
  142. long byteCountReliableReceived = 0;
  143. long byteCountUnreliableReceived = 0;
  144. foreach (var tuple in data)
  145. {
  146. if (tuple.Item2.IsReliable)
  147. byteCountReliableReceived += tuple.Item2.TotalSize;
  148. else
  149. byteCountUnreliableReceived += tuple.Item2.TotalSize;
  150. }
  151. m_linesData[m_currentFirstIndex].ByteCountReliableReceived = byteCountReliableReceived;
  152. m_linesData[m_currentFirstIndex].ByteCountUnreliableReceived = byteCountUnreliableReceived;
  153. m_linesData[m_currentFirstIndex].ByteCountSent = byteCountSent - m_currentByteCountSent;
  154. m_currentByteCountReceived = byteCountReceived;
  155. m_currentByteCountSent = byteCountSent;
  156. CalculateInAndOut();
  157. CalculateCurrentLineData();
  158. RecalculateAverageScaleLimit();
  159. RecalculatePacketScaleLimit();
  160. m_previousIndex = m_currentFirstIndex;
  161. m_currentFirstIndex++;
  162. if (m_currentFirstIndex == NUMBER_OF_VISIBLE_PACKETS)
  163. m_currentFirstIndex = 0;
  164. }
  165. private void CalculateInAndOut()
  166. {
  167. AverageIncomingKBytes = AverageOutgoingKBytes = 0;
  168. foreach (NetgraphLineData data in m_linesData)
  169. {
  170. AverageIncomingKBytes += data.TotalByteCountReceived;
  171. AverageOutgoingKBytes += data.ByteCountSent;
  172. }
  173. AverageIncomingKBytes = (AverageIncomingKBytes * ONE_OVER_KB * REAL_SECONDS_MULTIPLIER);
  174. AverageOutgoingKBytes = (AverageOutgoingKBytes * ONE_OVER_KB * REAL_SECONDS_MULTIPLIER);
  175. }
  176. private void CalculateCurrentLineData()
  177. {
  178. long averageReceivedBytes = 0;
  179. long averageSentBytes = 0;
  180. m_byteMaximumForPacketScale = 0;
  181. m_averageMaximum = 0;
  182. m_overPacketScaleCounter = 0;
  183. int startIndex = m_currentFirstIndex - LINE_AVERAGE_COUNT;
  184. if (startIndex < 0)
  185. {
  186. int secondStep = m_currentFirstIndex;
  187. startIndex = MyHudNetgraph.NUMBER_OF_VISIBLE_PACKETS + startIndex;
  188. for (int i = startIndex; i < MyHudNetgraph.NUMBER_OF_VISIBLE_PACKETS; i++)
  189. {
  190. averageReceivedBytes += m_linesData[i].TotalByteCountReceived;
  191. averageSentBytes += m_linesData[i].ByteCountSent;
  192. m_byteMaximumForPacketScale = Math.Max(m_byteMaximumForPacketScale, m_linesData[i].TotalByteCountReceived + m_linesData[i].ByteCountSent);
  193. m_averageMaximum = Math.Max(m_averageMaximum, Math.Max(m_linesData[i].AverageReceivedOnThisLine, m_linesData[i].AverageSentOnThisLine));
  194. }
  195. for (int i = 0; i < secondStep; i++)
  196. {
  197. averageReceivedBytes += m_linesData[i].TotalByteCountReceived;
  198. averageSentBytes += m_linesData[i].ByteCountSent;
  199. m_byteMaximumForPacketScale = Math.Max(m_byteMaximumForPacketScale, m_linesData[i].TotalByteCountReceived + m_linesData[i].ByteCountSent);
  200. m_averageMaximum = Math.Max(m_averageMaximum, Math.Max(m_linesData[i].AverageReceivedOnThisLine, m_linesData[i].AverageSentOnThisLine));
  201. }
  202. }
  203. else
  204. {
  205. for (int i = startIndex; i < startIndex + LINE_AVERAGE_COUNT; i++)
  206. {
  207. averageReceivedBytes += m_linesData[i].TotalByteCountReceived;
  208. averageSentBytes += m_linesData[i].ByteCountSent;
  209. m_byteMaximumForPacketScale = Math.Max(m_byteMaximumForPacketScale, m_linesData[i].TotalByteCountReceived + m_linesData[i].ByteCountSent);
  210. m_averageMaximum = Math.Max(m_averageMaximum, Math.Max(m_linesData[i].AverageReceivedOnThisLine, m_linesData[i].AverageSentOnThisLine));
  211. }
  212. }
  213. //ByteAverageForPacketScale = averageReceivedBytes;
  214. m_linesData[m_currentFirstIndex].AverageReceivedOnThisLine = averageReceivedBytes * (1000f / (MyNetworkStats.NETGRAPH_UPDATE_TIME_MS * LINE_AVERAGE_COUNT));
  215. m_linesData[m_currentFirstIndex].AverageSentOnThisLine = averageSentBytes * (1000f / (MyNetworkStats.NETGRAPH_UPDATE_TIME_MS * LINE_AVERAGE_COUNT));
  216. }
  217. public void ClearNetgraph()
  218. {
  219. AverageIncomingKBytes = AverageOutgoingKBytes = 0;
  220. foreach (NetgraphLineData data in m_linesData)
  221. {
  222. data.Clear();
  223. }
  224. m_previousIndex = m_currentFirstIndex = 0;
  225. m_currentByteCountReceived = m_currentByteCountSent = 0;
  226. UpdatesPerSecond = 0;
  227. FramesPerSecond = 0;
  228. CurrentAverageScaleMultiplier = 1;
  229. CurrentPacketScaleMultiplier = 1;
  230. }
  231. public NetgraphLineData GetNetgraphLineDataAtIndex(int i)
  232. {
  233. return m_linesData[i];
  234. }
  235. private void RecalculateAverageScaleLimit()
  236. {
  237. if ((Stopwatch.GetTimestamp() - m_lastAverageScaleChange) / Stopwatch.Frequency > SCALE_CHANGE_DELAY)
  238. {
  239. if (m_averageMaximum > CurrentAverageScaleMaximumValue)
  240. {
  241. int multiplier = MathHelper.Log2((int)(m_averageMaximum / AVERAGE_SCALE_MINIMUM)) + 1;
  242. if (AVERAGE_SCALE_MAXIMUM_MULTIPLIER < multiplier)
  243. multiplier = AVERAGE_SCALE_MAXIMUM_MULTIPLIER;
  244. CurrentAverageScaleMultiplier = multiplier;
  245. m_lastAverageScaleChange = Stopwatch.GetTimestamp();
  246. }
  247. else if (m_averageMaximum < CurrentAverageScaleMinimumValue)
  248. {
  249. int multiplier = MathHelper.Log2((int)(m_averageMaximum / AVERAGE_SCALE_MINIMUM)) + 1;
  250. CurrentAverageScaleMultiplier = multiplier;
  251. m_lastAverageScaleChange = Stopwatch.GetTimestamp();
  252. }
  253. }
  254. }
  255. private void RecalculatePacketScaleLimit()
  256. {
  257. if ((Stopwatch.GetTimestamp() - m_lastPacketScaleChange) / Stopwatch.Frequency > SCALE_CHANGE_DELAY)
  258. {
  259. if (m_byteMaximumForPacketScale > CurrentPacketScaleMaximumValue)
  260. {
  261. int multiplier = MathHelper.Log2((int)(m_byteMaximumForPacketScale / PACKET_SCALE_MINIMUM)) + 1;
  262. if (PACKET_SCALE_MAXIMUM_MULTIPLIER < multiplier)
  263. multiplier = PACKET_SCALE_MAXIMUM_MULTIPLIER;
  264. CurrentPacketScaleMultiplier = multiplier;
  265. m_lastPacketScaleChange = Stopwatch.GetTimestamp();
  266. }
  267. else if (m_byteMaximumForPacketScale < CurrentPacketScaleMinimumValue)
  268. {
  269. int multiplier = MathHelper.Log2((int)(m_byteMaximumForPacketScale / PACKET_SCALE_MINIMUM));
  270. CurrentPacketScaleMultiplier = multiplier;
  271. m_lastPacketScaleChange = Stopwatch.GetTimestamp();
  272. }
  273. }
  274. }
  275. private static readonly string[] BYTE_UNITS = new string[] { "[B]", "[kB]", "[MB]" };
  276. private static readonly string[] BYTE_PER_SECOND_UNITS = new string[] { "[B/s]", "[kB/s]", "[MB/s]" };
  277. private static readonly float[] BYTE_MULTIPLIERS = new float[] { 1f, 1024f, 1024f * 1024f };
  278. public void GetProperFormatAndValueForBytes(float input, out float formattedValue, StringBuilder outFormat, bool perSecond = false)
  279. {
  280. float inputAbs = Math.Abs(input);
  281. int i = 1;
  282. while (i < BYTE_MULTIPLIERS.Length)
  283. {
  284. if (inputAbs < BYTE_MULTIPLIERS[i])
  285. break;
  286. i++;
  287. }
  288. i--;
  289. formattedValue = input / BYTE_MULTIPLIERS[i];
  290. formattedValue = (float)(Math.Truncate(100.0 * formattedValue) * 0.01f);
  291. if (!perSecond)
  292. outFormat.Append(BYTE_UNITS[i]);
  293. else
  294. outFormat.Append(BYTE_PER_SECOND_UNITS[i]);
  295. }
  296. }
  297. }