889 lines
34 KiB
C#
889 lines
34 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using System.Timers;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace OpenSim.Framework.ServerStatus
|
|
{
|
|
public partial class StatusWindow : Form
|
|
{
|
|
System.Timers.Timer m_updateTimer;
|
|
static Dictionary<int, ThreadItem> m_threadItems = new Dictionary<int, ThreadItem>();
|
|
static Dictionary<int, string> m_idToName = new Dictionary<int, string>();
|
|
static int m_nCoreCount = System.Environment.ProcessorCount;
|
|
|
|
PerformanceCounter m_pcAvailRam = null;
|
|
|
|
class TrafficHistory {
|
|
public float outUdpBytes = 0;
|
|
public float inUdpBytes = 0;
|
|
public float outTcpBytes = 0;
|
|
public float inTcpBytes = 0;
|
|
public float outTotalBytes = 0;
|
|
public float inTotalBytes = 0;
|
|
public float resentBytes = 0;
|
|
}
|
|
|
|
class MemoryHistory {
|
|
public float nonpagedSystemMemory;
|
|
public float pagedMemory;
|
|
public float pagedSystemMemory;
|
|
public float gcReportedMem;
|
|
public float workingSet;
|
|
}
|
|
|
|
class CpuHistory {
|
|
public float[] cpuUsage = new float[m_nCoreCount];
|
|
public float totalUsage = 0;
|
|
}
|
|
|
|
class PacketItem
|
|
{
|
|
public long m_bytesOut = 0;
|
|
public long m_packetsOut = 0;
|
|
public long m_bytesIn = 0;
|
|
public long m_packetsIn = 0;
|
|
public long m_resent = 0;
|
|
|
|
public bool m_addedToList = false;
|
|
public ListViewItem.ListViewSubItem m_listBytesOut = null;
|
|
public ListViewItem.ListViewSubItem m_listPacketsOut = null;
|
|
public ListViewItem.ListViewSubItem m_listBytesIn = null;
|
|
public ListViewItem.ListViewSubItem m_listPacketsIn = null;
|
|
public ListViewItem.ListViewSubItem m_listResent = null;
|
|
}
|
|
|
|
static float m_fNetworkHistoryScale;
|
|
static float m_fMemoryHistoryScale;
|
|
|
|
static Dictionary<string, PacketItem> m_packets = new Dictionary<string, PacketItem>();
|
|
static LinkedList<TrafficHistory> m_trafficHistory = new LinkedList<TrafficHistory>();
|
|
static LinkedList<MemoryHistory> m_memoryHistory = new LinkedList<MemoryHistory>();
|
|
static LinkedList<CpuHistory> m_cpuHistory = new LinkedList<CpuHistory>();
|
|
|
|
PerformanceCounter[] m_pcCpu = new PerformanceCounter[System.Environment.ProcessorCount];
|
|
PerformanceCounter m_pcCpuTotal = null;
|
|
|
|
static volatile int outUdpBytes = 0;
|
|
static volatile int inUdpBytes = 0;
|
|
static volatile int outTcpBytes = 0;
|
|
static volatile int inTcpBytes = 0;
|
|
static volatile int outResent = 0;
|
|
|
|
BufferedListView m_threads;
|
|
BufferedListView m_listPackets;
|
|
|
|
#region BufferedListView
|
|
/**
|
|
* Flicker minimized listview
|
|
**/
|
|
public class BufferedListView : ListView
|
|
{
|
|
#region WM - Window Messages
|
|
public enum WM
|
|
{
|
|
WM_NULL = 0x0000,
|
|
WM_CREATE = 0x0001,
|
|
WM_DESTROY = 0x0002,
|
|
WM_MOVE = 0x0003,
|
|
WM_SIZE = 0x0005,
|
|
WM_ACTIVATE = 0x0006,
|
|
WM_SETFOCUS = 0x0007,
|
|
WM_KILLFOCUS = 0x0008,
|
|
WM_ENABLE = 0x000A,
|
|
WM_SETREDRAW = 0x000B,
|
|
WM_SETTEXT = 0x000C,
|
|
WM_GETTEXT = 0x000D,
|
|
WM_GETTEXTLENGTH = 0x000E,
|
|
WM_PAINT = 0x000F,
|
|
WM_CLOSE = 0x0010,
|
|
WM_QUERYENDSESSION = 0x0011,
|
|
WM_QUIT = 0x0012,
|
|
WM_QUERYOPEN = 0x0013,
|
|
WM_ERASEBKGND = 0x0014,
|
|
|
|
}
|
|
#endregion
|
|
|
|
#region RECT
|
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
|
public struct RECT
|
|
{
|
|
public int left;
|
|
public int top;
|
|
public int right;
|
|
public int bottom;
|
|
}
|
|
#endregion
|
|
|
|
#region Imported User32.DLL functions
|
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
|
static public extern bool ValidateRect(IntPtr handle, ref RECT rect);
|
|
#endregion
|
|
|
|
#region GetWindowRECT
|
|
// Get the listview's rectangle and return it as a RECT structure
|
|
private RECT GetWindowRECT()
|
|
{
|
|
RECT rect = new RECT();
|
|
rect.left = this.Left;
|
|
rect.right = this.Right;
|
|
rect.top = this.Top;
|
|
rect.bottom = this.Bottom;
|
|
return rect;
|
|
}
|
|
#endregion
|
|
|
|
volatile public bool updating = false;
|
|
|
|
public BufferedListView()
|
|
{
|
|
}
|
|
|
|
|
|
protected override void OnPaintBackground(PaintEventArgs pea)
|
|
{
|
|
// do nothing here since this event is now handled by OnPaint
|
|
}
|
|
|
|
|
|
protected override void OnPaint(PaintEventArgs pea)
|
|
{
|
|
base.OnPaint(pea);
|
|
}
|
|
|
|
protected override void WndProc(ref Message messg)
|
|
{
|
|
if (updating)
|
|
{
|
|
if ((int)WM.WM_ERASEBKGND == messg.Msg)
|
|
{
|
|
return;
|
|
}
|
|
else if ((int)WM.WM_PAINT == messg.Msg)
|
|
{
|
|
RECT vrect = this.GetWindowRECT();
|
|
// validate the entire window
|
|
ValidateRect(this.Handle, ref vrect);
|
|
}
|
|
|
|
}
|
|
base.WndProc(ref messg);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region ThreadItem
|
|
/**
|
|
* Represents a single thread item in the listview control
|
|
**/
|
|
class ThreadItem
|
|
{
|
|
public ListViewItem listItem;
|
|
public ListViewItem.ListViewSubItem name;
|
|
public ListViewItem.ListViewSubItem cpu;
|
|
}
|
|
#endregion
|
|
|
|
|
|
public static void ReportOutPacketUdp(int size, bool resent)
|
|
{
|
|
if (resent)
|
|
{
|
|
outResent += size += 8;
|
|
}
|
|
outUdpBytes += size + 8;
|
|
}
|
|
|
|
public static void ReportInPacketUdp(int size) { inUdpBytes += size + 8; }
|
|
|
|
public static void ReportOutPacketTcp(int size) { outTcpBytes += size + 20; }
|
|
public static void ReportInPacketTcp(int size) { inTcpBytes += size + 20; }
|
|
|
|
public static void ReportProcessedOutPacket(string name, int size, bool resent)
|
|
{
|
|
PacketItem item = null;
|
|
if (m_packets.ContainsKey(name))
|
|
{
|
|
item = m_packets[name];
|
|
}
|
|
else
|
|
{
|
|
item = new PacketItem();
|
|
m_packets[name] = item;
|
|
}
|
|
|
|
if (resent)
|
|
{
|
|
item.m_resent += size;
|
|
}
|
|
item.m_bytesOut += size;
|
|
item.m_packetsOut++;
|
|
}
|
|
|
|
public static void ReportProcessedInPacket(string name, int size)
|
|
{
|
|
PacketItem item = null;
|
|
if (m_packets.ContainsKey(name))
|
|
{
|
|
item = m_packets[name];
|
|
}
|
|
else
|
|
{
|
|
item = new PacketItem();
|
|
m_packets[name] = item;
|
|
}
|
|
|
|
item.m_bytesIn += size;
|
|
item.m_packetsIn++;
|
|
}
|
|
|
|
|
|
public StatusWindow()
|
|
{
|
|
m_pcAvailRam = new PerformanceCounter("Memory", "Available MBytes");
|
|
m_packets = new Dictionary<string, PacketItem>();
|
|
|
|
InitializeComponent();
|
|
|
|
m_listPackets = new BufferedListView();
|
|
m_listPackets.Dock = System.Windows.Forms.DockStyle.Fill;
|
|
m_listPackets.GridLines = true;
|
|
m_listPackets.Location = new System.Drawing.Point(3, 3);
|
|
m_listPackets.MultiSelect = false;
|
|
m_listPackets.Name = "m_listPackets";
|
|
m_listPackets.Size = new System.Drawing.Size(500, 400);
|
|
m_listPackets.TabIndex = 0;
|
|
m_listPackets.View = System.Windows.Forms.View.Details;
|
|
|
|
tabPackets.Controls.Add(m_listPackets);
|
|
|
|
m_listPackets.Columns.Add("Packet").Width = 260;
|
|
m_listPackets.Columns.Add("In count").Width = 80;
|
|
m_listPackets.Columns.Add("In bytes").Width = 80;
|
|
m_listPackets.Columns.Add("Out count").Width = 80;
|
|
m_listPackets.Columns.Add("Out bytes").Width = 80;
|
|
m_listPackets.Columns.Add("Resent").Width = 80;
|
|
|
|
|
|
m_threads = new BufferedListView();
|
|
m_threads.Dock = System.Windows.Forms.DockStyle.Fill;
|
|
m_threads.GridLines = true;
|
|
m_threads.Location = new System.Drawing.Point(3, 3);
|
|
m_threads.MultiSelect = false;
|
|
m_threads.Name = "m_threads";
|
|
m_threads.Size = new System.Drawing.Size(500, 400);
|
|
m_threads.TabIndex = 0;
|
|
m_threads.View = System.Windows.Forms.View.Details;
|
|
|
|
tabThreads.Controls.Add(m_threads);
|
|
|
|
m_threads.Columns.Add("ID");
|
|
m_threads.Columns.Add("Name").Width = 260;
|
|
m_threads.Columns.Add("CPU Time").Width=100;
|
|
|
|
m_updateTimer = new System.Timers.Timer(2000);
|
|
m_updateTimer.Elapsed += new ElapsedEventHandler(UpdateTimer);
|
|
outUdpBytes = 0;
|
|
inUdpBytes = 0;
|
|
outTcpBytes = 0;
|
|
inTcpBytes = 0;
|
|
outResent = 0;
|
|
m_updateTimer.Start();
|
|
|
|
for(int i = 0; i < m_nCoreCount; i++)
|
|
{
|
|
m_pcCpu[i] = new PerformanceCounter("Processor", "% Processor Time", i.ToString(), true);
|
|
m_pcCpu[i].MachineName = ".";
|
|
}
|
|
m_pcCpuTotal = new PerformanceCounter("Processor", "% Processor Time", "_Total", true);
|
|
}
|
|
|
|
public void CloseStatusWindow() {
|
|
Close();
|
|
m_updateTimer.Stop();
|
|
m_threadItems.Clear();
|
|
|
|
m_pcAvailRam.Close();
|
|
m_pcAvailRam = null;
|
|
|
|
for (int i = 0; i < m_nCoreCount; i++)
|
|
{
|
|
m_pcCpu[i].Close();
|
|
m_pcCpu[i] = null;
|
|
}
|
|
|
|
foreach(PacketItem item in m_packets.Values)
|
|
{
|
|
item.m_addedToList = false;
|
|
}
|
|
|
|
m_packets = null;
|
|
|
|
m_pcCpuTotal.Close();
|
|
m_pcCpuTotal = null;
|
|
}
|
|
|
|
public static void ReportThreadName(int id, string name)
|
|
{
|
|
lock (m_threadItems)
|
|
{
|
|
m_idToName[id] = name;
|
|
}
|
|
}
|
|
|
|
delegate void UpdateControlsDelegate();
|
|
|
|
TrafficHistory UpdateNetworkHistory()
|
|
{
|
|
TrafficHistory item = new TrafficHistory();
|
|
|
|
item.inUdpBytes = ((float)inUdpBytes) / 1024.0f / 2.0f;
|
|
item.outUdpBytes = ((float)outUdpBytes) / 1024.0f / 2.0f;
|
|
item.inTcpBytes = ((float)inTcpBytes) / 1024.0f / 2.0f;
|
|
item.outTcpBytes = ((float)outTcpBytes) / 1024.0f / 2.0f;
|
|
item.resentBytes = ((float)outResent) / 1024.0f / 2.0f;
|
|
item.inTotalBytes = item.inUdpBytes + item.inTcpBytes;
|
|
item.outTotalBytes = item.outUdpBytes + item.outTcpBytes;
|
|
inUdpBytes = 0;
|
|
outUdpBytes = 0;
|
|
inTcpBytes = 0;
|
|
outTcpBytes = 0;
|
|
outResent = 0;
|
|
|
|
m_trafficHistory.AddFirst(item);
|
|
if (m_trafficHistory.Count > 500)
|
|
{
|
|
m_trafficHistory.RemoveLast();
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
MemoryHistory UpdateMemoryHistory(Process proc)
|
|
{
|
|
MemoryHistory item = new MemoryHistory();
|
|
|
|
item.gcReportedMem = ((float)System.GC.GetTotalMemory(false)) / 1024.0f / 1024.0f;
|
|
item.workingSet = ((float)proc.WorkingSet64) / 1024.0f / 1024.0f;
|
|
item.nonpagedSystemMemory = ((float)proc.NonpagedSystemMemorySize64) / 1024.0f / 1024.0f;
|
|
item.pagedSystemMemory = ((float)proc.PagedMemorySize64) / 1024.0f / 1024.0f;
|
|
item.pagedSystemMemory = ((float)proc.PagedSystemMemorySize64) / 1024.0f / 1024.0f;
|
|
|
|
m_memoryHistory.AddFirst(item);
|
|
if (m_memoryHistory.Count > 500)
|
|
{
|
|
m_memoryHistory.RemoveLast();
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
void UpdateCpuHistory() {
|
|
CpuHistory item = new CpuHistory();
|
|
|
|
for( int i = 0; i < m_nCoreCount; i++)
|
|
{
|
|
item.cpuUsage[i] = m_pcCpu[i].NextValue();
|
|
}
|
|
|
|
item.totalUsage = m_pcCpuTotal.NextValue();
|
|
|
|
m_cpuHistory.AddFirst(item);
|
|
if (m_cpuHistory.Count > 500)
|
|
{
|
|
m_cpuHistory.RemoveLast();
|
|
}
|
|
}
|
|
|
|
string FormatDataSize(long byteCount)
|
|
{
|
|
double fCount = (double)byteCount;
|
|
if (byteCount > 1024 * 1024 * 1024)
|
|
{
|
|
fCount/=(1024.0*1024.0*1024.0);
|
|
return fCount.ToString("##0.00") + "GB";
|
|
}
|
|
else if (byteCount > 1024*1024*10)
|
|
{
|
|
fCount/=(1024.0*1024.0);
|
|
return fCount.ToString("##0.00") + "MB";
|
|
}
|
|
else if (byteCount > 1024*10)
|
|
{
|
|
fCount/=1024.0;
|
|
return fCount.ToString("##0.00") + "KB";
|
|
}
|
|
else
|
|
{
|
|
return byteCount.ToString() +"B";
|
|
}
|
|
}
|
|
|
|
void UpdatePacketView()
|
|
{
|
|
foreach(KeyValuePair<string, PacketItem> item in m_packets)
|
|
{
|
|
if (item.Value.m_addedToList)
|
|
{
|
|
item.Value.m_listPacketsIn.Text = item.Value.m_packetsIn.ToString();
|
|
item.Value.m_listBytesIn.Text = FormatDataSize(item.Value.m_bytesIn);
|
|
item.Value.m_listPacketsOut.Text = item.Value.m_packetsOut.ToString();
|
|
item.Value.m_listBytesOut.Text = FormatDataSize(item.Value.m_bytesOut);
|
|
item.Value.m_listResent.Text = FormatDataSize(item.Value.m_resent);
|
|
}
|
|
else
|
|
{
|
|
ListViewItem listItem = m_listPackets.Items.Add(item.Key);
|
|
item.Value.m_listPacketsIn = listItem.SubItems.Add(item.Value.m_packetsIn.ToString());
|
|
item.Value.m_listBytesIn = listItem.SubItems.Add(FormatDataSize(item.Value.m_bytesIn));
|
|
item.Value.m_listPacketsOut = listItem.SubItems.Add(item.Value.m_packetsOut.ToString());
|
|
item.Value.m_listBytesOut = listItem.SubItems.Add(FormatDataSize(item.Value.m_bytesOut));
|
|
item.Value.m_listResent = listItem.SubItems.Add(FormatDataSize(item.Value.m_resent));
|
|
item.Value.m_addedToList = true;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
void UpdateControls()
|
|
{
|
|
Process proc = Process.GetCurrentProcess();
|
|
|
|
TrafficHistory netItem = UpdateNetworkHistory();
|
|
MemoryHistory memItem = UpdateMemoryHistory(proc);
|
|
|
|
UpdateCpuHistory();
|
|
|
|
if (tabControl1.SelectedIndex == 0)
|
|
{
|
|
m_threads.updating = true;
|
|
UpdateThreadList();
|
|
m_threads.updating = false;
|
|
m_threads.Invalidate();
|
|
}
|
|
else if (tabControl1.SelectedIndex == 1)
|
|
{
|
|
RefreshNetworkStats(netItem);
|
|
PaintNetworkHistory();
|
|
}
|
|
else if (tabControl1.SelectedIndex == 2)
|
|
{
|
|
m_availableMem.Text = m_pcAvailRam.NextValue().ToString("##0.00") + " MB";
|
|
m_commitSize.Text = memItem.workingSet.ToString("##0.00") + " MB";
|
|
PaintMemoryHistory();
|
|
}
|
|
else if (tabControl1.SelectedIndex == 3)
|
|
{
|
|
PaintCpuHistory();
|
|
}
|
|
else if (tabControl1.SelectedIndex == 4)
|
|
{
|
|
m_listPackets.updating = true;
|
|
UpdatePacketView();
|
|
m_listPackets.updating = false;
|
|
m_listPackets.Invalidate();
|
|
}
|
|
}
|
|
|
|
protected void PaintCpuHistory()
|
|
{
|
|
Pen[] pens = { Pens.Yellow, Pens.Blue, Pens.Green, Pens.Red,
|
|
Pens.White, Pens.Turquoise, Pens.Linen, Pens.Gray,
|
|
Pens.Purple, Pens.Pink, Pens.LightBlue, Pens.LightSalmon};
|
|
|
|
Pen penLine = Pens.DarkSlateGray;
|
|
|
|
Graphics screenGfx = m_cpuDrawing.CreateGraphics();
|
|
Bitmap backBuffer = new Bitmap(m_cpuDrawing.Width, m_cpuDrawing.Height);
|
|
Graphics gfx = Graphics.FromImage(backBuffer);
|
|
|
|
gfx.Clear(Color.Black);
|
|
|
|
float fMax = 105.0f;
|
|
for (int i = 0; i < m_cpuDrawing.Height - 10; i += 30)
|
|
{
|
|
float yPos = m_cpuDrawing.Height - i - 15;
|
|
float fPos = ((float)(i)) / ((float)m_cpuDrawing.Height);
|
|
gfx.DrawLine(penLine, 0, yPos, m_cpuDrawing.Width, yPos);
|
|
}
|
|
|
|
//Size of second in pixels
|
|
float fSecondStep = 2.5f; //120 seconds
|
|
float fTotalSeconds = (1 / fSecondStep) * (m_cpuDrawing.Width - 90);
|
|
for (int i = 0; i < m_cpuDrawing.Width - 90; i += 50)
|
|
{
|
|
float xPos = 90 + i;
|
|
float fTime = fTotalSeconds - (((float)(i)) / fSecondStep);
|
|
|
|
gfx.DrawLine(penLine, xPos, 0, xPos, m_cpuDrawing.Height - 15);
|
|
string strText = fTime.ToString("##0");
|
|
gfx.DrawString(strText, SystemFonts.DialogFont, Brushes.CadetBlue,
|
|
xPos - 4 * strText.Length, m_cpuDrawing.Height - 15);
|
|
}
|
|
|
|
|
|
float nXPos = m_cpuDrawing.Width;
|
|
float fHeightMul = m_cpuDrawing.Height - 15;
|
|
float fYStart = m_cpuDrawing.Height - 15;
|
|
CpuHistory lastItem = null;
|
|
|
|
foreach (CpuHistory item in m_cpuHistory)
|
|
{
|
|
if (lastItem != null)
|
|
{
|
|
nXPos -= fSecondStep * 2;
|
|
|
|
for (int i = 0; i < m_nCoreCount; i++)
|
|
{
|
|
gfx.DrawLine(pens[i+1], nXPos, fYStart - (item.cpuUsage[i] / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.cpuUsage[i] / fMax) * fHeightMul);
|
|
}
|
|
|
|
gfx.DrawLine(pens[0], nXPos, fYStart - (item.totalUsage / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.totalUsage / fMax) * fHeightMul);
|
|
|
|
if (nXPos < 0)
|
|
break;
|
|
}
|
|
|
|
lastItem = item;
|
|
}
|
|
|
|
for (int i = 0; i < m_cpuDrawing.Height - 10; i += 30)
|
|
{
|
|
float yPos = m_cpuDrawing.Height - i - 15;
|
|
float fPos = ((float)(i)) / ((float)m_cpuDrawing.Height);
|
|
gfx.DrawString((fPos * fMax).ToString("##0.00") + "%",
|
|
SystemFonts.DialogFont, Brushes.CadetBlue, 3, yPos);
|
|
}
|
|
|
|
int nPosX = m_cpuDrawing.Width - 50;
|
|
|
|
|
|
gfx.DrawString("Total", SystemFonts.DialogFont, pens[0].Brush, nPosX, 10);
|
|
for (int i = 0; i < m_nCoreCount; i++ )
|
|
{
|
|
gfx.DrawString("Core " + i, SystemFonts.DialogFont, pens[i+1].Brush, nPosX, 22 + i * 12);
|
|
}
|
|
|
|
screenGfx.DrawImageUnscaled(backBuffer, 0, 0);
|
|
}
|
|
|
|
protected void PaintNetworkHistory()
|
|
{
|
|
Pen penUdpOut = Pens.SkyBlue;
|
|
Pen penUdpIn = Pens.Blue;
|
|
Pen penTcpOut = Pens.Red;
|
|
Pen penTcpIn = Pens.Pink;
|
|
Pen penTotalOut = Pens.Green;
|
|
Pen penTotalIn = Pens.LimeGreen;
|
|
Pen penResent = Pens.Orange;
|
|
|
|
Pen penLine = Pens.DarkSlateGray;
|
|
|
|
|
|
Graphics screenGfx = m_networkDrawing.CreateGraphics();
|
|
Bitmap backBuffer = new Bitmap(m_networkDrawing.Width, m_networkDrawing.Height);
|
|
Graphics gfx = Graphics.FromImage(backBuffer);
|
|
|
|
gfx.Clear(Color.Black);
|
|
|
|
float fMax = m_fNetworkHistoryScale;
|
|
if (fMax < 12.0f)
|
|
fMax = 12.0f;
|
|
for( int i = 0; i < m_networkDrawing.Height-10; i+= 30)
|
|
{
|
|
float yPos = m_networkDrawing.Height - i-15;
|
|
float fPos = ((float)(i)) / ((float)m_networkDrawing.Height);
|
|
gfx.DrawLine(penLine, 0, yPos, m_networkDrawing.Width, yPos);
|
|
}
|
|
|
|
//Size of second in pixels
|
|
float fSecondStep = 1.5f; //120 seconds
|
|
float fTotalSeconds = (1/fSecondStep) * (m_networkDrawing.Width - 90);
|
|
for( int i = 0; i < m_networkDrawing.Width-90; i+= 50)
|
|
{
|
|
float xPos = 90 + i;
|
|
float fTime = fTotalSeconds - (((float)(i)) / fSecondStep);
|
|
|
|
gfx.DrawLine(penLine, xPos, 0, xPos, m_networkDrawing.Height - 15);
|
|
string strText = fTime.ToString("##0");
|
|
gfx.DrawString(strText, SystemFonts.DialogFont, Brushes.CadetBlue,
|
|
xPos - 4 * strText.Length, m_networkDrawing.Height - 15);
|
|
}
|
|
|
|
|
|
float nXPos = m_networkDrawing.Width;
|
|
float fHeightMul = m_networkDrawing.Height - 15;
|
|
float fYStart = m_networkDrawing.Height - 15;
|
|
TrafficHistory lastItem = null;
|
|
|
|
float fHighestRate = 0;
|
|
foreach(TrafficHistory item in m_trafficHistory) {
|
|
if (lastItem != null)
|
|
{
|
|
nXPos -= fSecondStep * 2;
|
|
|
|
gfx.DrawLine(penUdpIn, nXPos, fYStart - (item.inUdpBytes / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.inUdpBytes / fMax) * fHeightMul);
|
|
gfx.DrawLine(penUdpOut, nXPos, fYStart - (item.outUdpBytes / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.outUdpBytes / fMax) * fHeightMul);
|
|
|
|
gfx.DrawLine(penTcpIn, nXPos, fYStart - (item.inTcpBytes / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.inTcpBytes / fMax) * fHeightMul);
|
|
gfx.DrawLine(penTcpOut, nXPos, fYStart - (item.outTcpBytes / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.outTcpBytes / fMax) * fHeightMul);
|
|
|
|
gfx.DrawLine(penTotalIn, nXPos, fYStart - (item.inTotalBytes / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.inTotalBytes / fMax) * fHeightMul);
|
|
gfx.DrawLine(penTotalOut, nXPos, fYStart - (item.outTotalBytes / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.outTotalBytes / fMax) * fHeightMul);
|
|
|
|
gfx.DrawLine(penResent, nXPos, fYStart - (item.resentBytes / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.resentBytes / fMax) * fHeightMul);
|
|
|
|
if (nXPos < 0)
|
|
break;
|
|
}
|
|
lastItem = item;
|
|
if (item.inTotalBytes > fHighestRate)
|
|
fHighestRate = item.inTotalBytes;
|
|
if (item.outTotalBytes > fHighestRate)
|
|
fHighestRate = item.outTotalBytes;
|
|
}
|
|
|
|
for (int i = 0; i < m_networkDrawing.Height - 10; i += 30)
|
|
{
|
|
float yPos = m_networkDrawing.Height - i - 15;
|
|
float fPos = ((float)(i)) / ((float)m_networkDrawing.Height);
|
|
gfx.DrawString((fPos * fMax).ToString("##0.00") + " KB/s",
|
|
SystemFonts.DialogFont, Brushes.CadetBlue, 3, yPos);
|
|
}
|
|
|
|
int nPosX = m_networkDrawing.Width-60;
|
|
gfx.DrawString("Udp in", SystemFonts.DialogFont, penUdpIn.Brush, nPosX, 10);
|
|
gfx.DrawString("Udp out", SystemFonts.DialogFont, penUdpOut.Brush, nPosX, 22);
|
|
gfx.DrawString("Tcp in", SystemFonts.DialogFont, penTcpIn.Brush, nPosX, 34);
|
|
gfx.DrawString("Tcp out", SystemFonts.DialogFont, penTcpOut.Brush, nPosX, 46);
|
|
gfx.DrawString("Total in", SystemFonts.DialogFont, penTotalIn.Brush, nPosX, 58);
|
|
gfx.DrawString("Total out", SystemFonts.DialogFont, penTotalOut.Brush, nPosX, 70);
|
|
gfx.DrawString("Resent", SystemFonts.DialogFont, penResent.Brush, nPosX, 82);
|
|
|
|
screenGfx.DrawImageUnscaled(backBuffer, 0, 0);
|
|
|
|
m_fNetworkHistoryScale = fHighestRate + 10;
|
|
}
|
|
|
|
protected void PaintMemoryHistory()
|
|
{
|
|
Pen penPagedMemory = Pens.Gray;
|
|
Pen penPagedSystemMemory = Pens.Orange;
|
|
Pen penNonPagedMemory = Pens.LawnGreen;
|
|
Pen penWorkingSet = Pens.HotPink;
|
|
Pen penGcReported = Pens.Red;
|
|
|
|
|
|
Pen penLine = Pens.DarkSlateGray;
|
|
|
|
Graphics screenGfx = m_memStats.CreateGraphics();
|
|
Bitmap backBuffer = new Bitmap(m_memStats.Width, m_memStats.Height);
|
|
Graphics gfx = Graphics.FromImage(backBuffer);
|
|
|
|
gfx.Clear(Color.Black);
|
|
|
|
float fMax = m_fMemoryHistoryScale;
|
|
if (fMax < 12.0f)
|
|
fMax = 12.0f;
|
|
for (int i = 0; i < m_memStats.Height - 10; i += 30)
|
|
{
|
|
float yPos = m_memStats.Height - i - 15;
|
|
float fPos = ((float)(i)) / ((float)m_memStats.Height);
|
|
gfx.DrawLine(penLine, 0, yPos, m_memStats.Width, yPos);
|
|
}
|
|
|
|
//Size of second in pixels
|
|
float fSecondStep = 1.5f; //120 seconds
|
|
float fTotalSeconds = (1 / fSecondStep) * (m_memStats.Width - 90);
|
|
for (int i = 0; i < m_memStats.Width - 90; i += 50)
|
|
{
|
|
float xPos = 90 + i;
|
|
float fTime = fTotalSeconds - (((float)(i)) / fSecondStep);
|
|
|
|
gfx.DrawLine(penLine, xPos, 0, xPos, m_memStats.Height - 15);
|
|
string strText = fTime.ToString("##0");
|
|
gfx.DrawString(strText, SystemFonts.DialogFont, Brushes.CadetBlue,
|
|
xPos - 4 * strText.Length, m_memStats.Height - 15);
|
|
}
|
|
|
|
|
|
float nXPos = m_memStats.Width;
|
|
float fHeightMul = m_memStats.Height - 15;
|
|
float fYStart = m_memStats.Height - 15;
|
|
MemoryHistory lastItem = null;
|
|
|
|
float fHighestRate = 0;
|
|
foreach (MemoryHistory item in m_memoryHistory)
|
|
{
|
|
if (lastItem != null)
|
|
{
|
|
|
|
nXPos -= fSecondStep * 2;
|
|
|
|
gfx.DrawLine(penPagedMemory, nXPos, fYStart - (item.pagedMemory / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.pagedMemory / fMax) * fHeightMul);
|
|
|
|
gfx.DrawLine(penPagedSystemMemory, nXPos, fYStart - (item.pagedSystemMemory / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.pagedSystemMemory / fMax) * fHeightMul);
|
|
|
|
gfx.DrawLine(penNonPagedMemory, nXPos, fYStart - (item.nonpagedSystemMemory / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.nonpagedSystemMemory / fMax) * fHeightMul);
|
|
|
|
gfx.DrawLine(penWorkingSet, nXPos, fYStart - (item.workingSet / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.workingSet / fMax) * fHeightMul);
|
|
|
|
gfx.DrawLine(penGcReported, nXPos, fYStart - (item.gcReportedMem / fMax) * fHeightMul,
|
|
nXPos + fSecondStep * 2, fYStart - (lastItem.gcReportedMem / fMax) * fHeightMul);
|
|
|
|
if (nXPos < 0)
|
|
break;
|
|
}
|
|
|
|
lastItem = item;
|
|
if (item.nonpagedSystemMemory > fHighestRate)
|
|
fHighestRate = item.nonpagedSystemMemory;
|
|
if (item.pagedMemory > fHighestRate)
|
|
fHighestRate = item.pagedMemory;
|
|
if (item.pagedSystemMemory > fHighestRate)
|
|
fHighestRate = item.pagedSystemMemory;
|
|
if (item.workingSet > fHighestRate)
|
|
fHighestRate = item.workingSet;
|
|
if (item.gcReportedMem > fHighestRate)
|
|
fHighestRate = item.gcReportedMem;
|
|
}
|
|
|
|
for (int i = 0; i < m_memStats.Height - 10; i += 30)
|
|
{
|
|
float yPos = m_memStats.Height - i - 15;
|
|
float fPos = ((float)(i)) / ((float)m_memStats.Height);
|
|
gfx.DrawString((fPos * fMax).ToString("##0.00") + " MB",
|
|
SystemFonts.DialogFont, Brushes.CadetBlue, 3, yPos);
|
|
}
|
|
|
|
int nPosX = m_memStats.Width - 120;
|
|
|
|
gfx.DrawString("Working set", SystemFonts.DialogFont, penWorkingSet.Brush, nPosX, 10);
|
|
gfx.DrawString("GC Reported mem.", SystemFonts.DialogFont, penGcReported.Brush, nPosX, 22);
|
|
gfx.DrawString("Paged mem.", SystemFonts.DialogFont, penPagedMemory.Brush, nPosX, 34);
|
|
gfx.DrawString("Paged system mem.", SystemFonts.DialogFont, penPagedSystemMemory.Brush, nPosX, 46);
|
|
gfx.DrawString("Nonpaged mem.", SystemFonts.DialogFont, penNonPagedMemory.Brush, nPosX, 58);
|
|
|
|
screenGfx.DrawImageUnscaled(backBuffer, 0, 0);
|
|
|
|
m_fMemoryHistoryScale = fHighestRate + 10;
|
|
}
|
|
|
|
void RefreshNetworkStats(TrafficHistory item)
|
|
{
|
|
m_inUdpTraffic.Text = item.inUdpBytes.ToString("##0.00") + " KB/s";
|
|
m_outUdpTraffic.Text = item.outUdpBytes.ToString("##0.00") + " KB/s";
|
|
m_inTcpTraffic.Text = item.inTcpBytes.ToString("##0.00") + " KB/s";
|
|
m_outTcpTraffic.Text = item.outTcpBytes.ToString("##0.00") + " KB/s";
|
|
m_inTotalTraffic.Text = item.inTotalBytes.ToString("##0.00") + " KB/s";
|
|
m_outTotalTraffic.Text = item.outTotalBytes.ToString("##0.00") + " KB/s";
|
|
}
|
|
|
|
protected void UpdateTimer(object sender, ElapsedEventArgs ea)
|
|
{
|
|
if (m_threads.InvokeRequired)
|
|
{
|
|
m_threads.Invoke(new UpdateControlsDelegate(UpdateControls));
|
|
}
|
|
else
|
|
{
|
|
UpdateControls();
|
|
}
|
|
}
|
|
|
|
|
|
#region Thread items access
|
|
void UpdateThreadItem(ProcessThread pt)
|
|
{
|
|
if (m_threadItems.ContainsKey(pt.Id))
|
|
{
|
|
ThreadItem item = m_threadItems[pt.Id];
|
|
|
|
item.cpu.Text = pt.TotalProcessorTime.ToString();
|
|
if (m_idToName.ContainsKey(pt.Id))
|
|
{
|
|
item.name.Text = m_idToName[pt.Id];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ThreadItem item = new ThreadItem();
|
|
item.listItem = m_threads.Items.Add(pt.Id.ToString());
|
|
string name = "[n/a]";
|
|
if (m_idToName.ContainsKey(pt.Id))
|
|
{
|
|
name = m_idToName[pt.Id];
|
|
}
|
|
item.name = item.listItem.SubItems.Add(name);
|
|
item.cpu = item.listItem.SubItems.Add(pt.TotalProcessorTime.ToString());
|
|
|
|
m_threadItems[pt.Id] = item;
|
|
}
|
|
}
|
|
|
|
void RemoveThreadItems(List<int> removed)
|
|
{
|
|
foreach (int id in removed)
|
|
{
|
|
m_threads.Items.Remove(m_threadItems[id].listItem);
|
|
m_threadItems.Remove(id);
|
|
m_idToName.Remove(id);
|
|
}
|
|
}
|
|
|
|
private void UpdateThreadList()
|
|
{
|
|
ProcessThreadCollection threads = Process.GetCurrentProcess().Threads;
|
|
|
|
lock (m_threadItems)
|
|
{
|
|
Dictionary<int, int> runningThreads = new Dictionary<int, int>();
|
|
|
|
foreach (ProcessThread pt in threads)
|
|
{
|
|
runningThreads[pt.Id] = 0;
|
|
|
|
UpdateThreadItem(pt);
|
|
}
|
|
|
|
List<int> removed = new List<int>();
|
|
foreach (int id in m_threadItems.Keys)
|
|
{
|
|
if (!runningThreads.ContainsKey(id))
|
|
{
|
|
removed.Add(id);
|
|
}
|
|
}
|
|
|
|
RemoveThreadItems(removed);
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void m_callGCButton_Click(object sender, EventArgs e)
|
|
{
|
|
System.GC.Collect();
|
|
}
|
|
}
|
|
} |