/NRefactory/ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs

http://github.com/icsharpcode/ILSpy · C# · 207 lines · 14 code · 2 blank · 191 comment · 0 complexity · ddea32b6bb06651ffcb9c5e67c46e9ca MD5 · raw file

  1. // Copyright (c) AlphaSierraPapa for the SharpDevelop Team
  2. //
  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:
  8. //
  9. // The above copyright notice and this permission notice shall be included in all copies or
  10. // substantial portions of the Software.
  11. //
  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.
  18. using System;
  19. using System.Collections;
  20. using System.Collections.Generic;
  21. using System.Collections.ObjectModel;
  22. using System.Linq;
  23. using System.Runtime.CompilerServices;
  24. using System.Runtime.InteropServices;
  25. using System.Runtime.Serialization;
  26. using ICSharpCode.NRefactory.TypeSystem.Implementation;
  27. using ICSharpCode.NRefactory.Utils;
  28. using NUnit.Framework;
  29. namespace ICSharpCode.NRefactory.TypeSystem
  30. {
  31. /* Not a real unit test
  32. [TestFixture]
  33. public class TestInterningProvider
  34. {
  35. sealed class ReferenceComparer : IEqualityComparer<object>
  36. {
  37. public new bool Equals(object a, object b)
  38. {
  39. return ReferenceEquals(a, b);
  40. }
  41. public int GetHashCode(object obj)
  42. {
  43. return RuntimeHelpers.GetHashCode(obj);
  44. }
  45. }
  46. sealed class InterningComparer : IEqualityComparer<ISupportsInterning>
  47. {
  48. public bool Equals(ISupportsInterning x, ISupportsInterning y)
  49. {
  50. return x.EqualsForInterning(y);
  51. }
  52. public int GetHashCode(ISupportsInterning obj)
  53. {
  54. return obj.GetHashCodeForInterning();
  55. }
  56. }
  57. sealed class ListComparer : IEqualityComparer<IEnumerable<object>>
  58. {
  59. public bool Equals(IEnumerable<object> a, IEnumerable<object> b)
  60. {
  61. if (a.GetType() != b.GetType())
  62. return false;
  63. return Enumerable.SequenceEqual(a, b, new ReferenceComparer());
  64. }
  65. public int GetHashCode(IEnumerable<object> obj)
  66. {
  67. int hashCode = obj.GetType().GetHashCode();
  68. unchecked {
  69. foreach (object o in obj) {
  70. hashCode *= 27;
  71. hashCode += RuntimeHelpers.GetHashCode(o);
  72. }
  73. }
  74. return hashCode;
  75. }
  76. }
  77. sealed class InterningProvider : IInterningProvider
  78. {
  79. internal HashSet<object> uniqueObjectsPreIntern = new HashSet<object>(new ReferenceComparer());
  80. internal HashSet<object> uniqueObjectsPostIntern = new HashSet<object>(new ReferenceComparer());
  81. internal Dictionary<object, object> byValueDict = new Dictionary<object, object>();
  82. internal Dictionary<ISupportsInterning, ISupportsInterning> supportsInternDict = new Dictionary<ISupportsInterning, ISupportsInterning>(new InterningComparer());
  83. internal Dictionary<IEnumerable<object>, IEnumerable<object>> listDict = new Dictionary<IEnumerable<object>, IEnumerable<object>>(new ListComparer());
  84. public T Intern<T>(T obj) where T : class
  85. {
  86. if (obj == null)
  87. return null;
  88. uniqueObjectsPreIntern.Add(obj);
  89. ISupportsInterning s = obj as ISupportsInterning;
  90. if (s != null) {
  91. ISupportsInterning output;
  92. if (supportsInternDict.TryGetValue(s, out output)) {
  93. obj = (T)output;
  94. } else {
  95. s.PrepareForInterning(this);
  96. if (supportsInternDict.TryGetValue(s, out output))
  97. obj = (T)output;
  98. else
  99. supportsInternDict.Add(s, s);
  100. }
  101. } else if (obj is IType || Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) {
  102. object output;
  103. if (byValueDict.TryGetValue(obj, out output))
  104. obj = (T)output;
  105. else
  106. byValueDict.Add(obj, obj);
  107. }
  108. uniqueObjectsPostIntern.Add(obj);
  109. return obj;
  110. }
  111. public IList<T> InternList<T>(IList<T> list) where T : class
  112. {
  113. if (list == null)
  114. return null;
  115. uniqueObjectsPreIntern.Add(list);
  116. for (int i = 0; i < list.Count; i++) {
  117. T oldItem = list[i];
  118. T newItem = Intern(oldItem);
  119. if (oldItem != newItem) {
  120. if (list.IsReadOnly)
  121. list = new T[list.Count];
  122. list[i] = newItem;
  123. }
  124. }
  125. if (!list.IsReadOnly)
  126. list = new ReadOnlyCollection<T>(list);
  127. IEnumerable<object> output;
  128. if (listDict.TryGetValue(list, out output))
  129. list = (IList<T>)output;
  130. else
  131. listDict.Add(list, list);
  132. uniqueObjectsPostIntern.Add(list);
  133. return list;
  134. }
  135. public void InternProject(IProjectContent pc)
  136. {
  137. foreach (var c in TreeTraversal.PreOrder(pc.GetClasses(), c => c.NestedTypes)) {
  138. Intern(c.Namespace);
  139. Intern(c.Name);
  140. foreach (IMember m in c.Members) {
  141. Intern(m);
  142. }
  143. }
  144. }
  145. }
  146. IProjectContent[] LoadProjects(CecilLoader loader)
  147. {
  148. const string dir = @"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.0\";
  149. return new IProjectContent[] {
  150. loader.LoadAssemblyFile(dir + "mscorlib.dll"),
  151. loader.LoadAssemblyFile(dir + "System.dll"),
  152. loader.LoadAssemblyFile(dir + "System.Core.dll"),
  153. loader.LoadAssemblyFile(dir + "System.Xml.dll"),
  154. loader.LoadAssemblyFile(dir + "System.Xml.Linq.dll"),
  155. loader.LoadAssemblyFile(dir + "System.Data.dll"),
  156. loader.LoadAssemblyFile(dir + "System.Drawing.dll"),
  157. loader.LoadAssemblyFile(dir + "System.Windows.Forms.dll"),
  158. loader.LoadAssemblyFile(dir + "WindowsBase.dll"),
  159. loader.LoadAssemblyFile(dir + "PresentationCore.dll"),
  160. loader.LoadAssemblyFile(dir + "PresentationFramework.dll")
  161. };
  162. }
  163. [Test]
  164. public void PrintStatistics()
  165. {
  166. long startMemory = GC.GetTotalMemory(true);
  167. IProjectContent[] pc = LoadProjects(new CecilLoader());
  168. long memoryWithFullPC = GC.GetTotalMemory(true) - startMemory;
  169. InterningProvider p = new InterningProvider();
  170. CecilLoader loader = new CecilLoader();
  171. loader.InterningProvider = p;
  172. pc = LoadProjects(loader);
  173. PrintStatistics(p);
  174. loader = null;
  175. p = null;
  176. long memoryWithInternedPC = GC.GetTotalMemory(true) - startMemory;
  177. GC.KeepAlive(pc);
  178. Console.WriteLine(memoryWithInternedPC / 1024 + " KB / " + memoryWithFullPC / 1024 + " KB");
  179. }
  180. void PrintStatistics(InterningProvider p)
  181. {
  182. var stats =
  183. from obj in p.uniqueObjectsPreIntern
  184. group 1 by obj.GetType() into g
  185. join g2 in (from obj in p.uniqueObjectsPostIntern group 1 by obj.GetType()) on g.Key equals g2.Key
  186. orderby g.Key.FullName
  187. select new { Type = g.Key, PreCount = g.Count(), PostCount = g2.Count() };
  188. foreach (var element in stats) {
  189. Console.WriteLine(element.Type + ": " + element.PostCount + "/" + element.PreCount);
  190. }
  191. }
  192. }//*/
  193. }