Browse Source

new traffic chart style (#704)

* new traffic chart style
- remove invoke
- force to set AxisY.Maximum not zero
- format LogForm.cs

* avoid data race
tags/3.3
破娃酱 Syrone Wong 8 years ago
parent
commit
59c315d465
4 changed files with 117 additions and 43 deletions
  1. +1
    -1
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  2. +38
    -0
      shadowsocks-csharp/Util/Util.cs
  3. +4
    -0
      shadowsocks-csharp/View/LogForm.Designer.cs
  4. +74
    -42
      shadowsocks-csharp/View/LogForm.cs

+ 1
- 1
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -89,7 +89,7 @@ namespace Shadowsocks.Controller
StatisticsConfiguration = StatisticsStrategyConfiguration.Load(); StatisticsConfiguration = StatisticsStrategyConfiguration.Load();
_strategyManager = new StrategyManager(this); _strategyManager = new StrategyManager(this);
StartReleasingMemory(); StartReleasingMemory();
StartTrafficStatistics(60);
StartTrafficStatistics(61);
} }
public void Start() public void Start()


+ 38
- 0
shadowsocks-csharp/Util/Util.cs View File

@@ -117,6 +117,44 @@ namespace Shadowsocks.Util
return $"{result.Item1:0.##}{result.Item2}"; return $"{result.Item1:0.##}{result.Item2}";
} }
public static string FormatBytes(long bytes)
{
const long K = 1024L;
const long M = K * 1024L;
const long G = M * 1024L;
const long T = G * 1024L;
const long P = T * 1024L;
const long E = P * 1024L;
if (bytes >= P * 990)
return (bytes / (double)E).ToString("F5") + "EB";
if (bytes >= T * 990)
return (bytes / (double)P).ToString("F5") + "PB";
if (bytes >= G * 990)
return (bytes / (double)T).ToString("F5") + "TB";
if (bytes >= M * 990)
{
return (bytes / (double)G).ToString("F4") + "GB";
}
if (bytes >= M * 100)
{
return (bytes / (double)M).ToString("F1") + "MB";
}
if (bytes >= M * 10)
{
return (bytes / (double)M).ToString("F2") + "MB";
}
if (bytes >= K * 990)
{
return (bytes / (double)M).ToString("F3") + "MB";
}
if (bytes > K * 2)
{
return (bytes / (double)K).ToString("F1") + "KB";
}
return bytes.ToString();
}
/// <summary> /// <summary>
/// Return scaled bandwidth /// Return scaled bandwidth
/// </summary> /// </summary>


+ 4
- 0
shadowsocks-csharp/View/LogForm.Designer.cs View File

@@ -250,6 +250,8 @@
chartArea1.AxisX.MajorGrid.Interval = 5D; chartArea1.AxisX.MajorGrid.Interval = 5D;
chartArea1.AxisX.MajorGrid.LineColor = System.Drawing.Color.LightGray; chartArea1.AxisX.MajorGrid.LineColor = System.Drawing.Color.LightGray;
chartArea1.AxisX.MajorTickMark.Enabled = false; chartArea1.AxisX.MajorTickMark.Enabled = false;
chartArea1.AxisX.Maximum = 61D;
chartArea1.AxisX.Minimum = 1D;
chartArea1.AxisY.IntervalAutoMode = System.Windows.Forms.DataVisualization.Charting.IntervalAutoMode.VariableCount; chartArea1.AxisY.IntervalAutoMode = System.Windows.Forms.DataVisualization.Charting.IntervalAutoMode.VariableCount;
chartArea1.AxisY.LabelAutoFitMaxFontSize = 8; chartArea1.AxisY.LabelAutoFitMaxFontSize = 8;
chartArea1.AxisY.LabelStyle.Interval = 0D; chartArea1.AxisY.LabelStyle.Interval = 0D;
@@ -266,12 +268,14 @@
this.trafficChart.Location = new System.Drawing.Point(0, 0); this.trafficChart.Location = new System.Drawing.Point(0, 0);
this.trafficChart.Name = "trafficChart"; this.trafficChart.Name = "trafficChart";
this.trafficChart.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.None; this.trafficChart.Palette = System.Windows.Forms.DataVisualization.Charting.ChartColorPalette.None;
series1.BorderWidth = 2;
series1.ChartArea = "ChartArea1"; series1.ChartArea = "ChartArea1";
series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line; series1.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
series1.Color = System.Drawing.Color.FromArgb(255, 128, 0); series1.Color = System.Drawing.Color.FromArgb(255, 128, 0);
series1.IsXValueIndexed = true; series1.IsXValueIndexed = true;
series1.Legend = "Legend1"; series1.Legend = "Legend1";
series1.Name = "Inbound"; series1.Name = "Inbound";
series2.BorderWidth = 2;
series2.ChartArea = "ChartArea1"; series2.ChartArea = "ChartArea1";
series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line; series2.ChartType = System.Windows.Forms.DataVisualization.Charting.SeriesChartType.Line;
series2.Color = System.Drawing.Color.FromArgb(128, 128, 255); series2.Color = System.Drawing.Color.FromArgb(128, 128, 255);


+ 74
- 42
shadowsocks-csharp/View/LogForm.cs View File

@@ -22,11 +22,8 @@ namespace Shadowsocks.View
ShadowsocksController controller; ShadowsocksController controller;
#region chart #region chart
List<float> inboundPoints = new List<float>();
List<float> outboundPoints = new List<float>();
Tuple<float, string, long> bandwidthScale = new Tuple<float, string, long>(0, "B", 1);
TextAnnotation inboundAnnotation = new TextAnnotation();
TextAnnotation outboundAnnotation = new TextAnnotation();
long lastMaxSpeed;
public ShadowsocksController.QueueLast<Tuple<long, long>> traffic = new ShadowsocksController.QueueLast<Tuple<long, long>>();
#endregion #endregion
public LogForm(ShadowsocksController controller, string filename) public LogForm(ShadowsocksController controller, string filename)
@@ -56,16 +53,40 @@ namespace Shadowsocks.View
UpdateTexts(); UpdateTexts();
} }
private void controller_TrafficChanged(object sender, EventArgs e)
private void update_TrafficChart()
{ {
List<float> inboundPoints = new List<float>();
List<float> outboundPoints = new List<float>();
TextAnnotation inboundAnnotation = new TextAnnotation();
TextAnnotation outboundAnnotation = new TextAnnotation();
Tuple<float, string, long> bandwidthScale;
const long minScale = 50;
long maxSpeed = 0; long maxSpeed = 0;
inboundPoints.Clear();
outboundPoints.Clear();
foreach (var trafficPerSecond in controller.traffic)
long lastInbound, lastOutbound;
lock (this)
{ {
inboundPoints.Add(trafficPerSecond.inboundIncreasement);
outboundPoints.Add(trafficPerSecond.outboundIncreasement);
maxSpeed = Math.Max(maxSpeed, Math.Max(trafficPerSecond.inboundIncreasement, trafficPerSecond.outboundIncreasement));
if (traffic.Count == 0)
return;
foreach (var trafficPerSecond in traffic)
{
inboundPoints.Add(trafficPerSecond.Item1);
outboundPoints.Add(trafficPerSecond.Item2);
maxSpeed = Math.Max(maxSpeed, Math.Max(trafficPerSecond.Item1, trafficPerSecond.Item2));
}
lastInbound = traffic.Last().Item1;
lastOutbound = traffic.Last().Item2;
}
if (maxSpeed > 0)
{
lastMaxSpeed -= lastMaxSpeed / 32;
maxSpeed = Math.Max(minScale, Math.Max(maxSpeed, lastMaxSpeed));
lastMaxSpeed = maxSpeed;
}
else
{
maxSpeed = lastMaxSpeed = minScale;
} }
bandwidthScale = Utils.GetBandwidthScale(maxSpeed); bandwidthScale = Utils.GetBandwidthScale(maxSpeed);
@@ -74,29 +95,31 @@ namespace Shadowsocks.View
inboundPoints = inboundPoints.Select(p => p / bandwidthScale.Item3).ToList(); inboundPoints = inboundPoints.Select(p => p / bandwidthScale.Item3).ToList();
outboundPoints = outboundPoints.Select(p => p / bandwidthScale.Item3).ToList(); outboundPoints = outboundPoints.Select(p => p / bandwidthScale.Item3).ToList();
try
if (trafficChart.IsHandleCreated)
{ {
if (trafficChart.InvokeRequired && trafficChart.IsHandleCreated)
{
trafficChart.Invoke(new Action(() =>
{
trafficChart.Series["Inbound"].Points.DataBindY(inboundPoints);
trafficChart.Series["Outbound"].Points.DataBindY(outboundPoints);
trafficChart.ChartAreas[0].AxisY.LabelStyle.Format = "{0:0.##} " + bandwidthScale.Item2;
inboundAnnotation.AnchorDataPoint = trafficChart.Series["Inbound"].Points.Last();
inboundAnnotation.Text = Utils.FormatBandwidth(controller.traffic.Last.inboundIncreasement);
outboundAnnotation.AnchorDataPoint = trafficChart.Series["Outbound"].Points.Last();
outboundAnnotation.Text = Utils.FormatBandwidth(controller.traffic.Last.outboundIncreasement);
trafficChart.Annotations.Clear();
trafficChart.Annotations.Add(inboundAnnotation);
trafficChart.Annotations.Add(outboundAnnotation);
}));
}
trafficChart.Series["Inbound"].Points.DataBindY(inboundPoints);
trafficChart.Series["Outbound"].Points.DataBindY(outboundPoints);
trafficChart.ChartAreas[0].AxisY.LabelStyle.Format = "{0:0.##} " + bandwidthScale.Item2;
trafficChart.ChartAreas[0].AxisY.Maximum = bandwidthScale.Item1;
inboundAnnotation.AnchorDataPoint = trafficChart.Series["Inbound"].Points.Last();
inboundAnnotation.Text = Utils.FormatBandwidth(lastInbound);
outboundAnnotation.AnchorDataPoint = trafficChart.Series["Outbound"].Points.Last();
outboundAnnotation.Text = Utils.FormatBandwidth(lastOutbound);
trafficChart.Annotations.Clear();
trafficChart.Annotations.Add(inboundAnnotation);
trafficChart.Annotations.Add(outboundAnnotation);
} }
catch (ObjectDisposedException)
}
private void controller_TrafficChanged(object sender, EventArgs e)
{
lock (this)
{ {
// suppress the thread race error:
// when closing the form but the Invoked Action is still working and cause 'Chart is Disposed' exception
traffic = new ShadowsocksController.QueueLast<Tuple<long, long>>();
foreach (var trafficPerSecond in controller.traffic)
{
traffic.Enqueue(new Tuple<long, long>(trafficPerSecond.inboundIncreasement, trafficPerSecond.outboundIncreasement));
}
} }
} }
@@ -124,6 +147,7 @@ namespace Shadowsocks.View
private void Timer_Tick(object sender, EventArgs e) private void Timer_Tick(object sender, EventArgs e)
{ {
UpdateContent(); UpdateContent();
update_TrafficChart();
} }
private void InitContent() private void InitContent()
@@ -149,29 +173,35 @@ namespace Shadowsocks.View
private void UpdateContent() private void UpdateContent()
{ {
try {
using(StreamReader reader = new StreamReader(new FileStream(filename,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) {
try
{
using (StreamReader reader = new StreamReader(new FileStream(filename,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
{
reader.BaseStream.Seek(lastOffset, SeekOrigin.Begin); reader.BaseStream.Seek(lastOffset, SeekOrigin.Begin);
string line = ""; string line = "";
bool changed = false; bool changed = false;
while((line = reader.ReadLine()) != null) {
while ((line = reader.ReadLine()) != null)
{
changed = true; changed = true;
LogMessageTextBox.AppendText(line + Environment.NewLine); LogMessageTextBox.AppendText(line + Environment.NewLine);
} }
if(changed) {
if (changed)
{
LogMessageTextBox.ScrollToCaret(); LogMessageTextBox.ScrollToCaret();
} }
lastOffset = reader.BaseStream.Position; lastOffset = reader.BaseStream.Position;
} }
} catch(FileNotFoundException) {
}
catch (FileNotFoundException)
{
} }
this.Text = I18N.GetString("Log Viewer") + this.Text = I18N.GetString("Log Viewer") +
$" [in: {Utils.FormatBandwidth(controller.InboundCounter)}, out: {Utils.FormatBandwidth(controller.OutboundCounter)}]";
$" [in: {Utils.FormatBytes(controller.InboundCounter)}, out: {Utils.FormatBytes(controller.OutboundCounter)}]";
} }
private void LogForm_Load(object sender, EventArgs e) private void LogForm_Load(object sender, EventArgs e)
@@ -179,7 +209,7 @@ namespace Shadowsocks.View
InitContent(); InitContent();
timer = new Timer(); timer = new Timer();
timer.Interval = 300;
timer.Interval = 100;
timer.Tick += Timer_Tick; timer.Tick += Timer_Tick;
timer.Start(); timer.Start();
@@ -190,7 +220,8 @@ namespace Shadowsocks.View
Width = config.width; Width = config.width;
Top = config.GetBestTop(); Top = config.GetBestTop();
Left = config.GetBestLeft(); Left = config.GetBestLeft();
if(config.maximized) {
if (config.maximized)
{
WindowState = FormWindowState.Maximized; WindowState = FormWindowState.Maximized;
} }
@@ -218,7 +249,8 @@ namespace Shadowsocks.View
config.SetFont(LogMessageTextBox.Font); config.SetFont(LogMessageTextBox.Font);
config.SetBackgroundColor(LogMessageTextBox.BackColor); config.SetBackgroundColor(LogMessageTextBox.BackColor);
config.SetTextColor(LogMessageTextBox.ForeColor); config.SetTextColor(LogMessageTextBox.ForeColor);
if (WindowState != FormWindowState.Minimized && !(config.maximized = WindowState == FormWindowState.Maximized)) {
if (WindowState != FormWindowState.Minimized && !(config.maximized = WindowState == FormWindowState.Maximized))
{
config.top = Top; config.top = Top;
config.left = Left; config.left = Left;
config.height = Height; config.height = Height;


Loading…
Cancel
Save