Skip to content

Commit c0e0af1

Browse files
Network GC reduction (Issue #8)
1 parent 05b2af2 commit c0e0af1

14 files changed

+298
-117
lines changed

src/CommNetConstellation/CommNetConstellation.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
<Compile Include="UI\ColorPickerDialog.cs" />
8181
<Compile Include="UI\ConstellationControlDialog.cs" />
8282
<Compile Include="UI\ConstellationEditDialog.cs" />
83+
<Compile Include="UI\GameUtils.cs" />
8384
<Compile Include="UI\GroundStationEditDialog.cs" />
8485
<Compile Include="UI\UIUtils.cs" />
8586
<Compile Include="UI\VesselMgtTools\AntennaTool.cs" />

src/CommNetConstellation/CommNetLayer/CNCCommNetHome.cs

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ public class CNCCommNetHome : CommNetHome, IComparable<CNCCommNetHome>
2020
[Persistent] public string ID;
2121
[Persistent] public Color Color = Color.red;
2222
[Persistent] protected string OptionalName = "";
23-
[Persistent(collectionIndex = "Frequency")] public List<short> Frequencies = new List<short>(new short[] { CNCSettings.Instance.PublicRadioFrequency });
23+
[Persistent(collectionIndex = "Frequency")] protected List<short> Frequencies = new List<short>(new short[] { CNCSettings.Instance.PublicRadioFrequency });
24+
25+
//for low-gc operations
26+
protected short[] sorted_frequency_array;
2427

2528
public double altitude { get { return this.alt; } }
2629
public double latitude { get { return this.lat; } }
@@ -72,14 +75,54 @@ public void replaceFrequency(short oldFrequency, short newFrequency)
7275
this.Frequencies.Remove(oldFrequency);
7376
this.Frequencies.Add(newFrequency);
7477
this.Frequencies.Sort();
78+
regenerateFrequencyArray(this.Frequencies);
7579
}
7680

7781
/// <summary>
7882
/// Drop the specific frequency from the list
7983
/// </summary>
80-
public bool deleteFrequency(short frequency)
84+
public void deleteFrequency(short frequency)
85+
{
86+
this.Frequencies.Remove(frequency);
87+
regenerateFrequencyArray(this.Frequencies);
88+
}
89+
90+
/// <summary>
91+
/// Get the *sorted* array of frequencies only
92+
/// </summary>
93+
public short[] getFrequencyArray()
94+
{
95+
if(this.sorted_frequency_array == null)
96+
{
97+
regenerateFrequencyArray(this.Frequencies);
98+
}
99+
return this.sorted_frequency_array;
100+
}
101+
102+
/// <summary>
103+
/// Get the *sorted* list of frequencies only
104+
/// </summary>
105+
public List<short> getFrequencyList()
106+
{
107+
return this.Frequencies;
108+
}
109+
110+
/// <summary>
111+
/// Remove all frequencies
112+
/// </summary>
113+
public void deleteFrequencies()
81114
{
82-
return this.Frequencies.Remove(frequency);
115+
this.Frequencies.Clear();
116+
regenerateFrequencyArray(this.Frequencies);
117+
}
118+
119+
/// <summary>
120+
/// Replace all frequencies
121+
/// </summary>
122+
public void replaceFrequencies(List<short> newFreqs)
123+
{
124+
this.Frequencies = newFreqs;
125+
regenerateFrequencyArray(this.Frequencies);
83126
}
84127

85128
/// <summary>
@@ -186,5 +229,24 @@ public int CompareTo(CNCCommNetHome other)
186229
{
187230
return this.stationName.CompareTo(other.stationName);
188231
}
232+
233+
/// <summary>
234+
/// Regenerate frequency array used for low-gc operations
235+
/// </summary>
236+
protected void regenerateFrequencyArray(List<short> list)
237+
{
238+
if (list.Count == 0)
239+
{
240+
sorted_frequency_array = new short[] { };
241+
}
242+
243+
sorted_frequency_array = new short[list.Count];
244+
for(int i=0; i< list.Count; i++)
245+
{
246+
sorted_frequency_array[i] = list[i];
247+
}
248+
249+
GameUtils.Quicksort(sorted_frequency_array, 0, sorted_frequency_array.Length - 1);
250+
}
189251
}
190252
}

src/CommNetConstellation/CommNetLayer/CNCCommNetScenario.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CommNet;
2+
using CommNetConstellation.UI;
23
using KSP.UI.Screens.Flight;
34
using System;
45
using System.Collections.Generic;
@@ -103,7 +104,7 @@ protected override void Start()
103104
UnityEngine.Object.Destroy(bodies[i]);
104105
}
105106

106-
CNCLog.Verbose("CommNet Scenario loading done! ");
107+
CNCLog.Verbose("CommNet Scenario loading done!");
107108
}
108109

109110
public override void OnAwake()
@@ -208,7 +209,7 @@ public override void OnLoad(ConfigNode gameNode)
208209
ConfigNode.LoadObjectFromConfig(dummyGroundStation, stationNodes[i]);
209210
if(!stationNodes[i].HasNode("Frequencies")) // empty list is not saved as empty node in persistent.sfs
210211
{
211-
dummyGroundStation.Frequencies.Clear();// clear the default frequency list
212+
dummyGroundStation.deleteFrequencies();// clear the default frequency list
212213
}
213214
persistentGroundStations.Add(dummyGroundStation);
214215
}
@@ -288,7 +289,7 @@ public List<CNCCommNetVessel> getCommNetVessels(short targetFrequency = -1)
288289
List<CNCCommNetVessel> newList = new List<CNCCommNetVessel>();
289290
for(int i=0; i<commVessels.Count; i++)
290291
{
291-
if (commVessels[i].getFrequencies().Contains(targetFrequency) || targetFrequency == -1)
292+
if (targetFrequency == -1 || GameUtils.firstCommonElement(commVessels[i].getFrequencyArray(), new short[] { targetFrequency }) >= 0)
292293
newList.Add(commVessels[i]);
293294
}
294295

@@ -359,20 +360,16 @@ private void onVesselCountChanged(Vessel v)
359360
/// <summary>
360361
/// Convenient method to obtain a frequency list from a given CommNode
361362
/// </summary>
362-
public List<short> getFrequencies(CommNode a)
363+
public short[] getFrequencies(CommNode a)
363364
{
364-
List<short> aFreqs = new List<short>();
365-
366365
if (a.isHome && findCorrespondingGroundStation(a) != null)
367366
{
368-
aFreqs.AddRange(findCorrespondingGroundStation(a).Frequencies);
367+
return findCorrespondingGroundStation(a).getFrequencyArray();
369368
}
370369
else
371370
{
372-
aFreqs = ((CNCCommNetVessel)findCorrespondingVessel(a).Connection).getFrequencies();
371+
return ((CNCCommNetVessel)findCorrespondingVessel(a).Connection).getFrequencyArray();
373372
}
374-
375-
return aFreqs;
376373
}
377374

378375
/// <summary>

src/CommNetConstellation/CommNetLayer/CNCCommNetUI.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using CommNet;
2+
using CommNetConstellation.UI;
23
using KSP.Localization;
34
using KSP.UI.Screens.Mapview;
45
using System;
@@ -130,12 +131,12 @@ private void OnMapNodeUpdateVisible(MapNode node, MapNode.IconData iconData)
130131
private Color getConstellationColor(CommNode a, CommNode b)
131132
{
132133
//Assume the connection between A and B passes the check test
133-
List<short> commonFreqs = Constellation.NonLinqIntersect(CNCCommNetScenario.Instance.getFrequencies(a), CNCCommNetScenario.Instance.getFrequencies(b));
134+
short[] commonFreqs = GameUtils.NonLinqIntersect(CNCCommNetScenario.Instance.getFrequencies(a), CNCCommNetScenario.Instance.getFrequencies(b));
134135
IRangeModel rangeModel = CNCCommNetScenario.RangeModel;
135136
short strongestFreq = -1;
136137
double longestRange = 0.0;
137138

138-
for (int i = 0; i < commonFreqs.Count; i++)
139+
for (int i = 0; i < commonFreqs.Length; i++)
139140
{
140141
short thisFreq = commonFreqs[i];
141142
double thisRange = rangeModel.GetMaximumRange(CNCCommNetScenario.Instance.getCommPower(a, thisFreq), CNCCommNetScenario.Instance.getCommPower(b, thisFreq));

src/CommNetConstellation/CommNetLayer/CNCCommNetVessel.cs

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ public enum FrequencyListOperation
8282
[Persistent] private List<double> FreqDictionaryValues = new List<double>();
8383
[Persistent] public FrequencyListOperation FreqListOperation = FrequencyListOperation.AutoBuild; // initial value
8484

85+
//for low-gc operations
86+
protected short[] sorted_frequency_array;
87+
8588
protected short strongestFreq = -1;
8689
protected List<CNCAntennaPartInfo> vesselAntennas = new List<CNCAntennaPartInfo>();
8790
protected bool stageActivated = false;
@@ -392,19 +395,33 @@ protected Dictionary<short, double> buildFrequencyList(List<CNCAntennaPartInfo>
392395
short freq = allFreqs[i];
393396

394397
//best antenna power * (total power / best power) ^ (sum(expo*power)/total power)
395-
double weightedExpo = Constellation.NonLinqSum(expoFreqDict[freq]) / Constellation.NonLinqSum(combinepowerFreqDict[freq]);
396-
double combinedPower = (combinepowerFreqDict[freq].Count == 0)? 0.0 : Constellation.NonLinqMax(combinepowerFreqDict[freq]) * Math.Pow((Constellation.NonLinqSum(combinepowerFreqDict[freq]) / Constellation.NonLinqMax(combinepowerFreqDict[freq])), weightedExpo);
398+
double weightedExpo = GameUtils.NonLinqSum(expoFreqDict[freq]) / GameUtils.NonLinqSum(combinepowerFreqDict[freq]);
399+
double combinedPower = (combinepowerFreqDict[freq].Count == 0)? 0.0 : GameUtils.NonLinqMax(combinepowerFreqDict[freq]) * Math.Pow((GameUtils.NonLinqSum(combinepowerFreqDict[freq]) / GameUtils.NonLinqMax(combinepowerFreqDict[freq])), weightedExpo);
397400
freqDict.Add(freq, Math.Max(combinedPower, noncombinepowerDict[freq]));
398401
CNCLog.Debug("CommNet Vessel '{0}''s freq list has freq {1} of {2} power", this.Vessel.GetName(), freq, Math.Max(combinedPower, noncombinepowerDict[freq]));
399402
}
400403

404+
regenerateFrequencyArray(freqDict);
405+
401406
return freqDict;
402407
}
403408

409+
/// <summary>
410+
/// Get the *sorted* array of frequencies only
411+
/// </summary>
412+
public short[] getFrequencyArray()
413+
{
414+
if(sorted_frequency_array == null)
415+
{
416+
regenerateFrequencyArray(this.FrequencyDict);
417+
}
418+
return sorted_frequency_array;
419+
}
420+
404421
/// <summary>
405422
/// Get the *unsorted* list of frequencies only
406423
/// </summary>
407-
public List<short> getFrequencies()
424+
public List<short> getFrequencyList()
408425
{
409426
List<short> freqs = new List<short>();
410427
var itr = this.FrequencyDict.Keys.GetEnumerator();
@@ -557,6 +574,8 @@ public void addToFreqList(short frequency, double commPower)
557574
else
558575
this.FrequencyDict.Add(frequency, commPower);
559576

577+
regenerateFrequencyArray(this.FrequencyDict);
578+
560579
CNCLog.Debug("CommNet Vessel '{0}''s freq list gains {1} ({2} power)", this.Vessel.GetName(), frequency, commPower);
561580
}
562581

@@ -568,6 +587,8 @@ public void removeFromFreqList(short frequency)
568587
if (!isFreqListEditable()) return;
569588

570589
this.FrequencyDict.Remove(frequency);
590+
regenerateFrequencyArray(this.FrequencyDict);
591+
571592
CNCLog.Debug("CommNet Vessel '{0}''s freq list loses freq {1}", this.Vessel.GetName(), frequency);
572593
}
573594

@@ -579,6 +600,8 @@ public void clearFreqList()
579600
if (!isFreqListEditable()) return;
580601

581602
this.FrequencyDict.Clear();
603+
regenerateFrequencyArray(this.FrequencyDict);
604+
582605
CNCLog.Debug("CommNet Vessel '{0}''s freq list is cleared", this.Vessel.GetName());
583606
}
584607

@@ -775,6 +798,29 @@ public void PersistenceLoad()
775798
{
776799
FrequencyDict.Add(FreqDictionaryKeys[i], FreqDictionaryValues[i]);
777800
}
801+
regenerateFrequencyArray(FrequencyDict);
802+
}
803+
804+
/// <summary>
805+
/// Regenerate frequency array used for low-gc operations
806+
/// </summary>
807+
protected void regenerateFrequencyArray(Dictionary<short, double> dict)
808+
{
809+
if (dict.Keys.Count == 0)
810+
{
811+
sorted_frequency_array = new short[] { };
812+
}
813+
814+
int i = 0;
815+
sorted_frequency_array = new short[dict.Keys.Count];
816+
817+
var valueItr = dict.Keys.GetEnumerator();
818+
while (valueItr.MoveNext())
819+
{
820+
sorted_frequency_array[i++] = valueItr.Current;
821+
}
822+
823+
GameUtils.Quicksort(sorted_frequency_array, 0, sorted_frequency_array.Length - 1);
778824
}
779825
}
780826
}

src/CommNetConstellation/CommNetLayer/CNCCommNetwork.cs

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using CommNet;
2+
using CommNetConstellation.UI;
23
using System;
3-
using System.Collections.Generic;
44

55
namespace CommNetConstellation.CommNetLayer
66
{
@@ -31,39 +31,33 @@ public static bool AreSame(CommNode a, CommNode b)
3131
/// </summary>
3232
protected override bool SetNodeConnection(CommNode a, CommNode b)
3333
{
34-
List<short> aFreqs, bFreqs;
35-
3634
try
3735
{
3836
//stop links between ground stations
3937
if (a.isHome && b.isHome)
4038
{
4139
this.Disconnect(a, b, true);
42-
return false;
4340
}
44-
45-
//each CommNode has at least some frequencies?
46-
aFreqs = CNCCommNetScenario.Instance.getFrequencies(a);
47-
bFreqs = CNCCommNetScenario.Instance.getFrequencies(b);
48-
49-
//share same frequency?
50-
for (int i = 0; i < aFreqs.Count; i++)
41+
else
5142
{
52-
if (bFreqs.Contains(aFreqs[i])) // yes, it does
43+
//each CommNode has at least some frequencies?
44+
if (GameUtils.firstCommonElement(CNCCommNetScenario.Instance.getFrequencies(a), CNCCommNetScenario.Instance.getFrequencies(b)) >= 0)
5345
{
5446
return base.SetNodeConnection(a, b);
5547
}
48+
else
49+
{
50+
this.Disconnect(a, b, true);
51+
}
5652
}
57-
58-
this.Disconnect(a, b, true);
59-
return false;
6053
}
6154
catch (Exception e) // either CommNode could be a kerbal on EVA
6255
{
6356
//CNCLog.Verbose("Error thrown when checking CommNodes '{0}' & '{1}' - {2}", a.name, b.name, e.Message);
6457
this.Disconnect(a, b, true);
65-
return false;
6658
}
59+
60+
return false;
6761
}
6862
}
6963
}

0 commit comments

Comments
 (0)