[System.ServiceModel] Prevent crash in Dispatcher.ListenerLoopManager… (#7136)
[mono-project.git] / mono / tests / sgen-bridge-pathologies.cs
blob7c8dbc087311677c159a0f3b86b57f8e6d62ef6f
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Threading;
6 public class Bridge {
7 public int __test;
8 public List<object> Links = new List<object> ();
9 public static int fin_count;
10 ~Bridge () {
11 ++fin_count;
12 Links = null;
16 public class NonBridge
18 public object Link;
21 class Driver {
22 const int OBJ_COUNT = 200 * 1000;
23 const int LINK_COUNT = 2;
24 const int EXTRAS_COUNT = 0;
25 const double survival_rate = 0.6;
28 * Pathological case for the original old algorithm. Goes
29 * away when merging is replaced by appending with flag
30 * checking.
32 static void SetupLinks () {
33 var list = new List<Bridge> ();
34 for (int i = 0; i < OBJ_COUNT; ++i) {
35 var bridge = new Bridge ();
36 list.Add (bridge);
39 var r = new Random (100);
40 for (int i = 0; i < OBJ_COUNT; ++i) {
41 var n = list [i];
42 for (int j = 0; j < LINK_COUNT; ++j)
43 n.Links.Add (list [r.Next (OBJ_COUNT)]);
44 for (int j = 0; j < EXTRAS_COUNT; ++j)
45 n.Links.Add (j);
46 if (r.NextDouble () <= survival_rate)
47 n.__test = 1;
49 Console.WriteLine ("-setup done-");
52 const int LIST_LENGTH = 20000;
53 const int FAN_OUT = 20000;
56 * Pathological case for the new algorithm. Goes away with
57 * the single-node elimination optimization, but will still
58 * persist if modified by using a ladder instead of the single
59 * list.
61 static void SetupLinkedFan ()
63 var head = new Bridge ();
64 var tail = new NonBridge ();
65 head.Links.Add (tail);
66 for (int i = 0; i < LIST_LENGTH; ++i)
68 var obj = new NonBridge ();
69 tail.Link = obj;
70 tail = obj;
72 var list = new List<Bridge> ();
73 tail.Link = list;
74 for (int i = 0; i < FAN_OUT; ++i)
75 list.Add (new Bridge ());
76 Console.WriteLine ("-linked fan done-");
80 * Pathological case for the improved old algorithm. Goes
81 * away with copy-on-write DynArrays, but will still persist
82 * if modified by using a ladder instead of the single list.
84 static void SetupInverseFan ()
86 var tail = new Bridge ();
87 object list = tail;
88 for (int i = 0; i < LIST_LENGTH; ++i)
90 var obj = new NonBridge ();
91 obj.Link = list;
92 list = obj;
94 var heads = new Bridge [FAN_OUT];
95 for (int i = 0; i < FAN_OUT; ++i)
97 var obj = new Bridge ();
98 obj.Links.Add (list);
99 heads [i] = obj;
101 Console.WriteLine ("-inverse fan done-");
105 * Pathological case for the bridge in general. We generate
106 * 2*FAN_OUT bridge objects here, but the output of the bridge
107 * is a graph with FAN_OUT^2 edges.
109 static void SetupDoubleFan ()
111 var heads = new Bridge [FAN_OUT];
112 for (int i = 0; i < FAN_OUT; ++i)
113 heads [i] = new Bridge ();
115 // We make five identical multiplexers to verify Tarjan-bridge can merge them together correctly.
116 var MULTIPLEXER_COUNT = 5;
117 Bridge[] multiplexer0 = null;
118 for(int m = 0; m < MULTIPLEXER_COUNT; m++) {
119 var multiplexer = new Bridge [FAN_OUT];
120 if (m == 0) {
121 multiplexer0 = multiplexer;
122 for (int i = 0; i < FAN_OUT; ++i)
124 heads [i].Links.Add (multiplexer);
125 multiplexer [i] = new Bridge ();
127 } else {
128 for (int i = 0; i < FAN_OUT; ++i)
130 heads [i].Links.Add (multiplexer);
131 multiplexer [i] = multiplexer0 [i];
136 Console.WriteLine ("-double fan x5 done-");
140 * Not necessarily a pathology, but a special case of where we
141 * generate lots of "dead" SCCs. A non-bridge object that
142 * can't reach a bridge object can safely be removed from the
143 * graph. In this special case it's a linked list hanging off
144 * a bridge object. We can handle this by "forwarding" edges
145 * going to non-bridge nodes that have only a single outgoing
146 * edge. That collapses the whole list into a single node.
147 * We could remove that node, too, by removing non-bridge
148 * nodes with no outgoing edges.
150 static void SetupDeadList ()
152 var head = new Bridge ();
153 var tail = new NonBridge ();
154 head.Links.Add (tail);
155 for (int i = 0; i < LIST_LENGTH; ++i)
157 var obj = new NonBridge ();
158 tail.Link = obj;
159 tail = obj;
164 * Triggered a bug in the forwarding mechanic.
166 static void SetupSelfLinks ()
168 var head = new Bridge ();
169 var tail = new NonBridge ();
170 head.Links.Add (tail);
171 tail.Link = tail;
174 const int L0_COUNT = 100000;
175 const int L1_COUNT = 100000;
176 const int EXTRA_LEVELS = 4;
179 Set a complex graph from one bridge to a couple.
180 The graph is designed to expose naive coloring on
181 tarjan and SCC explosion on classic.
183 static void Spider () {
184 Bridge a = new Bridge ();
185 Bridge b = new Bridge ();
187 var l1 = new List<object> ();
188 for (int i = 0; i < L0_COUNT; ++i) {
189 var l0 = new List<object> ();
190 l0.Add (a);
191 l0.Add (b);
192 l1.Add (l0);
194 var last_level = l1;
195 for (int l = 0; l < EXTRA_LEVELS; ++l) {
196 int j = 0;
197 var l2 = new List<object> ();
198 for (int i = 0; i < L1_COUNT; ++i) {
199 var tmp = new List<object> ();
200 tmp.Add (last_level [j++ % last_level.Count]);
201 tmp.Add (last_level [j++ % last_level.Count]);
202 l2.Add (tmp);
204 last_level = l2;
206 Bridge c = new Bridge ();
207 c.Links.Add (last_level);
210 static void RunTest (ThreadStart setup)
212 var t = new Thread (setup);
213 t.Start ();
214 t.Join ();
216 for (int i = 0; i < 5; ++i) {
217 Console.WriteLine("-GC {0}/5-", i);
218 GC.Collect ();
219 GC.WaitForPendingFinalizers ();
222 Console.WriteLine ("-GCs done- {0}", Bridge.fin_count);
225 static int Main ()
227 RunTest (SetupLinks);
228 RunTest (SetupLinkedFan);
229 RunTest (SetupInverseFan);
230 RunTest (SetupDoubleFan);
231 RunTest (SetupDeadList);
232 RunTest (SetupSelfLinks);
233 RunTest (Spider);
235 for (int i = 0; i < 0; ++i) {
236 GC.Collect ();
237 GC.WaitForPendingFinalizers ();
238 Console.WriteLine ("-Cleanup GC- {0}", Bridge.fin_count);
240 return 0;