var heads = new Bridge [FAN_OUT];
for (int i = 0; i < FAN_OUT; ++i)
heads [i] = new Bridge ();
- var multiplexer = new Bridge [FAN_OUT];
- for (int i = 0; i < FAN_OUT; ++i)
+
+ // We make five identical multiplexers to verify Tarjan-bridge can merge them together correctly.
+ var MULTIPLEXER_COUNT = 5;
+ Bridge[] multiplexer0 = null;
+ for(int m = 0; m < MULTIPLEXER_COUNT; m++) {
+ var multiplexer = new Bridge [FAN_OUT];
+ if (m == 0) {
+ multiplexer0 = multiplexer;
+ for (int i = 0; i < FAN_OUT; ++i)
+ {
+ heads [i].Links.Add (multiplexer);
+ multiplexer [i] = new Bridge ();
+ }
+ } else {
+ for (int i = 0; i < FAN_OUT; ++i)
+ {
+ heads [i].Links.Add (multiplexer);
+ multiplexer [i] = multiplexer0 [i];
+ }
+ }
+ }
+
+ Console.WriteLine ("-double fan x5 done-");
+ }
+
+ /*
+ * Not necessarily a pathology, but a special case of where we
+ * generate lots of "dead" SCCs. A non-bridge object that
+ * can't reach a bridge object can safely be removed from the
+ * graph. In this special case it's a linked list hanging off
+ * a bridge object. We can handle this by "forwarding" edges
+ * going to non-bridge nodes that have only a single outgoing
+ * edge. That collapses the whole list into a single node.
+ * We could remove that node, too, by removing non-bridge
+ * nodes with no outgoing edges.
+ */
+ static void SetupDeadList ()
+ {
+ var head = new Bridge ();
+ var tail = new NonBridge ();
+ head.Links.Add (tail);
+ for (int i = 0; i < LIST_LENGTH; ++i)
{
- heads [i].Links.Add (multiplexer);
- multiplexer [i] = new Bridge ();
+ var obj = new NonBridge ();
+ tail.Link = obj;
+ tail = obj;
+ }
+ }
+
+ /*
+ * Triggered a bug in the forwarding mechanic.
+ */
+ static void SetupSelfLinks ()
+ {
+ var head = new Bridge ();
+ var tail = new NonBridge ();
+ head.Links.Add (tail);
+ tail.Link = tail;
+ }
+
+ const int L0_COUNT = 100000;
+ const int L1_COUNT = 100000;
+ const int EXTRA_LEVELS = 4;
+
+ /*
+ Set a complex graph from one bridge to a couple.
+ The graph is designed to expose naive coloring on
+ tarjan and SCC explosion on classic.
+ */
+ static void Spider () {
+ Bridge a = new Bridge ();
+ Bridge b = new Bridge ();
+
+ var l1 = new List<object> ();
+ for (int i = 0; i < L0_COUNT; ++i) {
+ var l0 = new List<object> ();
+ l0.Add (a);
+ l0.Add (b);
+ l1.Add (l0);
+ }
+ var last_level = l1;
+ for (int l = 0; l < EXTRA_LEVELS; ++l) {
+ int j = 0;
+ var l2 = new List<object> ();
+ for (int i = 0; i < L1_COUNT; ++i) {
+ var tmp = new List<object> ();
+ tmp.Add (last_level [j++ % last_level.Count]);
+ tmp.Add (last_level [j++ % last_level.Count]);
+ l2.Add (tmp);
+ }
+ last_level = l2;
}
- Console.WriteLine ("-double fan done-");
+ Bridge c = new Bridge ();
+ c.Links.Add (last_level);
}
static void RunTest (ThreadStart setup)
t.Join ();
for (int i = 0; i < 5; ++i) {
+ Console.WriteLine("-GC {0}/5-", i);
GC.Collect ();
GC.WaitForPendingFinalizers ();
}
RunTest (SetupLinkedFan);
RunTest (SetupInverseFan);
RunTest (SetupDoubleFan);
+ RunTest (SetupDeadList);
+ RunTest (SetupSelfLinks);
+ RunTest (Spider);
for (int i = 0; i < 0; ++i) {
GC.Collect ();