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.
This commit is contained in:
@@ -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;
|
||||
current.inboundCounter = InboundCounter;
|
||||
current.outboundCounter = OutboundCounter;
|
||||
current.inboundIncreasement = current.inboundCounter - previous.inboundCounter;
|
||||
current.outboundIncreasement = current.outboundCounter - previous.outboundCounter;
|
||||
|
||||
traffic.Enqueue(current);
|
||||
if (traffic.Count > queueMaxSize)
|
||||
traffic.Dequeue();
|
||||
trafficPerSecondQueue.Enqueue(current);
|
||||
if (trafficPerSecondQueue.Count > queueMaxSize)
|
||||
trafficPerSecondQueue.Dequeue();
|
||||
|
||||
TrafficChanged?.Invoke(this, new EventArgs());
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user