-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathProgram.cs
321 lines (269 loc) · 9.41 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
using System.Diagnostics;
using System.Runtime.Serialization.Formatters.Binary;
using TreeIterator;
using TreeIterator.TestApp;
// ReSharper disable RedundantAssignment
#pragma warning disable SYSLIB0011
bool iterate = true;
TreeEnumerationMode enumerationMode = TreeEnumerationMode.DepthFirst;
EnterSelection:
Console.Clear();
Write("Please choose what you want to do:");
Write("1 - Mirror directory in tree, iterate it (timing), serialize " +
"tree binary (legacy + custom), as XML and dump it as text.");
Write("2 - Deserialize from legacy binary file");
Write("3 - Deserialize from custom binary file");
Write("4 - Deserialize from XML");
Write($"5 - Change deserialization iteration on/off [Current: {iterate}]");
Write($"6 - Change enumeration mode Depth/Breadth [Current: {enumerationMode} - Color " +
"Code: " + (enumerationMode == TreeEnumerationMode.DepthFirst ? "Cyan" : "Green") + "]");
Write("7 - Exit");
if (!int.TryParse(Console.ReadLine(), out var selection))
goto EnterSelection;
Stopwatch stopwatch = new();
if (selection == 1)
{
EnterPath:
Write("Enter any directory which should be built as tree (or enter for the test directory [recommended]:");
string? rootDir = Console.ReadLine();
if (string.IsNullOrEmpty(rootDir))
{
rootDir = Path.Combine(Environment.CurrentDirectory, "Test Folder");
}
DirectoryInfo root;
try
{
root = new(rootDir);
if (!root.Exists) throw new();
}
catch
{
Write("Yeah sure thing, but that ain't no valid directory. Once again...", ConsoleColor.Red);
goto EnterPath;
}
string output = Path.Combine(Environment.CurrentDirectory, "fsTree.txt");
Write($"A tree of the file system structure will be built now. " +
$"The output will be placed inside '{output}'.", ConsoleColor.Cyan);
Write("Depending on your directory this might take a while. Don't close the application! Stuff is happening right now.",
ConsoleColor.Yellow);
// Build tree
FileSystemTreeBranch rootBranch = new(root.Name, true);
FileSystemTree tree = new(rootBranch);
BuildTree(root, rootBranch);
Write("The tree is built up. Press key to start iteration. WARNING: No real performance test!", ConsoleColor.Yellow);
Console.ReadLine();
Console.ForegroundColor = ConsoleColor.Magenta;
tree.EnumerationMode = TreeEnumerationMode.BreadthFirst;
// Cold run-through
stopwatch.Start();
foreach (var _ in tree)
{
}
stopwatch.Stop();
Write($"Breadth-first cold run-through: {stopwatch.Elapsed.TotalMilliseconds} ms ({stopwatch.Elapsed.TotalSeconds} s).",
ConsoleColor.Red);
// Warm run-through
stopwatch.Restart();
foreach (var _ in tree)
{
}
stopwatch.Stop();
Write($"Breadth-first warm run-through: {stopwatch.Elapsed.TotalMilliseconds} ms ({stopwatch.Elapsed.TotalSeconds} s).",
ConsoleColor.Red);
// Cold run-through
tree.EnumerationMode = TreeEnumerationMode.DepthFirst;
stopwatch.Restart();
foreach (var _ in tree)
{
}
stopwatch.Stop();
Write($"Depth-first cold run-through: {stopwatch.Elapsed.TotalMilliseconds} ms ({stopwatch.Elapsed.TotalSeconds} s).",
ConsoleColor.Red);
// Warm run-through
stopwatch.Restart();
foreach (var _ in tree)
{
}
stopwatch.Stop();
Write($"Depth-first warm run-through: {stopwatch.Elapsed.TotalMilliseconds} ms ({stopwatch.Elapsed.TotalSeconds} s).",
ConsoleColor.Red);
// Dump
stopwatch.Restart();
tree.Dump(output);
stopwatch.Stop();
Performance("Text dump write down", stopwatch.Elapsed);
// Serialize
BinaryFormatter formatter = new();
using (FileStream fs = new(Path.Combine(Environment.CurrentDirectory, "tree.legacybin"), FileMode.OpenOrCreate))
{
stopwatch.Restart();
formatter.Serialize(fs, tree);
stopwatch.Stop();
}
Performance("Legacy binary write down", stopwatch.Elapsed);
stopwatch.Restart();
tree.WriteXml(Path.Combine(Environment.CurrentDirectory, "tree.xml"));
stopwatch.Stop();
Performance("XML write down", stopwatch.Elapsed);
stopwatch.Restart();
tree.WriteBinary(Path.Combine(Environment.CurrentDirectory, "tree.bin"));
stopwatch.Stop();
Performance("Binary write down", stopwatch.Elapsed);
Console.ReadLine();
Process.Start(Environment.CurrentDirectory);
}
else if (selection == 2)
{
string file = Path.Combine(Environment.CurrentDirectory, "tree.legacybin");
BinaryFormatter formatter = new();
try
{
FileSystemTree fsTree;
using (FileStream fs = new(file, FileMode.Open))
{
// Cold run-through
stopwatch.Start();
fsTree = (FileSystemTree)formatter.Deserialize(fs);
stopwatch.Stop();
Performance("Legacy binary deserialization cold run-through", stopwatch.Elapsed);
// Warm run-through
fs.Seek(0, SeekOrigin.Begin);
stopwatch.Restart();
fsTree = (FileSystemTree)formatter.Deserialize(fs);
stopwatch.Stop();
Performance("Legacy binary deserialization warm run-through", stopwatch.Elapsed);
}
if (iterate)
{
Console.ForegroundColor = enumerationMode == TreeEnumerationMode.DepthFirst
? ConsoleColor.Cyan
: ConsoleColor.Green;
fsTree.EnumerationMode = enumerationMode;
foreach (var branch in fsTree)
{
Console.WriteLine(branch);
}
}
Write(Environment.NewLine);
}
catch (Exception ex)
{
Write("Error parsing legacy binary file:", ConsoleColor.Red);
Write(ex.Message + ex.StackTrace, ConsoleColor.Red);
}
Write(Environment.NewLine);
Console.Read();
}
else if (selection == 3)
{
string file = Path.Combine(Environment.CurrentDirectory, "tree.bin");
try
{
// Cold run-through
stopwatch.Start();
FileSystemTree fsTree = Tree.ParseBinary<FileSystemTree>(file);
stopwatch.Stop();
Performance("Binary deserialization cold run-through", stopwatch.Elapsed);
// Warm run-through
stopwatch.Restart();
fsTree = (FileSystemTree)Tree<FileSystemTreeBranch>.ParseBinary(file);
stopwatch.Stop();
Performance("Binary deserialization warm run-through", stopwatch.Elapsed);
if (iterate)
{
Console.ForegroundColor = enumerationMode == TreeEnumerationMode.DepthFirst
? ConsoleColor.Cyan
: ConsoleColor.Green;
fsTree.EnumerationMode = enumerationMode;
foreach (var branch in fsTree)
{
Console.WriteLine(branch);
}
}
Write(Environment.NewLine);
}
catch (Exception ex)
{
Write("Error parsing binary file:", ConsoleColor.Red);
Write(ex.Message + ex.StackTrace, ConsoleColor.Red);
}
Write(Environment.NewLine);
Console.Read();
}
else if (selection == 4)
{
string file = Path.Combine(Environment.CurrentDirectory, "tree.xml");
try
{
// Cold run-through
stopwatch.Start();
FileSystemTree fsTree = (FileSystemTree)Tree.ParseXml(file);
stopwatch.Stop();
Performance("XML deserialization cold run-through", stopwatch.Elapsed);
// Warm run-through
stopwatch.Restart();
fsTree = (FileSystemTree)Tree.ParseXml(file);
stopwatch.Stop();
Performance("XML deserialization warm run-through", stopwatch.Elapsed);
if (iterate)
{
Console.ForegroundColor = enumerationMode == TreeEnumerationMode.DepthFirst
? ConsoleColor.Cyan
: ConsoleColor.Green;
fsTree.EnumerationMode = enumerationMode;
foreach (var branch in fsTree)
{
Console.WriteLine(branch);
}
}
Write(Environment.NewLine);
}
catch (Exception ex)
{
Write("Error parsing XML file:", ConsoleColor.Red);
Write(ex.Message + ex.StackTrace, ConsoleColor.Red);
}
Write(Environment.NewLine);
Console.Read();
}
else if (selection == 5)
{
iterate = !iterate;
}
else if (selection == 6)
{
enumerationMode = enumerationMode == TreeEnumerationMode.DepthFirst
? TreeEnumerationMode.BreadthFirst
: TreeEnumerationMode.DepthFirst;
}
else if (selection == 7) return;
goto EnterSelection;
static void BuildTree(DirectoryInfo current, FileSystemTreeBranch branch)
{
// Scans the file system structure and builds up the tree
// The try/catch is necessary for system files as these would fire exceptions
try
{
foreach (var file in current.GetFiles())
branch.AddBranch(new FileSystemTreeBranch(file.Name, false));
foreach (var dir in current.GetDirectories())
{
FileSystemTreeBranch next = new(dir.Name, true);
BuildTree(dir, next);
branch.AddBranch(next);
}
}
catch (UnauthorizedAccessException)
{
}
}
static void Write(string message, ConsoleColor color = ConsoleColor.White)
{
Console.ForegroundColor = color;
Console.WriteLine(message);
}
static void Performance(string name, TimeSpan timing)
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine($"[PERFORMANCE] {name}: {timing.TotalMilliseconds} ms ({timing.TotalSeconds} s)");
}