Probably fixed the flickering lines by only checking one relay per inactive vessel, and by setting BestVesselRelay per vessel in RelayDatabase.
Probably fixed the flickering lines by only checking one relay per inactive vessel, and by setting BestVesselRelay per vessel in RelayDatabase.

--- a/ARFlightController.cs
+++ b/ARFlightController.cs
@@ -241,6 +241,35 @@
 				FlightGlobals.ActiveVessel != null
 			)
 			{
+				Vessel vessel;
+				IAntennaRelay relay;
+				IList<IAntennaRelay> activeVesselRelays;
+
+				for (int vIdx = 0; vIdx < FlightGlobals.Vessels.Count; vIdx++)
+				{
+					vessel = FlightGlobals.Vessels[vIdx];
+
+					if (vessel == FlightGlobals.ActiveVessel)
+					{
+						continue;
+					}
+
+					relay = vessel.GetBestRelay();
+
+					if (relay != null)
+					{
+						relay.FindNearestRelay();
+					}
+				}
+
+				activeVesselRelays = RelayDatabase.Instance[FlightGlobals.ActiveVessel];
+				for (int rIdx = 0; rIdx < activeVesselRelays.Count; rIdx++)
+				{
+					relay = activeVesselRelays[rIdx];
+
+					relay.FindNearestRelay();
+				}
+
 				log.Append("Checking vessel relay status.\n");
 
 				this.currentConnectionStatus = FlightGlobals.ActiveVessel.GetConnectionStatus();

--- a/ARMapRenderer.cs
+++ b/ARMapRenderer.cs
@@ -40,11 +40,16 @@
 	{
 		#region Fields
 		private Dictionary<Guid, LineRenderer> vesselLineRenderers;
-		private Dictionary<Guid, bool> vesselFrameCache;
+
+		// Debug Stuff
+		#pragma warning disable 649
+		private System.Diagnostics.Stopwatch timer;
+		private Tools.DebugLogger log;
+		private long relayStart;
+		private long start;
+		#pragma warning restore 649
 
 		#pragma warning disable 414
-		private bool dumpBool;
-		private Color lastColor;
 		private Color thisColor;
 		#pragma warning restore 414
 		#endregion
@@ -90,8 +95,12 @@
 			if (ARConfiguration.PrettyLines)
 			{
 				this.vesselLineRenderers = new Dictionary<Guid, LineRenderer>();
-				this.vesselFrameCache = new Dictionary<Guid, bool>();
-			}
+			}
+
+			#if DEBUG
+			this.timer = new System.Diagnostics.Stopwatch();
+			this.log = Tools.DebugLogger.New(this);
+			#endif
 		}
 
 		private void OnPreCull()
@@ -103,10 +112,14 @@
 				return;
 			}
 
-			Tools.DebugLogger log = Tools.DebugLogger.New(this);
+			#if DEBUG
+			timer.Restart();
+			#endif
 
 			try
 			{
+				log.Clear();
+
 				log.AppendFormat("OnPreCull.\n");
 
 				log.AppendFormat("\tMapView: Draw3DLines: {0}\n" +
@@ -117,10 +130,6 @@
 					MapView.MapCamera.Distance
 				);
 
-				this.vesselFrameCache.Clear();
-
-				log.AppendLine("vesselFrameCache cleared.");
-
 				if (FlightGlobals.ready && FlightGlobals.Vessels != null)
 				{
 					log.AppendLine("FlightGlobals ready and Vessels list not null.");
@@ -129,19 +138,13 @@
 					{
 						Vessel vessel = FlightGlobals.Vessels[i];
 
+						log.AppendFormat("\nStarting check for vessel {0} at {1}ms", vessel, timer.ElapsedMilliseconds);
+
 						if (vessel == null)
 						{
-							log.AppendFormat("Skipping vessel {0} altogether because it is null.\n");
+							log.AppendFormat("\n\tSkipping vessel {0} altogether because it is null.", vessel);
 							continue;
 						}
-
-						if (this.vesselFrameCache.TryGetValue(vessel.id, out dumpBool))
-						{
-							log.AppendFormat("Skipping vessel {0} because it's already been processed this frame.");
-							continue;
-						}
-
-						log.AppendFormat("Checking vessel {0}.\n", vessel.vesselName);
 
 						switch (vessel.vesselType)
 						{
@@ -149,27 +152,47 @@
 							case VesselType.EVA:
 							case VesselType.Unknown:
 							case VesselType.SpaceObject:
-								log.AppendFormat("\tDiscarded because vessel is of invalid type {0}\n",
+								log.AppendFormat("\n\tDiscarded because vessel is of invalid type {0}",
 									vessel.vesselType);
 								continue;
 						}
 
+						log.AppendFormat("\n\tChecking vessel {0}.", vessel.vesselName);
+
+						start = timer.ElapsedMilliseconds;
+
 						IAntennaRelay vesselRelay = vessel.GetBestRelay();
+
+						if (vesselRelay == null)
+						{
+							continue;
+						}
+
+						log.AppendFormat("\n\tGot best relay {0} ({3}) for vessel {1} in {2} ms",
+							vesselRelay, vessel, timer.ElapsedMilliseconds - start, vesselRelay.GetType().Name);
 
 						if (vesselRelay != null)
 						{
+							start = timer.ElapsedMilliseconds;
+
 							this.SetRelayVertices(vesselRelay);
+
+							log.AppendFormat("\n\tSet relay vertices for {0} in {1}ms",
+								vessel, timer.ElapsedMilliseconds - start);
 						}
 					}
 				}
 			}
-			catch (Exception)
-			{
+			catch (Exception ex)
+			{
+				this.LogError("Caught {0}: {1}\n{2}\n", ex.GetType().Name, ex.ToString(), ex.StackTrace.ToString());
 				this.Cleanup();
 			}
 			#if DEBUG
 			finally
 			{
+				log.AppendFormat("\n\tOnPreCull finished in {0}ms\n", timer.ElapsedMilliseconds);
+
 				log.Print();
 			}
 			#endif
@@ -186,7 +209,13 @@
 		#region Utility
 		private void SetRelayVertices(IAntennaRelay relay)
 		{
-			lastColor = default(Color);
+			log.AppendFormat("\n\t\tDrawing line for relay chain starting at {0}.", relay);
+
+			if (relay.vessel == null)
+			{
+				log.Append("\n\t\tvessel is null, bailing out");
+				return;
+			}
 
 			LineRenderer renderer = this[relay.vessel.id];
 			Vector3d start = ScaledSpace.LocalToScaledSpace(relay.vessel.GetWorldPos3D());
@@ -213,62 +242,59 @@
 
 			int idx = 0;
 
-			while (relay != null)
-			{
-				Vector3d nextPoint;
-
-				renderer.enabled = true;
-
-				if (!relay.CanTransmit())
-				{
-					thisColor = Color.red;
+			relayStart = timer.ElapsedMilliseconds;
+
+			Vector3d nextPoint;
+
+			renderer.enabled = true;
+
+			if (!relay.CanTransmit())
+			{
+				thisColor = Color.red;
+			}
+			else
+			{
+				if (relay.transmitDistance < relay.nominalTransmitDistance)
+				{
+					thisColor = Color.green;
 				}
 				else
 				{
-					if (relay.transmitDistance < relay.nominalTransmitDistance)
-					{
-						thisColor = Color.green;
-					}
-					else
-					{
-						thisColor = Color.yellow;
-					}
-				}
-
-				if (lastColor != default(Color) && thisColor != lastColor)
-				{
-					break;
-				}
-
-				lastColor = thisColor;
-				renderer.SetColors(thisColor, thisColor);
-
-				this.vesselFrameCache[relay.vessel.id] = true;
-
-				if (relay.KerbinDirect)
-				{
-					nextPoint = ScaledSpace.LocalToScaledSpace(AntennaRelay.Kerbin.position);
-					relay = null;
-				}
-				else
-				{
-					if (relay.targetRelay == null)
-					{
-						return;
-					}
-
-					nextPoint = ScaledSpace.LocalToScaledSpace(relay.targetRelay.vessel.GetWorldPos3D());
-					relay = relay.targetRelay;
-				}
-
-				if (!MapView.Draw3DLines)
-				{
-					nextPoint = MapView.MapCamera.camera.WorldToScreenPoint(nextPoint);
-					nextPoint.z = nextPoint.z >= 0f ? d : -d;
-				}
-
-				renderer.SetPosition(++idx, nextPoint);
-			}
+					thisColor = Color.yellow;
+				}
+			}
+
+			if (relay.KerbinDirect)
+			{
+				nextPoint = ScaledSpace.LocalToScaledSpace(AntennaRelay.Kerbin.position);
+				relay = null;
+			}
+			else
+			{
+				if (relay.targetRelay == null)
+				{
+					renderer.enabled = false;
+					return;
+				}
+
+				nextPoint = ScaledSpace.LocalToScaledSpace(relay.targetRelay.vessel.GetWorldPos3D());
+				relay = relay.targetRelay;
+			}
+
+			renderer.SetColors(thisColor, thisColor);
+
+			if (!MapView.Draw3DLines)
+			{
+				nextPoint = MapView.MapCamera.camera.WorldToScreenPoint(nextPoint);
+				nextPoint.z = nextPoint.z >= 0f ? d : -d;
+			}
+
+			idx++;
+
+			renderer.SetVertexCount(idx + 1);
+			renderer.SetPosition(idx, nextPoint);
+
+			log.AppendFormat("\n\t\t\t...finished segment in {0} ms", timer.ElapsedMilliseconds - relayStart);
 		}
 
 		private void Cleanup()
@@ -286,11 +312,6 @@
 				}
 				this.vesselLineRenderers.Clear();
 			}
-
-			if (this.vesselFrameCache != null && this.vesselFrameCache.Count > 0)
-			{
-				this.vesselFrameCache.Clear();
-			}
 		}
 		#endregion
 	}

--- a/AntennaRange.csproj
+++ b/AntennaRange.csproj
@@ -80,6 +80,7 @@
     <Compile Include="ARConfiguration.cs" />
     <Compile Include="ARFlightController.cs" />
     <Compile Include="ARMapRenderer.cs" />
+    <Compile Include="VesselCache.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>

--- a/AntennaRelay.cs
+++ b/AntennaRelay.cs
@@ -37,8 +37,8 @@
 	/// </summary>
 	public class AntennaRelay
 	{
-		private static readonly System.Diagnostics.Stopwatch searchTimer = new System.Diagnostics.Stopwatch();
-		private const long millisecondsBetweenSearches = 125L;
+		public static readonly System.Diagnostics.Stopwatch searchTimer = new System.Diagnostics.Stopwatch();
+		public const long millisecondsBetweenSearches = 125L;
 
 		// We don't have a Bard, so we'll hide Kerbin here.
 		private static CelestialBody _Kerbin;
@@ -62,6 +62,7 @@
 		private long lastSearch;
 
 		private bool canTransmit;
+		private bool isChecked;
 
 		private IAntennaRelay nearestRelay;
 		private IAntennaRelay bestOccludedRelay;
@@ -110,8 +111,6 @@
 		{
 			get
 			{
-				this.FindNearestRelay();
-
 				if (this.KerbinDirect || this.targetRelay == null)
 				{
 					return this.DistanceTo(Kerbin);
@@ -158,7 +157,6 @@
 		/// <returns><c>true</c> if this instance can transmit; otherwise, <c>false</c>.</returns>
 		public virtual bool CanTransmit()
 		{
-			this.FindNearestRelay();
 			return this.canTransmit;
 		}
 
@@ -166,27 +164,16 @@
 		/// Finds the nearest relay.
 		/// </summary>
 		/// <returns>The nearest relay or null, if no relays in range.</returns>
-		private void FindNearestRelay()
-		{
+		public void FindNearestRelay()
+		{
+			if (!FlightGlobals.ready)
+			{
+				return;
+			}
+
 			if (!searchTimer.IsRunning)
 			{
 				searchTimer.Start();
-			}
-
-			long searchTime = searchTimer.ElapsedMilliseconds;
-			long timeSinceLast = searchTime - this.lastSearch;
-
-			if (timeSinceLast < Math.Max(millisecondsBetweenSearches, UnityEngine.Time.smoothDeltaTime))
-			{
-				return;
-			}
-
-			this.lastSearch = searchTime;
-
-			// Skip vessels that have already been checked for a nearest relay this pass.
-			if (RelayDatabase.Instance.CheckedVesselsTable.ContainsKey(this.vessel.id))
-			{
-				return;
 			}
 
 			Tools.DebugLogger log;
@@ -194,11 +181,38 @@
 			log = Tools.DebugLogger.New(this);
 			#endif
 
+			long searchTime = searchTimer.ElapsedMilliseconds;
+			long timeSinceLast = searchTime - this.lastSearch;
+
+			if (timeSinceLast < millisecondsBetweenSearches)
+			{
+				log.AppendFormat(
+					"{0}: Target search skipped because it's not time to search again yet ({1} - {2}) < {3})",
+					this, searchTime, this.lastSearch, millisecondsBetweenSearches
+				);
+				log.Print();
+				return;
+			}
+
+			// Skip vessels that have already been checked for a nearest relay this pass.
+			if (this.isChecked)
+			{
+				log.AppendFormat("{0}: Target search skipped because our vessel has been checked already this search.",
+					this);
+				log.Print();
+				return;
+			}
+
 			log.AppendFormat("{0}: Target search started at {1} ms ({2} ms since last search).",
 				this.ToString(), searchTime, timeSinceLast);
-			
+
+			#if DEBUG
+			try {
+			#endif
 			// Set this vessel as checked, so that we don't check it again.
-			RelayDatabase.Instance.CheckedVesselsTable[vessel.id] = true;
+			this.isChecked = true;
+
+			this.lastSearch = searchTime;
 
 			// Blank everything we're trying to find before the search.
 			this.firstOccludingBody = null;
@@ -225,8 +239,24 @@
 			IList<IAntennaRelay> vesselRelays;
 			for (int vIdx = 0; vIdx < FlightGlobals.Vessels.Count; vIdx++)
 			{
+				log.AppendFormat("\nFetching vessel at index {0}", vIdx);
 				potentialVessel = FlightGlobals.Vessels[vIdx];
+				
+				if (potentialVessel == null)
+				{
+					log.AppendFormat("\n\tSkipping vessel at index {0} because it is null.", vIdx);
+					log.Print();
+					return;
+				}
+				#if DEBUG
+				else
+				{
+					log.AppendFormat("\n\tGot vessel {0}", potentialVessel);
+				}
+				#endif
+
 				// Skip vessels of the wrong type.
+				log.Append("\n\tchecking vessel type");
 				switch (potentialVessel.vesselType)
 				{
 					case VesselType.Debris:
@@ -234,43 +264,62 @@
 					case VesselType.EVA:
 					case VesselType.SpaceObject:
 					case VesselType.Unknown:
+							log.Append("\n\tSkipping because vessel is the wrong type.");
 						continue;
 					default:
 						break;
 				}
-
+				
+				log.Append("\n\tchecking if vessel is this vessel");
 				// Skip vessels with the wrong ID
 				if (potentialVessel.id == vessel.id)
 				{
+					log.Append("\n\tSkipping because vessel is this vessel.");
 					continue;
 				}
 
 				// Find the distance from here to the vessel...
+				log.Append("\n\tgetting distance to potential vessel");
 				double potentialSqrDistance = this.sqrDistanceTo(potentialVessel);
+				log.Append("\n\tgetting vessel relays");
 				vesselRelays = potentialVessel.GetAntennaRelays();
+					log.AppendFormat("\n\t\tvesselRelays: {0}",
+						vesselRelays == null ? "null" : vesselRelays.Count.ToString());
 
 				CelestialBody fob = null;
-
+				
+				log.Append("\n\tdoing LOS check");
 				// Skip vessels to which we do not have line of sight.
 				if (
 					ARConfiguration.RequireLineOfSight &&
 					!this.vessel.hasLineOfSightTo(potentialVessel, out fob, ARConfiguration.RadiusRatio)
 				)
 				{
+					log.Append("\n\tfailed LOS check");
 					this.firstOccludingBody = fob;
-
+					
 					log.AppendFormat("\n\t{0}: Vessel {1} not in line of sight.",
 						this.ToString(), potentialVessel.vesselName);
+					
+					log.AppendFormat("\n\t\tpotentialSqrDistance: {0}", potentialSqrDistance);
+					log.AppendFormat("\n\t\tbestOccludedSqrDistance: {0}", bestOccludedSqrDistance);
+					log.AppendFormat("\n\t\tmaxTransmitSqrDistance: {0}", maxTransmitSqrDistance);
 
 					if (
 						(potentialSqrDistance < bestOccludedSqrDistance) &&
 						(potentialSqrDistance < maxTransmitSqrDistance)
 					)
 					{
-						
+						log.Append("\n\t\t...vessel is close enough to check for occluded relays");
+						log.AppendFormat("\n\t\tthis: {0}", this);
+						log.AppendFormat("\n\t\tpotentialVessel: {0}",
+							potentialVessel == null ? "null" : potentialVessel.ToString());
+						log.AppendFormat("\n\t\tvesselRelays: {0}",
+							vesselRelays == null ? "null" : vesselRelays.ToString());
+
 						log.AppendFormat("\n\t\t{0}: Checking {1} relays on occluded vessel {2}.",
 							this.ToString(),
-							potentialVessel.GetAntennaRelays().Count,
+							vesselRelays.Count,
 							potentialVessel
 						);
 
@@ -302,9 +351,12 @@
 							}
 						}
 					}
-
+					
+					log.Append("\n\t\t...vessel is not close enough to check for occluded relays, carrying on");
 					continue;
 				}
+
+				log.Append("\n\tpassed LOS check");
 
 				/*
 				 * ...so that we can skip the vessel if it is further away than a vessel we've already checked.
@@ -319,25 +371,35 @@
 					continue;
 				}
 
+				log.Append("\n\tpassed distance check");
+
 				IAntennaRelay potentialRelay;
 				for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
 				{
+					log.AppendFormat("\n\t\tfetching vessel relay at index {0}", rIdx);
 					potentialRelay = vesselRelays[rIdx];
-
-					if (potentialRelay.CanTransmit() && potentialRelay.targetRelay != this)
+					log.AppendFormat("\n\t\tgot relay {0}", potentialRelay == null ? "null" : potentialRelay.ToString());
+
+					if (potentialRelay == null)
+					{
+						log.Append("\n\t\t...skipping null relay");
+						continue;
+					}
+
+					if (
+						potentialRelay.CanTransmit() &&
+						(potentialRelay.targetRelay == null || potentialRelay.targetRelay.vessel != this.vessel))
 					{
 						// @TODO: Moved this here from outside the loop; why was it there?
 						nearestRelaySqrDistance = potentialSqrDistance;
 						this.nearestRelay = potentialRelay;
 
-						if (FlightGlobals.ActiveVessel != null && FlightGlobals.ActiveVessel.id == this.vessel.id)
-						{
-							log.AppendFormat("\n\t{0}: found new nearest relay {1} ({2}m)",
-								this.ToString(),
-								this.nearestRelay.ToString(),
-								Math.Sqrt(nearestRelaySqrDistance)
-							);
-						}
+						log.AppendFormat("\n\t{0}: found new nearest relay {1} ({2}m)",
+							this.ToString(),
+							this.nearestRelay.ToString(),
+							Math.Sqrt(nearestRelaySqrDistance)
+						);
+						
 						break;
 					}
 				}
@@ -563,12 +625,20 @@
 				this.ToString(), searchTimer.ElapsedMilliseconds, searchTimer.ElapsedMilliseconds - searchTime);;
 
 			log.AppendFormat("\n{0}: Status determination complete.", this.ToString());
-
+			
+			#if DEBUG
+			} catch (Exception ex) {
+				log.AppendFormat("\nCaught {0}: {1}\n{2}", ex.GetType().FullName, ex.ToString(), ex.StackTrace);
+				UnityEngine.Application.Quit();
+			} finally {
+			#endif
 			log.Print(false);
-
+			#if DEBUG
+			}
+			#endif
 			// Now that we're done with our recursive CanTransmit checks, flag this relay as not checked so it can be
 			// used next time.
-			RelayDatabase.Instance.CheckedVesselsTable.Remove(vessel.id);
+			this.isChecked = false;
 		}
 
 		/// <summary>
@@ -592,6 +662,9 @@
 		public AntennaRelay(IAntennaRelay module)
 		{
 			this.moduleRef = module;
+			this.isChecked = false;
+
+			Tools.PostLogMessage("{0}: constructed {1}", this.GetType().Name, this.ToString());
 		}
 	}
 }

--- a/IAntennaRelay.cs
+++ b/IAntennaRelay.cs
@@ -83,6 +83,8 @@
 		/// </summary>
 		bool CanTransmit();
 
+		void FindNearestRelay();
+
 		/// <summary>
 		/// Returns a <see cref="System.String"/> that represents the current <see cref="AntennaRange.IAntennaRelay"/>.
 		/// </summary>

--- a/ModuleLimitedDataTransmitter.cs
+++ b/ModuleLimitedDataTransmitter.cs
@@ -436,6 +436,14 @@
 			return this.relay.CanTransmit();
 		}
 
+		public void FindNearestRelay()
+		{
+			if (this.relay != null)
+			{
+				this.relay.FindNearestRelay();
+			}
+		}
+
 		/// <summary>
 		/// Override ModuleDataTransmitter.TransmitData to check against CanTransmit and fail out when CanTransmit
 		/// returns false.
@@ -444,6 +452,8 @@
 		/// <param name="callback">Callback function</param>
 		public new void TransmitData(List<ScienceData> dataQueue, Callback callback)
 		{
+			this.FindNearestRelay();
+
 			this.PreTransmit_SetPacketSize();
 			this.PreTransmit_SetPacketResourceCost();
 
@@ -558,6 +568,8 @@
 		/// </summary>
 		public new void StartTransmission()
 		{
+			this.FindNearestRelay();
+
 			PreTransmit_SetPacketSize ();
 			PreTransmit_SetPacketResourceCost ();
 

--- a/ProtoAntennaRelay.cs
+++ b/ProtoAntennaRelay.cs
@@ -54,6 +54,12 @@
 				}
 				else
 				{
+					Tools.PostLogMessage("{0}: Could not fetch vessel!  {1}{2}{3}",
+						this.ToString(),
+						this.protoPart == null ? "\n\tprotoPart=Null" : string.Empty,
+						this.protoPart != null && this.protoPart.pVesselRef == null ? "\n\tthis.protoPart.pVesselRef=Null" : string.Empty,
+						this.protoPart != null && this.protoPart.pVesselRef != null && this.protoPart.pVesselRef.vesselRef == null ? "\n\tthis.protoPart.pVesselRef.vesselRef=Null" : string.Empty
+					);
 					return null;
 				}
 			}
@@ -146,6 +152,8 @@
 		public ProtoAntennaRelay(IAntennaRelay prefabRelay, ProtoPartSnapshot pps) : base(prefabRelay)
 		{
 			this.protoPart = pps;
+
+			Tools.PostLogMessage("{0}: constructed {1}", this.GetType().Name, this.ToString());
 		}
 	}
 }

--- a/RelayDatabase.cs
+++ b/RelayDatabase.cs
@@ -43,7 +43,7 @@
 		 * Static members
 		 * */
 		// Singleton storage
-		protected static RelayDatabase _instance;
+		private static RelayDatabase _instance;
 		// Gets the singleton
 		public static RelayDatabase Instance
 		{
@@ -66,16 +66,17 @@
 		 * Fields
 		 * */
 		// Vessel.id-keyed hash table of Part.GetHashCode()-keyed tables of relay objects.
-		protected Dictionary<Guid, List<IAntennaRelay>> relayDatabase;
+		private Dictionary<Guid, List<IAntennaRelay>> relayDatabase;
+		private Dictionary<Guid, IAntennaRelay> bestRelayTable;
 
 		// Vessel.id-keyed hash table of part counts, used for caching
-		protected Dictionary<Guid, int> vesselPartCountTable;
+		private Dictionary<Guid, int> vesselPartCountTable;
 
 		// Vessel.id-keyed hash table of booleans to track what vessels have been checked so far this time.
 		public Dictionary<Guid, bool> CheckedVesselsTable;
 
-		protected int cacheHits;
-		protected int cacheMisses;
+		private int cacheHits;
+		private int cacheMisses;
 
 		/*
 		 * Properties
@@ -113,9 +114,43 @@
 		/* 
 		 * Methods
 		 * */
+		// Remove a vessel from the cache, if it exists.
+		public void DirtyVessel(Vessel vessel)
+		{
+			this.relayDatabase.Remove(vessel.id);
+			this.vesselPartCountTable.Remove(vessel.id);
+			this.relayDatabase.Remove(vessel.id);
+		}
+
+		// Returns true if both the relayDatabase and the vesselPartCountDB contain the vessel id.
+		public bool ContainsKey(Guid key)
+		{
+			return this.relayDatabase.ContainsKey(key);
+		}
+
+		// Returns true if both the relayDatabase and the vesselPartCountDB contain the vessel.
+		public bool ContainsKey(Vessel vessel)
+		{
+			return this.ContainsKey(vessel.id);
+		}
+
+		public IAntennaRelay GetBestVesselRelay(Vessel vessel)
+		{
+			IAntennaRelay relay;
+			if (this.bestRelayTable.TryGetValue(vessel.id, out relay))
+			{
+				return relay;
+			}
+			else
+			{
+				var dump = this[vessel];
+				return null;
+			}
+		}
+
 		// Adds a vessel to the database
 		// The return for this function isn't used yet, but seems useful for potential future API-uses
-		public bool AddVessel(Vessel vessel)
+		private bool AddVessel(Vessel vessel)
 		{
 			// If this vessel is already here...
 			if (this.ContainsKey(vessel))
@@ -146,7 +181,7 @@
 		}
 
 		// Update the vessel's entry in the table
-		public void UpdateVessel(Vessel vessel)
+		private void UpdateVessel(Vessel vessel)
 		{
 			// Squak if the database doesn't have the vessel
 			if (!this.ContainsKey(vessel))
@@ -167,31 +202,6 @@
 			this.vesselPartCountTable[vessel.id] = vessel.Parts.Count;
 		}
 
-		// Remove a vessel from the cache, if it exists.
-		public void DirtyVessel(Vessel vessel)
-		{
-			if (this.relayDatabase.ContainsKey(vessel.id))
-			{
-				this.relayDatabase.Remove(vessel.id);
-			}
-			if (this.vesselPartCountTable.ContainsKey(vessel.id))
-			{
-				this.vesselPartCountTable.Remove(vessel.id);
-			}
-		}
-
-		// Returns true if both the relayDatabase and the vesselPartCountDB contain the vessel id.
-		public bool ContainsKey(Guid key)
-		{
-			return this.relayDatabase.ContainsKey(key);
-		}
-
-		// Returns true if both the relayDatabase and the vesselPartCountDB contain the vessel.
-		public bool ContainsKey(Vessel vessel)
-		{
-			return this.ContainsKey(vessel.id);
-		}
-
 		// Runs when a vessel is modified (or when we switch to one, to catch docking events)
 		public void onVesselEvent(Vessel vessel)
 		{
@@ -216,7 +226,7 @@
 		}
 
 		// Runs when the player requests a scene change, such as when changing vessels or leaving flight.
-		public void onSceneChange(GameScenes scene)
+		private void onSceneChange(GameScenes scene)
 		{
 			// If the active vessel is a real thing...
 			if (FlightGlobals.ActiveVessel != null)
@@ -227,7 +237,7 @@
 		}
 
 		// Runs when parts are undocked
-		public void onPartEvent(Part part)
+		private void onPartEvent(Part part)
 		{
 			if (part != null && part.vessel != null)
 			{
@@ -236,14 +246,14 @@
 		}
 
 		// Runs when parts are coupled, as in docking
-		public void onFromPartToPartEvent(GameEvents.FromToAction<Part, Part> data)
+		private void onFromPartToPartEvent(GameEvents.FromToAction<Part, Part> data)
 		{
 			this.onPartEvent(data.from);
 			this.onPartEvent(data.to);
 		}
 
 		// Produce a Part-hashed table of relays for the given vessel
-		protected void getVesselRelays(Vessel vessel, ref List<IAntennaRelay> relays)
+		private void getVesselRelays(Vessel vessel, ref List<IAntennaRelay> relays)
 		{
 			// We're going to completely regen this table, so dump the current contents.
 			relays.Clear();
@@ -253,6 +263,10 @@
 				"IAntennaRelay",
 				vessel.vesselName
 			));
+
+			double bestRelayRange = double.NegativeInfinity;
+			IAntennaRelay bestRelay = null;
+			IAntennaRelay relay;
 
 			// If the vessel is loaded, we can fetch modules implementing IAntennaRelay directly.
 			if (vessel.loaded) {
@@ -277,8 +291,16 @@
 						// ...if the module is a relay...
 						if (module is IAntennaRelay)
 						{
+							relay = (module as IAntennaRelay);
+
+							if (relay.maxTransmitDistance > bestRelayRange)
+							{
+								bestRelayRange = relay.maxTransmitDistance;
+								bestRelay = relay;
+							}
+
 							// ...add the module to the table
-							relays.Add(module as IAntennaRelay);
+							relays.Add(relay);
 							// ...neglect relay objects after the first in each part.
 							break;
 						}
@@ -337,14 +359,24 @@
 								module
 							));
 
+							relay = new ProtoAntennaRelay(module as IAntennaRelay, pps);
+
+							if (relay.maxTransmitDistance > bestRelayRange)
+							{
+								bestRelayRange = relay.maxTransmitDistance;
+								bestRelay = relay;
+							}
+
 							// ...build a new ProtoAntennaRelay and add it to the table
-							relays.Add(new ProtoAntennaRelay(module as IAntennaRelay, pps));
+							relays.Add(relay);
 							// ...neglect relay objects after the first in each part.
 							break;
 						}
 					}
 				}
 			}
+
+			this.bestRelayTable[vessel.id] = bestRelay;
 
 			Tools.PostDebugMessage(string.Format(
 				"{0}: vessel '{1}' ({2}) has {3} transmitters.",
@@ -356,10 +388,11 @@
 		}
 
 		// Construct the singleton
-		protected RelayDatabase()
+		private RelayDatabase()
 		{
 			// Initialize the databases
 			this.relayDatabase = new Dictionary<Guid, List<IAntennaRelay>>();
+			this.bestRelayTable = new Dictionary<Guid, IAntennaRelay>();
 			this.vesselPartCountTable = new Dictionary<Guid, int>();
 			this.CheckedVesselsTable = new Dictionary<Guid, bool>();
 

--- a/RelayExtensions.cs
+++ b/RelayExtensions.cs
@@ -166,25 +166,7 @@
 		/// <param name="vessel">This <see cref="Vessel"/></param>
 		public static IAntennaRelay GetBestRelay(this Vessel vessel)
 		{
-			IAntennaRelay bestRelay = null;
-			double bestScore = double.PositiveInfinity;
-			double relayScore = double.NaN;
-
-			IList<IAntennaRelay> vesselRelays = RelayDatabase.Instance[vessel];
-			IAntennaRelay relay;
-			for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
-			{
-				relay = vesselRelays[rIdx];
-				relayScore = relay.transmitDistance / relay.maxTransmitDistance;
-
-				if (relayScore < bestScore)
-				{
-					bestScore = relayScore;
-					bestRelay = relay;
-				}
-			}
-
-			return bestRelay;
+			return RelayDatabase.Instance.GetBestVesselRelay(vessel);
 		}
 	}
 

file:b/VesselCache.cs (new)
--- /dev/null
+++ b/VesselCache.cs
@@ -1,1 +1,16 @@
+// AntennaRange © 2015 toadicus
+//
+// This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a
+// copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
+using System;
 
+namespace AntennaRange
+{
+	public class Relay
+	{
+		public Vessel vessel;
+		public IAntennaRelay targetRelay;
+	}
+}
+
+