diff --git a/shadowsocks-csharp/Controller/ShadowsocksController.cs b/shadowsocks-csharp/Controller/ShadowsocksController.cs index 3f37cbf6..726e11be 100644 --- a/shadowsocks-csharp/Controller/ShadowsocksController.cs +++ b/shadowsocks-csharp/Controller/ShadowsocksController.cs @@ -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 traffic; + public Queue trafficPerSecondQueue; private bool stopped = false; @@ -50,16 +51,6 @@ namespace Shadowsocks.Controller public string Path; } - public class QueueLast : Queue - { - 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(); + trafficPerSecondQueue = new Queue(); 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()); diff --git a/shadowsocks-csharp/Util/Util.cs b/shadowsocks-csharp/Util/Util.cs index e428568d..ceda5c11 100755 --- a/shadowsocks-csharp/Util/Util.cs +++ b/shadowsocks-csharp/Util/Util.cs @@ -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) diff --git a/shadowsocks-csharp/View/LogForm.cs b/shadowsocks-csharp/View/LogForm.cs index 27864526..4c6d98ed 100644 --- a/shadowsocks-csharp/View/LogForm.cs +++ b/shadowsocks-csharp/View/LogForm.cs @@ -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 traffic = new ShadowsocksController.QueueLast(); + #region Traffic Chart + Queue trafficInfoQueue = new Queue(); + const int queueMaxLength = 60; + long lastInbound, lastOutbound; + long maxSpeed = 0, lastMaxSpeed = 0; + const long minScale = 50; + BandwidthScaleInfo bandwidthScale; + List inboundPoints = new List(); + List outboundPoints = new List(); + 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 inboundPoints = new List(); - List outboundPoints = new List(); - 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, .ForEach does not work + // re-scale the original data points, since it is List, .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(); - 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; + } + } } } diff --git a/shadowsocks-csharp/View/MenuViewController.cs b/shadowsocks-csharp/View/MenuViewController.cs index 18f11bd5..13e253ee 100644 --- a/shadowsocks-csharp/View/MenuViewController.cs +++ b/shadowsocks-csharp/View/MenuViewController.cs @@ -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;