Browse Source

Chart Refactor (#1019)

* Rename variable 'traffic' to 'trafficPerSecondQueue' and 'trafficInfoQueue'

* Remove class QueueLast<T> by using linq Queue.Last()

* Slight changes, such as rename, move several variables from function domain to class domain to improve performance.
Logic remains the same.

* Update the logic of copying queue from Controller to View.

* Move the TrafficInfo declaration into LogForm class

Overwise, the VS UI designer does not work.
tags/4.0
Allen Zhu Syrone Wong 8 years ago
parent
commit
84b69d3dff
4 changed files with 85 additions and 70 deletions
  1. +15
    -23
      shadowsocks-csharp/Controller/ShadowsocksController.cs
  2. +4
    -4
      shadowsocks-csharp/Util/Util.cs
  3. +63
    -41
      shadowsocks-csharp/View/LogForm.cs
  4. +3
    -2
      shadowsocks-csharp/View/MenuViewController.cs

+ 15
- 23
shadowsocks-csharp/Controller/ShadowsocksController.cs View File

@@ -13,6 +13,7 @@ using Shadowsocks.Controller.Strategy;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System.Linq;
namespace Shadowsocks.Controller
{
@@ -39,7 +40,7 @@ namespace Shadowsocks.Controller
private long _outboundCounter = 0;
public long InboundCounter => Interlocked.Read(ref _inboundCounter);
public long OutboundCounter => Interlocked.Read(ref _outboundCounter);
public QueueLast<TrafficPerSecond> traffic;
public Queue<TrafficPerSecond> trafficPerSecondQueue;
private bool stopped = false;
@@ -50,16 +51,6 @@ namespace Shadowsocks.Controller
public string Path;
}
public class QueueLast<T> : Queue<T>
{
public T Last { get; private set; }
public new void Enqueue(T item)
{
Last = item;
base.Enqueue(item);
}
}
public class TrafficPerSecond
{
public long inboundCounter;
@@ -620,10 +611,10 @@ namespace Shadowsocks.Controller
private void StartTrafficStatistics(int queueMaxSize)
{
traffic = new QueueLast<TrafficPerSecond>();
trafficPerSecondQueue = new Queue<TrafficPerSecond>();
for (int i = 0; i < queueMaxSize; i++)
{
traffic.Enqueue(new TrafficPerSecond());
trafficPerSecondQueue.Enqueue(new TrafficPerSecond());
}
_trafficThread = new Thread(new ThreadStart(() => TrafficStatistics(queueMaxSize)));
_trafficThread.IsBackground = true;
@@ -632,19 +623,20 @@ namespace Shadowsocks.Controller
private void TrafficStatistics(int queueMaxSize)
{
TrafficPerSecond previous, current;
while (true)
{
TrafficPerSecond previous = traffic.Last;
TrafficPerSecond current = new TrafficPerSecond();
previous = trafficPerSecondQueue.Last();
current = new TrafficPerSecond();
var inbound = current.inboundCounter = InboundCounter;
var outbound = current.outboundCounter = OutboundCounter;
current.inboundIncreasement = inbound - previous.inboundCounter;
current.outboundIncreasement = outbound - previous.outboundCounter;
traffic.Enqueue(current);
if (traffic.Count > queueMaxSize)
traffic.Dequeue();
current.inboundCounter = InboundCounter;
current.outboundCounter = OutboundCounter;
current.inboundIncreasement = current.inboundCounter - previous.inboundCounter;
current.outboundIncreasement = current.outboundCounter - previous.outboundCounter;
trafficPerSecondQueue.Enqueue(current);
if (trafficPerSecondQueue.Count > queueMaxSize)
trafficPerSecondQueue.Dequeue();
TrafficChanged?.Invoke(this, new EventArgs());


+ 4
- 4
shadowsocks-csharp/Util/Util.cs View File

@@ -12,13 +12,13 @@ namespace Shadowsocks.Util
public struct BandwidthScaleInfo
{
public float value;
public string unit_name;
public string unitName;
public long unit;
public BandwidthScaleInfo(float value, string unit_name, long unit)
public BandwidthScaleInfo(float value, string unitName, long unit)
{
this.value = value;
this.unit_name = unit_name;
this.unitName = unitName;
this.unit = unit;
}
}
@@ -111,7 +111,7 @@ namespace Shadowsocks.Util
public static string FormatBandwidth(long n)
{
var result = GetBandwidthScale(n);
return $"{result.value:0.##}{result.unit_name}";
return $"{result.value:0.##}{result.unitName}";
}
public static string FormatBytes(long bytes)


+ 63
- 41
shadowsocks-csharp/View/LogForm.cs View File

@@ -14,18 +14,6 @@ using System.Text;
namespace Shadowsocks.View
{
struct TrafficInfo
{
public long inbound;
public long outbound;
public TrafficInfo(long inbound, long outbound)
{
this.inbound = inbound;
this.outbound = outbound;
}
}
public partial class LogForm : Form
{
long lastOffset;
@@ -37,9 +25,17 @@ namespace Shadowsocks.View
// global traffic update lock, make it static
private static readonly object _lock = new object();
#region chart
long lastMaxSpeed;
ShadowsocksController.QueueLast<TrafficInfo> traffic = new ShadowsocksController.QueueLast<TrafficInfo>();
#region Traffic Chart
Queue<TrafficInfo> trafficInfoQueue = new Queue<TrafficInfo>();
const int queueMaxLength = 60;
long lastInbound, lastOutbound;
long maxSpeed = 0, lastMaxSpeed = 0;
const long minScale = 50;
BandwidthScaleInfo bandwidthScale;
List<float> inboundPoints = new List<float>();
List<float> outboundPoints = new List<float>();
TextAnnotation inboundAnnotation = new TextAnnotation();
TextAnnotation outboundAnnotation = new TextAnnotation();
#endregion
public LogForm(ShadowsocksController controller, string filename)
@@ -63,29 +59,24 @@ namespace Shadowsocks.View
UpdateTexts();
}
private void update_TrafficChart()
private void UpdateTrafficChart()
{
List<float> inboundPoints = new List<float>();
List<float> outboundPoints = new List<float>();
TextAnnotation inboundAnnotation = new TextAnnotation();
TextAnnotation outboundAnnotation = new TextAnnotation();
BandwidthScaleInfo bandwidthScale;
const long minScale = 50;
long maxSpeed = 0;
long lastInbound, lastOutbound;
lock (_lock)
{
if (traffic.Count == 0)
if (trafficInfoQueue.Count == 0)
return;
foreach (var trafficPerSecond in traffic)
inboundPoints.Clear();
outboundPoints.Clear();
maxSpeed = 0;
foreach (var trafficInfo in trafficInfoQueue)
{
inboundPoints.Add(trafficPerSecond.inbound);
outboundPoints.Add(trafficPerSecond.outbound);
maxSpeed = Math.Max(maxSpeed, Math.Max(trafficPerSecond.inbound, trafficPerSecond.outbound));
inboundPoints.Add(trafficInfo.inbound);
outboundPoints.Add(trafficInfo.outbound);
maxSpeed = Math.Max(maxSpeed, Math.Max(trafficInfo.inbound, trafficInfo.outbound));
}
lastInbound = traffic.Last().inbound;
lastOutbound = traffic.Last().outbound;
lastInbound = trafficInfoQueue.Last().inbound;
lastOutbound = trafficInfoQueue.Last().outbound;
}
if (maxSpeed > 0)
@@ -101,7 +92,7 @@ namespace Shadowsocks.View
bandwidthScale = Utils.GetBandwidthScale(maxSpeed);
//rescale the original data points, since it is List<float>, .ForEach does not work
// re-scale the original data points, since it is List<float>, .ForEach does not work
inboundPoints = inboundPoints.Select(p => p / bandwidthScale.unit).ToList();
outboundPoints = outboundPoints.Select(p => p / bandwidthScale.unit).ToList();
@@ -109,7 +100,7 @@ namespace Shadowsocks.View
{
trafficChart.Series["Inbound"].Points.DataBindY(inboundPoints);
trafficChart.Series["Outbound"].Points.DataBindY(outboundPoints);
trafficChart.ChartAreas[0].AxisY.LabelStyle.Format = "{0:0.##} " + bandwidthScale.unit_name;
trafficChart.ChartAreas[0].AxisY.LabelStyle.Format = "{0:0.##} " + bandwidthScale.unitName;
trafficChart.ChartAreas[0].AxisY.Maximum = bandwidthScale.value;
inboundAnnotation.AnchorDataPoint = trafficChart.Series["Inbound"].Points.Last();
inboundAnnotation.Text = Utils.FormatBandwidth(lastInbound);
@@ -125,10 +116,29 @@ namespace Shadowsocks.View
{
lock (_lock)
{
traffic = new ShadowsocksController.QueueLast<TrafficInfo>();
foreach (var trafficPerSecond in controller.traffic)
if (trafficInfoQueue.Count == 0)
{
traffic.Enqueue(new TrafficInfo(trafficPerSecond.inboundIncreasement, trafficPerSecond.outboundIncreasement));
// Init an empty queue
for (int i = 0; i < queueMaxLength; i++)
{
trafficInfoQueue.Enqueue(new TrafficInfo(0, 0));
}
foreach (var trafficPerSecond in controller.trafficPerSecondQueue)
{
trafficInfoQueue.Enqueue(new TrafficInfo(trafficPerSecond.inboundIncreasement,
trafficPerSecond.outboundIncreasement));
if (trafficInfoQueue.Count > queueMaxLength)
trafficInfoQueue.Dequeue();
}
}
else
{
var lastTraffic = controller.trafficPerSecondQueue.Last();
trafficInfoQueue.Enqueue(new TrafficInfo(lastTraffic.inboundIncreasement,
lastTraffic.outboundIncreasement));
if (trafficInfoQueue.Count > queueMaxLength)
trafficInfoQueue.Dequeue();
}
}
}
@@ -157,7 +167,7 @@ namespace Shadowsocks.View
private void Timer_Tick(object sender, EventArgs e)
{
UpdateContent();
update_TrafficChart();
UpdateTrafficChart();
}
private void InitContent()
@@ -258,9 +268,9 @@ namespace Shadowsocks.View
config.topMost = topMostTrigger;
config.wrapText = wrapTextTrigger;
config.toolbarShown = toolbarTrigger;
config.Font=LogMessageTextBox.Font;
config.BackgroundColor=LogMessageTextBox.BackColor;
config.TextColor=LogMessageTextBox.ForeColor;
config.Font = LogMessageTextBox.Font;
config.BackgroundColor = LogMessageTextBox.BackColor;
config.TextColor = LogMessageTextBox.ForeColor;
if (WindowState != FormWindowState.Minimized && !(config.Maximized = WindowState == FormWindowState.Maximized))
{
config.Top = Top;
@@ -410,5 +420,17 @@ namespace Shadowsocks.View
ToolbarFlowLayoutPanel.Visible = toolbarTrigger;
ShowToolbarMenuItem.Checked = toolbarTrigger;
}
private class TrafficInfo
{
public long inbound;
public long outbound;
public TrafficInfo(long inbound, long outbound)
{
this.inbound = inbound;
this.outbound = outbound;
}
}
}
}

+ 3
- 2
shadowsocks-csharp/View/MenuViewController.cs View File

@@ -13,6 +13,7 @@ using Shadowsocks.Controller;
using Shadowsocks.Model;
using Shadowsocks.Properties;
using Shadowsocks.Util;
using System.Linq;
namespace Shadowsocks.View
{
@@ -112,8 +113,8 @@ namespace Shadowsocks.View
Icon newIcon;
bool hasInbound = controller.traffic.Last.inboundIncreasement > 0;
bool hasOutbound = controller.traffic.Last.outboundIncreasement > 0;
bool hasInbound = controller.trafficPerSecondQueue.Last().inboundIncreasement > 0;
bool hasOutbound = controller.trafficPerSecondQueue.Last().outboundIncreasement > 0;
if (hasInbound && hasOutbound)
newIcon = icon_both;


Loading…
Cancel
Save