1
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
3
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4
// software and associated documentation files (the "Software"), to deal in the Software
5
// without restriction, including without limitation the rights to use, copy, modify, merge,
6
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7
// to whom the Software is furnished to do so, subject to the following conditions:
9
// The above copyright notice and this permission notice shall be included in all copies or
10
// substantial portions of the Software.
12
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17
// DEALINGS IN THE SOFTWARE.
20
using System.Collections;
21
using System.Collections.Generic;
22
using System.Collections.ObjectModel;
24
using System.Runtime.CompilerServices;
25
using System.Runtime.InteropServices;
26
using System.Runtime.Serialization;
27
using ICSharpCode.NRefactory.TypeSystem.Implementation;
28
using ICSharpCode.NRefactory.Utils;
29
using NUnit.Framework;
31
namespace ICSharpCode.NRefactory.TypeSystem
33
/* Not a real unit test
35
public class TestInterningProvider
37
sealed class ReferenceComparer : IEqualityComparer<object>
39
public new bool Equals(object a, object b)
41
return ReferenceEquals(a, b);
44
public int GetHashCode(object obj)
46
return RuntimeHelpers.GetHashCode(obj);
50
sealed class InterningComparer : IEqualityComparer<ISupportsInterning>
52
public bool Equals(ISupportsInterning x, ISupportsInterning y)
54
return x.EqualsForInterning(y);
57
public int GetHashCode(ISupportsInterning obj)
59
return obj.GetHashCodeForInterning();
63
sealed class ListComparer : IEqualityComparer<IEnumerable<object>>
65
public bool Equals(IEnumerable<object> a, IEnumerable<object> b)
67
if (a.GetType() != b.GetType())
69
return Enumerable.SequenceEqual(a, b, new ReferenceComparer());
72
public int GetHashCode(IEnumerable<object> obj)
74
int hashCode = obj.GetType().GetHashCode();
76
foreach (object o in obj) {
78
hashCode += RuntimeHelpers.GetHashCode(o);
85
sealed class InterningProvider : IInterningProvider
87
internal HashSet<object> uniqueObjectsPreIntern = new HashSet<object>(new ReferenceComparer());
88
internal HashSet<object> uniqueObjectsPostIntern = new HashSet<object>(new ReferenceComparer());
89
internal Dictionary<object, object> byValueDict = new Dictionary<object, object>();
90
internal Dictionary<ISupportsInterning, ISupportsInterning> supportsInternDict = new Dictionary<ISupportsInterning, ISupportsInterning>(new InterningComparer());
91
internal Dictionary<IEnumerable<object>, IEnumerable<object>> listDict = new Dictionary<IEnumerable<object>, IEnumerable<object>>(new ListComparer());
93
public T Intern<T>(T obj) where T : class
97
uniqueObjectsPreIntern.Add(obj);
98
ISupportsInterning s = obj as ISupportsInterning;
100
ISupportsInterning output;
101
if (supportsInternDict.TryGetValue(s, out output)) {
104
s.PrepareForInterning(this);
105
if (supportsInternDict.TryGetValue(s, out output))
108
supportsInternDict.Add(s, s);
110
} else if (obj is IType || Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) {
112
if (byValueDict.TryGetValue(obj, out output))
115
byValueDict.Add(obj, obj);
117
uniqueObjectsPostIntern.Add(obj);
121
public IList<T> InternList<T>(IList<T> list) where T : class
125
uniqueObjectsPreIntern.Add(list);
126
for (int i = 0; i < list.Count; i++) {
128
T newItem = Intern(oldItem);
129
if (oldItem != newItem) {
131
list = new T[list.Count];
135
if (!list.IsReadOnly)
136
list = new ReadOnlyCollection<T>(list);
137
IEnumerable<object> output;
138
if (listDict.TryGetValue(list, out output))
139
list = (IList<T>)output;
141
listDict.Add(list, list);
142
uniqueObjectsPostIntern.Add(list);
146
public void InternProject(IProjectContent pc)
148
foreach (var c in TreeTraversal.PreOrder(pc.GetClasses(), c => c.NestedTypes)) {
151
foreach (IMember m in c.Members) {
158
IProjectContent[] LoadProjects(CecilLoader loader)
160
const string dir = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\";
161
return new IProjectContent[] {
162
loader.LoadAssemblyFile(dir + "mscorlib.dll"),
163
loader.LoadAssemblyFile(dir + "System.dll"),
164
loader.LoadAssemblyFile(dir + "System.Core.dll"),
165
loader.LoadAssemblyFile(dir + "System.Xml.dll"),
166
loader.LoadAssemblyFile(dir + "System.Xml.Linq.dll"),
167
loader.LoadAssemblyFile(dir + "System.Data.dll"),
168
loader.LoadAssemblyFile(dir + "System.Drawing.dll"),
169
loader.LoadAssemblyFile(dir + "System.Windows.Forms.dll"),
170
loader.LoadAssemblyFile(dir + "WindowsBase.dll"),
171
loader.LoadAssemblyFile(dir + "PresentationCore.dll"),
172
loader.LoadAssemblyFile(dir + "PresentationFramework.dll")
177
public void PrintStatistics()
179
long startMemory = GC.GetTotalMemory(true);
180
IProjectContent[] pc = LoadProjects(new CecilLoader());
181
long memoryWithFullPC = GC.GetTotalMemory(true) - startMemory;
182
InterningProvider p = new InterningProvider();
183
CecilLoader loader = new CecilLoader();
184
loader.InterningProvider = p;
185
pc = LoadProjects(loader);
189
long memoryWithInternedPC = GC.GetTotalMemory(true) - startMemory;
191
Console.WriteLine(memoryWithInternedPC / 1024 + " KB / " + memoryWithFullPC / 1024 + " KB");
194
void PrintStatistics(InterningProvider p)
197
from obj in p.uniqueObjectsPreIntern
198
group 1 by obj.GetType() into g
199
join g2 in (from obj in p.uniqueObjectsPostIntern group 1 by obj.GetType()) on g.Key equals g2.Key
200
orderby g.Key.FullName
201
select new { Type = g.Key, PreCount = g.Count(), PostCount = g2.Count() };
202
foreach (var element in stats) {
203
Console.WriteLine(element.Type + ": " + element.PostCount + "/" + element.PreCount);