StatusWindow.cs 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;
  8. using System.Timers;
  9. using System.Diagnostics;
  10. using System.Runtime.InteropServices;
  11. namespace OpenSim.Framework.ServerStatus
  12. {
  13. public partial class StatusWindow : Form
  14. {
  15. System.Timers.Timer m_updateTimer;
  16. static Dictionary<int, ThreadItem> m_threadItems = new Dictionary<int, ThreadItem>();
  17. static Dictionary<int, string> m_idToName = new Dictionary<int, string>();
  18. static int m_nCoreCount = System.Environment.ProcessorCount;
  19. PerformanceCounter m_pcAvailRam = null;
  20. class TrafficHistory {
  21. public float outUdpBytes = 0;
  22. public float inUdpBytes = 0;
  23. public float outTcpBytes = 0;
  24. public float inTcpBytes = 0;
  25. public float outTotalBytes = 0;
  26. public float inTotalBytes = 0;
  27. public float resentBytes = 0;
  28. }
  29. class MemoryHistory {
  30. public float nonpagedSystemMemory;
  31. public float pagedMemory;
  32. public float pagedSystemMemory;
  33. public float gcReportedMem;
  34. public float workingSet;
  35. }
  36. class CpuHistory {
  37. public float[] cpuUsage = new float[m_nCoreCount];
  38. public float totalUsage = 0;
  39. }
  40. class PacketItem
  41. {
  42. public long m_bytesOut = 0;
  43. public long m_packetsOut = 0;
  44. public long m_bytesIn = 0;
  45. public long m_packetsIn = 0;
  46. public long m_resent = 0;
  47. public bool m_addedToList = false;
  48. public ListViewItem.ListViewSubItem m_listBytesOut = null;
  49. public ListViewItem.ListViewSubItem m_listPacketsOut = null;
  50. public ListViewItem.ListViewSubItem m_listBytesIn = null;
  51. public ListViewItem.ListViewSubItem m_listPacketsIn = null;
  52. public ListViewItem.ListViewSubItem m_listResent = null;
  53. }
  54. static float m_fNetworkHistoryScale;
  55. static float m_fMemoryHistoryScale;
  56. static Dictionary<string, PacketItem> m_packets = new Dictionary<string, PacketItem>();
  57. static LinkedList<TrafficHistory> m_trafficHistory = new LinkedList<TrafficHistory>();
  58. static LinkedList<MemoryHistory> m_memoryHistory = new LinkedList<MemoryHistory>();
  59. static LinkedList<CpuHistory> m_cpuHistory = new LinkedList<CpuHistory>();
  60. PerformanceCounter[] m_pcCpu = new PerformanceCounter[System.Environment.ProcessorCount];
  61. PerformanceCounter m_pcCpuTotal = null;
  62. static volatile int outUdpBytes = 0;
  63. static volatile int inUdpBytes = 0;
  64. static volatile int outTcpBytes = 0;
  65. static volatile int inTcpBytes = 0;
  66. static volatile int outResent = 0;
  67. BufferedListView m_threads;
  68. BufferedListView m_listPackets;
  69. #region BufferedListView
  70. /**
  71. * Flicker minimized listview
  72. **/
  73. public class BufferedListView : ListView
  74. {
  75. #region WM - Window Messages
  76. public enum WM
  77. {
  78. WM_NULL = 0x0000,
  79. WM_CREATE = 0x0001,
  80. WM_DESTROY = 0x0002,
  81. WM_MOVE = 0x0003,
  82. WM_SIZE = 0x0005,
  83. WM_ACTIVATE = 0x0006,
  84. WM_SETFOCUS = 0x0007,
  85. WM_KILLFOCUS = 0x0008,
  86. WM_ENABLE = 0x000A,
  87. WM_SETREDRAW = 0x000B,
  88. WM_SETTEXT = 0x000C,
  89. WM_GETTEXT = 0x000D,
  90. WM_GETTEXTLENGTH = 0x000E,
  91. WM_PAINT = 0x000F,
  92. WM_CLOSE = 0x0010,
  93. WM_QUERYENDSESSION = 0x0011,
  94. WM_QUIT = 0x0012,
  95. WM_QUERYOPEN = 0x0013,
  96. WM_ERASEBKGND = 0x0014,
  97. }
  98. #endregion
  99. #region RECT
  100. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  101. public struct RECT
  102. {
  103. public int left;
  104. public int top;
  105. public int right;
  106. public int bottom;
  107. }
  108. #endregion
  109. #region Imported User32.DLL functions
  110. [DllImport("user32.dll", CharSet = CharSet.Auto)]
  111. static public extern bool ValidateRect(IntPtr handle, ref RECT rect);
  112. #endregion
  113. #region GetWindowRECT
  114. // Get the listview's rectangle and return it as a RECT structure
  115. private RECT GetWindowRECT()
  116. {
  117. RECT rect = new RECT();
  118. rect.left = this.Left;
  119. rect.right = this.Right;
  120. rect.top = this.Top;
  121. rect.bottom = this.Bottom;
  122. return rect;
  123. }
  124. #endregion
  125. volatile public bool updating = false;
  126. public BufferedListView()
  127. {
  128. }
  129. protected override void OnPaintBackground(PaintEventArgs pea)
  130. {
  131. // do nothing here since this event is now handled by OnPaint
  132. }
  133. protected override void OnPaint(PaintEventArgs pea)
  134. {
  135. base.OnPaint(pea);
  136. }
  137. protected override void WndProc(ref Message messg)
  138. {
  139. if (updating)
  140. {
  141. if ((int)WM.WM_ERASEBKGND == messg.Msg)
  142. {
  143. return;
  144. }
  145. else if ((int)WM.WM_PAINT == messg.Msg)
  146. {
  147. RECT vrect = this.GetWindowRECT();
  148. // validate the entire window
  149. ValidateRect(this.Handle, ref vrect);
  150. }
  151. }
  152. base.WndProc(ref messg);
  153. }
  154. }
  155. #endregion
  156. #region ThreadItem
  157. /**
  158. * Represents a single thread item in the listview control
  159. **/
  160. class ThreadItem
  161. {
  162. public ListViewItem listItem;
  163. public ListViewItem.ListViewSubItem name;
  164. public ListViewItem.ListViewSubItem cpu;
  165. }
  166. #endregion
  167. public static void ReportOutPacketUdp(int size, bool resent)
  168. {
  169. if (resent)
  170. {
  171. outResent += size += 8;
  172. }
  173. outUdpBytes += size + 8;
  174. }
  175. public static void ReportInPacketUdp(int size) { inUdpBytes += size + 8; }
  176. public static void ReportOutPacketTcp(int size) { outTcpBytes += size + 20; }
  177. public static void ReportInPacketTcp(int size) { inTcpBytes += size + 20; }
  178. public static void ReportProcessedOutPacket(string name, int size, bool resent)
  179. {
  180. PacketItem item = null;
  181. if (m_packets.ContainsKey(name))
  182. {
  183. item = m_packets[name];
  184. }
  185. else
  186. {
  187. item = new PacketItem();
  188. m_packets[name] = item;
  189. }
  190. if (resent)
  191. {
  192. item.m_resent += size;
  193. }
  194. item.m_bytesOut += size;
  195. item.m_packetsOut++;
  196. }
  197. public static void ReportProcessedInPacket(string name, int size)
  198. {
  199. PacketItem item = null;
  200. if (m_packets.ContainsKey(name))
  201. {
  202. item = m_packets[name];
  203. }
  204. else
  205. {
  206. item = new PacketItem();
  207. m_packets[name] = item;
  208. }
  209. item.m_bytesIn += size;
  210. item.m_packetsIn++;
  211. }
  212. public StatusWindow()
  213. {
  214. m_pcAvailRam = new PerformanceCounter("Memory", "Available MBytes");
  215. m_packets = new Dictionary<string, PacketItem>();
  216. InitializeComponent();
  217. m_listPackets = new BufferedListView();
  218. m_listPackets.Dock = System.Windows.Forms.DockStyle.Fill;
  219. m_listPackets.GridLines = true;
  220. m_listPackets.Location = new System.Drawing.Point(3, 3);
  221. m_listPackets.MultiSelect = false;
  222. m_listPackets.Name = "m_listPackets";
  223. m_listPackets.Size = new System.Drawing.Size(500, 400);
  224. m_listPackets.TabIndex = 0;
  225. m_listPackets.View = System.Windows.Forms.View.Details;
  226. tabPackets.Controls.Add(m_listPackets);
  227. m_listPackets.Columns.Add("Packet").Width = 260;
  228. m_listPackets.Columns.Add("In count").Width = 80;
  229. m_listPackets.Columns.Add("In bytes").Width = 80;
  230. m_listPackets.Columns.Add("Out count").Width = 80;
  231. m_listPackets.Columns.Add("Out bytes").Width = 80;
  232. m_listPackets.Columns.Add("Resent").Width = 80;
  233. m_threads = new BufferedListView();
  234. m_threads.Dock = System.Windows.Forms.DockStyle.Fill;
  235. m_threads.GridLines = true;
  236. m_threads.Location = new System.Drawing.Point(3, 3);
  237. m_threads.MultiSelect = false;
  238. m_threads.Name = "m_threads";
  239. m_threads.Size = new System.Drawing.Size(500, 400);
  240. m_threads.TabIndex = 0;
  241. m_threads.View = System.Windows.Forms.View.Details;
  242. tabThreads.Controls.Add(m_threads);
  243. m_threads.Columns.Add("ID");
  244. m_threads.Columns.Add("Name").Width = 260;
  245. m_threads.Columns.Add("CPU Time").Width=100;
  246. m_updateTimer = new System.Timers.Timer(2000);
  247. m_updateTimer.Elapsed += new ElapsedEventHandler(UpdateTimer);
  248. outUdpBytes = 0;
  249. inUdpBytes = 0;
  250. outTcpBytes = 0;
  251. inTcpBytes = 0;
  252. outResent = 0;
  253. m_updateTimer.Start();
  254. for(int i = 0; i < m_nCoreCount; i++)
  255. {
  256. m_pcCpu[i] = new PerformanceCounter("Processor", "% Processor Time", i.ToString(), true);
  257. m_pcCpu[i].MachineName = ".";
  258. }
  259. m_pcCpuTotal = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
  260. }
  261. public void CloseStatusWindow() {
  262. Close();
  263. m_updateTimer.Stop();
  264. m_threadItems.Clear();
  265. m_pcAvailRam.Close();
  266. m_pcAvailRam = null;
  267. for (int i = 0; i < m_nCoreCount; i++)
  268. {
  269. m_pcCpu[i].Close();
  270. m_pcCpu[i] = null;
  271. }
  272. foreach(PacketItem item in m_packets.Values)
  273. {
  274. item.m_addedToList = false;
  275. }
  276. m_packets = null;
  277. m_pcCpuTotal.Close();
  278. m_pcCpuTotal = null;
  279. }
  280. public static void ReportThreadName(int id, string name)
  281. {
  282. lock (m_threadItems)
  283. {
  284. m_idToName[id] = name;
  285. }
  286. }
  287. delegate void UpdateControlsDelegate();
  288. TrafficHistory UpdateNetworkHistory()
  289. {
  290. TrafficHistory item = new TrafficHistory();
  291. item.inUdpBytes = ((float)inUdpBytes) / 1024.0f / 2.0f;
  292. item.outUdpBytes = ((float)outUdpBytes) / 1024.0f / 2.0f;
  293. item.inTcpBytes = ((float)inTcpBytes) / 1024.0f / 2.0f;
  294. item.outTcpBytes = ((float)outTcpBytes) / 1024.0f / 2.0f;
  295. item.resentBytes = ((float)outResent) / 1024.0f / 2.0f;
  296. item.inTotalBytes = item.inUdpBytes + item.inTcpBytes;
  297. item.outTotalBytes = item.outUdpBytes + item.outTcpBytes;
  298. inUdpBytes = 0;
  299. outUdpBytes = 0;
  300. inTcpBytes = 0;
  301. outTcpBytes = 0;
  302. outResent = 0;
  303. m_trafficHistory.AddFirst(item);
  304. if (m_trafficHistory.Count > 500)
  305. {
  306. m_trafficHistory.RemoveLast();
  307. }
  308. return item;
  309. }
  310. MemoryHistory UpdateMemoryHistory(Process proc)
  311. {
  312. MemoryHistory item = new MemoryHistory();
  313. item.gcReportedMem = ((float)System.GC.GetTotalMemory(false)) / 1024.0f / 1024.0f;
  314. item.workingSet = ((float)proc.WorkingSet64) / 1024.0f / 1024.0f;
  315. item.nonpagedSystemMemory = ((float)proc.NonpagedSystemMemorySize64) / 1024.0f / 1024.0f;
  316. item.pagedSystemMemory = ((float)proc.PagedMemorySize64) / 1024.0f / 1024.0f;
  317. item.pagedSystemMemory = ((float)proc.PagedSystemMemorySize64) / 1024.0f / 1024.0f;
  318. m_memoryHistory.AddFirst(item);
  319. if (m_memoryHistory.Count > 500)
  320. {
  321. m_memoryHistory.RemoveLast();
  322. }
  323. return item;
  324. }
  325. void UpdateCpuHistory() {
  326. CpuHistory item = new CpuHistory();
  327. for( int i = 0; i < m_nCoreCount; i++)
  328. {
  329. item.cpuUsage[i] = m_pcCpu[i].NextValue();
  330. }
  331. item.totalUsage = m_pcCpuTotal.NextValue();
  332. m_cpuHistory.AddFirst(item);
  333. if (m_cpuHistory.Count > 500)
  334. {
  335. m_cpuHistory.RemoveLast();
  336. }
  337. }
  338. string FormatDataSize(long byteCount)
  339. {
  340. double fCount = (double)byteCount;
  341. if (byteCount > 1024 * 1024 * 1024)
  342. {
  343. fCount/=(1024.0*1024.0*1024.0);
  344. return fCount.ToString("##0.00") + "GB";
  345. }
  346. else if (byteCount > 1024*1024*10)
  347. {
  348. fCount/=(1024.0*1024.0);
  349. return fCount.ToString("##0.00") + "MB";
  350. }
  351. else if (byteCount > 1024*10)
  352. {
  353. fCount/=1024.0;
  354. return fCount.ToString("##0.00") + "KB";
  355. }
  356. else
  357. {
  358. return byteCount.ToString() +"B";
  359. }
  360. }
  361. void UpdatePacketView()
  362. {
  363. foreach(KeyValuePair<string, PacketItem> item in m_packets)
  364. {
  365. if (item.Value.m_addedToList)
  366. {
  367. item.Value.m_listPacketsIn.Text = item.Value.m_packetsIn.ToString();
  368. item.Value.m_listBytesIn.Text = FormatDataSize(item.Value.m_bytesIn);
  369. item.Value.m_listPacketsOut.Text = item.Value.m_packetsOut.ToString();
  370. item.Value.m_listBytesOut.Text = FormatDataSize(item.Value.m_bytesOut);
  371. item.Value.m_listResent.Text = FormatDataSize(item.Value.m_resent);
  372. }
  373. else
  374. {
  375. ListViewItem listItem = m_listPackets.Items.Add(item.Key);
  376. item.Value.m_listPacketsIn = listItem.SubItems.Add(item.Value.m_packetsIn.ToString());
  377. item.Value.m_listBytesIn = listItem.SubItems.Add(FormatDataSize(item.Value.m_bytesIn));
  378. item.Value.m_listPacketsOut = listItem.SubItems.Add(item.Value.m_packetsOut.ToString());
  379. item.Value.m_listBytesOut = listItem.SubItems.Add(FormatDataSize(item.Value.m_bytesOut));
  380. item.Value.m_listResent = listItem.SubItems.Add(FormatDataSize(item.Value.m_resent));
  381. item.Value.m_addedToList = true;
  382. }
  383. }
  384. }
  385. void UpdateControls()
  386. {
  387. Process proc = Process.GetCurrentProcess();
  388. TrafficHistory netItem = UpdateNetworkHistory();
  389. MemoryHistory memItem = UpdateMemoryHistory(proc);
  390. UpdateCpuHistory();
  391. if (tabControl1.SelectedIndex == 0)
  392. {
  393. m_threads.updating = true;
  394. UpdateThreadList();
  395. m_threads.updating = false;
  396. m_threads.Invalidate();
  397. }
  398. else if (tabControl1.SelectedIndex == 1)
  399. {
  400. RefreshNetworkStats(netItem);
  401. PaintNetworkHistory();
  402. }
  403. else if (tabControl1.SelectedIndex == 2)
  404. {
  405. m_availableMem.Text = m_pcAvailRam.NextValue().ToString("##0.00") + " MB";
  406. m_commitSize.Text = memItem.workingSet.ToString("##0.00") + " MB";
  407. PaintMemoryHistory();
  408. }
  409. else if (tabControl1.SelectedIndex == 3)
  410. {
  411. PaintCpuHistory();
  412. }
  413. else if (tabControl1.SelectedIndex == 4)
  414. {
  415. m_listPackets.updating = true;
  416. UpdatePacketView();
  417. m_listPackets.updating = false;
  418. m_listPackets.Invalidate();
  419. }
  420. }
  421. protected void PaintCpuHistory()
  422. {
  423. Pen[] pens = { Pens.Yellow, Pens.Blue, Pens.Green, Pens.Red,
  424. Pens.White, Pens.Turquoise, Pens.Linen, Pens.Gray,
  425. Pens.Purple, Pens.Pink, Pens.LightBlue, Pens.LightSalmon};
  426. Pen penLine = Pens.DarkSlateGray;
  427. Graphics screenGfx = m_cpuDrawing.CreateGraphics();
  428. Bitmap backBuffer = new Bitmap(m_cpuDrawing.Width, m_cpuDrawing.Height);
  429. Graphics gfx = Graphics.FromImage(backBuffer);
  430. gfx.Clear(Color.Black);
  431. float fMax = 105.0f;
  432. for (int i = 0; i < m_cpuDrawing.Height - 10; i += 30)
  433. {
  434. float yPos = m_cpuDrawing.Height - i - 15;
  435. float fPos = ((float)(i)) / ((float)m_cpuDrawing.Height);
  436. gfx.DrawLine(penLine, 0, yPos, m_cpuDrawing.Width, yPos);
  437. }
  438. //Size of second in pixels
  439. float fSecondStep = 2.5f; //120 seconds
  440. float fTotalSeconds = (1 / fSecondStep) * (m_cpuDrawing.Width - 90);
  441. for (int i = 0; i < m_cpuDrawing.Width - 90; i += 50)
  442. {
  443. float xPos = 90 + i;
  444. float fTime = fTotalSeconds - (((float)(i)) / fSecondStep);
  445. gfx.DrawLine(penLine, xPos, 0, xPos, m_cpuDrawing.Height - 15);
  446. string strText = fTime.ToString("##0");
  447. gfx.DrawString(strText, SystemFonts.DialogFont, Brushes.CadetBlue,
  448. xPos - 4 * strText.Length, m_cpuDrawing.Height - 15);
  449. }
  450. float nXPos = m_cpuDrawing.Width;
  451. float fHeightMul = m_cpuDrawing.Height - 15;
  452. float fYStart = m_cpuDrawing.Height - 15;
  453. CpuHistory lastItem = null;
  454. foreach (CpuHistory item in m_cpuHistory)
  455. {
  456. if (lastItem != null)
  457. {
  458. nXPos -= fSecondStep * 2;
  459. for (int i = 0; i < m_nCoreCount; i++)
  460. {
  461. gfx.DrawLine(pens[i+1], nXPos, fYStart - (item.cpuUsage[i] / fMax) * fHeightMul,
  462. nXPos + fSecondStep * 2, fYStart - (lastItem.cpuUsage[i] / fMax) * fHeightMul);
  463. }
  464. gfx.DrawLine(pens[0], nXPos, fYStart - (item.totalUsage / fMax) * fHeightMul,
  465. nXPos + fSecondStep * 2, fYStart - (lastItem.totalUsage / fMax) * fHeightMul);
  466. if (nXPos < 0)
  467. break;
  468. }
  469. lastItem = item;
  470. }
  471. for (int i = 0; i < m_cpuDrawing.Height - 10; i += 30)
  472. {
  473. float yPos = m_cpuDrawing.Height - i - 15;
  474. float fPos = ((float)(i)) / ((float)m_cpuDrawing.Height);
  475. gfx.DrawString((fPos * fMax).ToString("##0.00") + "%",
  476. SystemFonts.DialogFont, Brushes.CadetBlue, 3, yPos);
  477. }
  478. int nPosX = m_cpuDrawing.Width - 50;
  479. gfx.DrawString("Total", SystemFonts.DialogFont, pens[0].Brush, nPosX, 10);
  480. for (int i = 0; i < m_nCoreCount; i++ )
  481. {
  482. gfx.DrawString("Core " + i, SystemFonts.DialogFont, pens[i+1].Brush, nPosX, 22 + i * 12);
  483. }
  484. screenGfx.DrawImageUnscaled(backBuffer, 0, 0);
  485. }
  486. protected void PaintNetworkHistory()
  487. {
  488. Pen penUdpOut = Pens.SkyBlue;
  489. Pen penUdpIn = Pens.Blue;
  490. Pen penTcpOut = Pens.Red;
  491. Pen penTcpIn = Pens.Pink;
  492. Pen penTotalOut = Pens.Green;
  493. Pen penTotalIn = Pens.LimeGreen;
  494. Pen penResent = Pens.Orange;
  495. Pen penLine = Pens.DarkSlateGray;
  496. Graphics screenGfx = m_networkDrawing.CreateGraphics();
  497. Bitmap backBuffer = new Bitmap(m_networkDrawing.Width, m_networkDrawing.Height);
  498. Graphics gfx = Graphics.FromImage(backBuffer);
  499. gfx.Clear(Color.Black);
  500. float fMax = m_fNetworkHistoryScale;
  501. if (fMax < 12.0f)
  502. fMax = 12.0f;
  503. for( int i = 0; i < m_networkDrawing.Height-10; i+= 30)
  504. {
  505. float yPos = m_networkDrawing.Height - i-15;
  506. float fPos = ((float)(i)) / ((float)m_networkDrawing.Height);
  507. gfx.DrawLine(penLine, 0, yPos, m_networkDrawing.Width, yPos);
  508. }
  509. //Size of second in pixels
  510. float fSecondStep = 1.5f; //120 seconds
  511. float fTotalSeconds = (1/fSecondStep) * (m_networkDrawing.Width - 90);
  512. for( int i = 0; i < m_networkDrawing.Width-90; i+= 50)
  513. {
  514. float xPos = 90 + i;
  515. float fTime = fTotalSeconds - (((float)(i)) / fSecondStep);
  516. gfx.DrawLine(penLine, xPos, 0, xPos, m_networkDrawing.Height - 15);
  517. string strText = fTime.ToString("##0");
  518. gfx.DrawString(strText, SystemFonts.DialogFont, Brushes.CadetBlue,
  519. xPos - 4 * strText.Length, m_networkDrawing.Height - 15);
  520. }
  521. float nXPos = m_networkDrawing.Width;
  522. float fHeightMul = m_networkDrawing.Height - 15;
  523. float fYStart = m_networkDrawing.Height - 15;
  524. TrafficHistory lastItem = null;
  525. float fHighestRate = 0;
  526. foreach(TrafficHistory item in m_trafficHistory) {
  527. if (lastItem != null)
  528. {
  529. nXPos -= fSecondStep * 2;
  530. gfx.DrawLine(penUdpIn, nXPos, fYStart - (item.inUdpBytes / fMax) * fHeightMul,
  531. nXPos + fSecondStep * 2, fYStart - (lastItem.inUdpBytes / fMax) * fHeightMul);
  532. gfx.DrawLine(penUdpOut, nXPos, fYStart - (item.outUdpBytes / fMax) * fHeightMul,
  533. nXPos + fSecondStep * 2, fYStart - (lastItem.outUdpBytes / fMax) * fHeightMul);
  534. gfx.DrawLine(penTcpIn, nXPos, fYStart - (item.inTcpBytes / fMax) * fHeightMul,
  535. nXPos + fSecondStep * 2, fYStart - (lastItem.inTcpBytes / fMax) * fHeightMul);
  536. gfx.DrawLine(penTcpOut, nXPos, fYStart - (item.outTcpBytes / fMax) * fHeightMul,
  537. nXPos + fSecondStep * 2, fYStart - (lastItem.outTcpBytes / fMax) * fHeightMul);
  538. gfx.DrawLine(penTotalIn, nXPos, fYStart - (item.inTotalBytes / fMax) * fHeightMul,
  539. nXPos + fSecondStep * 2, fYStart - (lastItem.inTotalBytes / fMax) * fHeightMul);
  540. gfx.DrawLine(penTotalOut, nXPos, fYStart - (item.outTotalBytes / fMax) * fHeightMul,
  541. nXPos + fSecondStep * 2, fYStart - (lastItem.outTotalBytes / fMax) * fHeightMul);
  542. gfx.DrawLine(penResent, nXPos, fYStart - (item.resentBytes / fMax) * fHeightMul,
  543. nXPos + fSecondStep * 2, fYStart - (lastItem.resentBytes / fMax) * fHeightMul);
  544. if (nXPos < 0)
  545. break;
  546. }
  547. lastItem = item;
  548. if (item.inTotalBytes > fHighestRate)
  549. fHighestRate = item.inTotalBytes;
  550. if (item.outTotalBytes > fHighestRate)
  551. fHighestRate = item.outTotalBytes;
  552. }
  553. for (int i = 0; i < m_networkDrawing.Height - 10; i += 30)
  554. {
  555. float yPos = m_networkDrawing.Height - i - 15;
  556. float fPos = ((float)(i)) / ((float)m_networkDrawing.Height);
  557. gfx.DrawString((fPos * fMax).ToString("##0.00") + " KB/s",
  558. SystemFonts.DialogFont, Brushes.CadetBlue, 3, yPos);
  559. }
  560. int nPosX = m_networkDrawing.Width-60;
  561. gfx.DrawString("Udp in", SystemFonts.DialogFont, penUdpIn.Brush, nPosX, 10);
  562. gfx.DrawString("Udp out", SystemFonts.DialogFont, penUdpOut.Brush, nPosX, 22);
  563. gfx.DrawString("Tcp in", SystemFonts.DialogFont, penTcpIn.Brush, nPosX, 34);
  564. gfx.DrawString("Tcp out", SystemFonts.DialogFont, penTcpOut.Brush, nPosX, 46);
  565. gfx.DrawString("Total in", SystemFonts.DialogFont, penTotalIn.Brush, nPosX, 58);
  566. gfx.DrawString("Total out", SystemFonts.DialogFont, penTotalOut.Brush, nPosX, 70);
  567. gfx.DrawString("Resent", SystemFonts.DialogFont, penResent.Brush, nPosX, 82);
  568. screenGfx.DrawImageUnscaled(backBuffer, 0, 0);
  569. m_fNetworkHistoryScale = fHighestRate + 10;
  570. }
  571. protected void PaintMemoryHistory()
  572. {
  573. Pen penPagedMemory = Pens.Gray;
  574. Pen penPagedSystemMemory = Pens.Orange;
  575. Pen penNonPagedMemory = Pens.LawnGreen;
  576. Pen penWorkingSet = Pens.HotPink;
  577. Pen penGcReported = Pens.Red;
  578. Pen penLine = Pens.DarkSlateGray;
  579. Graphics screenGfx = m_memStats.CreateGraphics();
  580. Bitmap backBuffer = new Bitmap(m_memStats.Width, m_memStats.Height);
  581. Graphics gfx = Graphics.FromImage(backBuffer);
  582. gfx.Clear(Color.Black);
  583. float fMax = m_fMemoryHistoryScale;
  584. if (fMax < 12.0f)
  585. fMax = 12.0f;
  586. for (int i = 0; i < m_memStats.Height - 10; i += 30)
  587. {
  588. float yPos = m_memStats.Height - i - 15;
  589. float fPos = ((float)(i)) / ((float)m_memStats.Height);
  590. gfx.DrawLine(penLine, 0, yPos, m_memStats.Width, yPos);
  591. }
  592. //Size of second in pixels
  593. float fSecondStep = 1.5f; //120 seconds
  594. float fTotalSeconds = (1 / fSecondStep) * (m_memStats.Width - 90);
  595. for (int i = 0; i < m_memStats.Width - 90; i += 50)
  596. {
  597. float xPos = 90 + i;
  598. float fTime = fTotalSeconds - (((float)(i)) / fSecondStep);
  599. gfx.DrawLine(penLine, xPos, 0, xPos, m_memStats.Height - 15);
  600. string strText = fTime.ToString("##0");
  601. gfx.DrawString(strText, SystemFonts.DialogFont, Brushes.CadetBlue,
  602. xPos - 4 * strText.Length, m_memStats.Height - 15);
  603. }
  604. float nXPos = m_memStats.Width;
  605. float fHeightMul = m_memStats.Height - 15;
  606. float fYStart = m_memStats.Height - 15;
  607. MemoryHistory lastItem = null;
  608. float fHighestRate = 0;
  609. foreach (MemoryHistory item in m_memoryHistory)
  610. {
  611. if (lastItem != null)
  612. {
  613. nXPos -= fSecondStep * 2;
  614. gfx.DrawLine(penPagedMemory, nXPos, fYStart - (item.pagedMemory / fMax) * fHeightMul,
  615. nXPos + fSecondStep * 2, fYStart - (lastItem.pagedMemory / fMax) * fHeightMul);
  616. gfx.DrawLine(penPagedSystemMemory, nXPos, fYStart - (item.pagedSystemMemory / fMax) * fHeightMul,
  617. nXPos + fSecondStep * 2, fYStart - (lastItem.pagedSystemMemory / fMax) * fHeightMul);
  618. gfx.DrawLine(penNonPagedMemory, nXPos, fYStart - (item.nonpagedSystemMemory / fMax) * fHeightMul,
  619. nXPos + fSecondStep * 2, fYStart - (lastItem.nonpagedSystemMemory / fMax) * fHeightMul);
  620. gfx.DrawLine(penWorkingSet, nXPos, fYStart - (item.workingSet / fMax) * fHeightMul,
  621. nXPos + fSecondStep * 2, fYStart - (lastItem.workingSet / fMax) * fHeightMul);
  622. gfx.DrawLine(penGcReported, nXPos, fYStart - (item.gcReportedMem / fMax) * fHeightMul,
  623. nXPos + fSecondStep * 2, fYStart - (lastItem.gcReportedMem / fMax) * fHeightMul);
  624. if (nXPos < 0)
  625. break;
  626. }
  627. lastItem = item;
  628. if (item.nonpagedSystemMemory > fHighestRate)
  629. fHighestRate = item.nonpagedSystemMemory;
  630. if (item.pagedMemory > fHighestRate)
  631. fHighestRate = item.pagedMemory;
  632. if (item.pagedSystemMemory > fHighestRate)
  633. fHighestRate = item.pagedSystemMemory;
  634. if (item.workingSet > fHighestRate)
  635. fHighestRate = item.workingSet;
  636. if (item.gcReportedMem > fHighestRate)
  637. fHighestRate = item.gcReportedMem;
  638. }
  639. for (int i = 0; i < m_memStats.Height - 10; i += 30)
  640. {
  641. float yPos = m_memStats.Height - i - 15;
  642. float fPos = ((float)(i)) / ((float)m_memStats.Height);
  643. gfx.DrawString((fPos * fMax).ToString("##0.00") + " MB",
  644. SystemFonts.DialogFont, Brushes.CadetBlue, 3, yPos);
  645. }
  646. int nPosX = m_memStats.Width - 120;
  647. gfx.DrawString("Working set", SystemFonts.DialogFont, penWorkingSet.Brush, nPosX, 10);
  648. gfx.DrawString("GC Reported mem.", SystemFonts.DialogFont, penGcReported.Brush, nPosX, 22);
  649. gfx.DrawString("Paged mem.", SystemFonts.DialogFont, penPagedMemory.Brush, nPosX, 34);
  650. gfx.DrawString("Paged system mem.", SystemFonts.DialogFont, penPagedSystemMemory.Brush, nPosX, 46);
  651. gfx.DrawString("Nonpaged mem.", SystemFonts.DialogFont, penNonPagedMemory.Brush, nPosX, 58);
  652. screenGfx.DrawImageUnscaled(backBuffer, 0, 0);
  653. m_fMemoryHistoryScale = fHighestRate + 10;
  654. }
  655. void RefreshNetworkStats(TrafficHistory item)
  656. {
  657. m_inUdpTraffic.Text = item.inUdpBytes.ToString("##0.00") + " KB/s";
  658. m_outUdpTraffic.Text = item.outUdpBytes.ToString("##0.00") + " KB/s";
  659. m_inTcpTraffic.Text = item.inTcpBytes.ToString("##0.00") + " KB/s";
  660. m_outTcpTraffic.Text = item.outTcpBytes.ToString("##0.00") + " KB/s";
  661. m_inTotalTraffic.Text = item.inTotalBytes.ToString("##0.00") + " KB/s";
  662. m_outTotalTraffic.Text = item.outTotalBytes.ToString("##0.00") + " KB/s";
  663. }
  664. protected void UpdateTimer(object sender, ElapsedEventArgs ea)
  665. {
  666. if (m_threads.InvokeRequired)
  667. {
  668. m_threads.Invoke(new UpdateControlsDelegate(UpdateControls));
  669. }
  670. else
  671. {
  672. UpdateControls();
  673. }
  674. }
  675. #region Thread items access
  676. void UpdateThreadItem(ProcessThread pt)
  677. {
  678. if (m_threadItems.ContainsKey(pt.Id))
  679. {
  680. ThreadItem item = m_threadItems[pt.Id];
  681. item.cpu.Text = pt.TotalProcessorTime.ToString();
  682. if (m_idToName.ContainsKey(pt.Id))
  683. {
  684. item.name.Text = m_idToName[pt.Id];
  685. }
  686. }
  687. else
  688. {
  689. ThreadItem item = new ThreadItem();
  690. item.listItem = m_threads.Items.Add(pt.Id.ToString());
  691. string name = "[n/a]";
  692. if (m_idToName.ContainsKey(pt.Id))
  693. {
  694. name = m_idToName[pt.Id];
  695. }
  696. item.name = item.listItem.SubItems.Add(name);
  697. item.cpu = item.listItem.SubItems.Add(pt.TotalProcessorTime.ToString());
  698. m_threadItems[pt.Id] = item;
  699. }
  700. }
  701. void RemoveThreadItems(List<int> removed)
  702. {
  703. foreach (int id in removed)
  704. {
  705. m_threads.Items.Remove(m_threadItems[id].listItem);
  706. m_threadItems.Remove(id);
  707. m_idToName.Remove(id);
  708. }
  709. }
  710. private void UpdateThreadList()
  711. {
  712. ProcessThreadCollection threads = Process.GetCurrentProcess().Threads;
  713. lock (m_threadItems)
  714. {
  715. Dictionary<int, int> runningThreads = new Dictionary<int, int>();
  716. foreach (ProcessThread pt in threads)
  717. {
  718. runningThreads[pt.Id] = 0;
  719. UpdateThreadItem(pt);
  720. }
  721. List<int> removed = new List<int>();
  722. foreach (int id in m_threadItems.Keys)
  723. {
  724. if (!runningThreads.ContainsKey(id))
  725. {
  726. removed.Add(id);
  727. }
  728. }
  729. RemoveThreadItems(removed);
  730. }
  731. }
  732. #endregion
  733. }
  734. }