|
|
@ -17,7 +17,7 @@ namespace ICSharpCode.NRefactory.TypeSystem |
|
|
|
{ |
|
|
|
{ |
|
|
|
//* Not a real unit test
|
|
|
|
//* Not a real unit test
|
|
|
|
[TestFixture] |
|
|
|
[TestFixture] |
|
|
|
public class TestInterningProvider : IInterningProvider |
|
|
|
public class TestInterningProvider |
|
|
|
{ |
|
|
|
{ |
|
|
|
sealed class ReferenceComparer : IEqualityComparer<object> |
|
|
|
sealed class ReferenceComparer : IEqualityComparer<object> |
|
|
|
{ |
|
|
|
{ |
|
|
@ -67,11 +67,13 @@ namespace ICSharpCode.NRefactory.TypeSystem |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
HashSet<object> uniqueObjectsPreIntern = new HashSet<object>(new ReferenceComparer()); |
|
|
|
sealed class InterningProvider : IInterningProvider |
|
|
|
HashSet<object> uniqueObjectsPostIntern = new HashSet<object>(new ReferenceComparer()); |
|
|
|
{ |
|
|
|
Dictionary<object, object> byValueDict = new Dictionary<object, object>(); |
|
|
|
internal HashSet<object> uniqueObjectsPreIntern = new HashSet<object>(new ReferenceComparer()); |
|
|
|
Dictionary<ISupportsInterning, ISupportsInterning> supportsInternDict = new Dictionary<ISupportsInterning, ISupportsInterning>(new InterningComparer()); |
|
|
|
internal HashSet<object> uniqueObjectsPostIntern = new HashSet<object>(new ReferenceComparer()); |
|
|
|
Dictionary<IEnumerable<object>, IEnumerable<object>> listDict = new Dictionary<IEnumerable<object>, IEnumerable<object>>(new ListComparer()); |
|
|
|
internal Dictionary<object, object> byValueDict = new Dictionary<object, object>(); |
|
|
|
|
|
|
|
internal Dictionary<ISupportsInterning, ISupportsInterning> supportsInternDict = new Dictionary<ISupportsInterning, ISupportsInterning>(new InterningComparer()); |
|
|
|
|
|
|
|
internal Dictionary<IEnumerable<object>, IEnumerable<object>> listDict = new Dictionary<IEnumerable<object>, IEnumerable<object>>(new ListComparer()); |
|
|
|
|
|
|
|
|
|
|
|
public T Intern<T>(T obj) where T : class |
|
|
|
public T Intern<T>(T obj) where T : class |
|
|
|
{ |
|
|
|
{ |
|
|
@ -90,7 +92,7 @@ namespace ICSharpCode.NRefactory.TypeSystem |
|
|
|
else |
|
|
|
else |
|
|
|
supportsInternDict.Add(s, s); |
|
|
|
supportsInternDict.Add(s, s); |
|
|
|
} |
|
|
|
} |
|
|
|
} else if (obj is string || obj is IType || obj is bool || obj is int) { |
|
|
|
} else if (obj is IType || Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) { |
|
|
|
object output; |
|
|
|
object output; |
|
|
|
if (byValueDict.TryGetValue(obj, out output)) |
|
|
|
if (byValueDict.TryGetValue(obj, out output)) |
|
|
|
obj = (T)output; |
|
|
|
obj = (T)output; |
|
|
@ -126,39 +128,44 @@ namespace ICSharpCode.NRefactory.TypeSystem |
|
|
|
return list; |
|
|
|
return list; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
[Test] |
|
|
|
public void InternProject(IProjectContent pc) |
|
|
|
public void PrintStatistics() |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
foreach (var c in TreeTraversal.PreOrder(CecilLoaderTests.Mscorlib.GetClasses(), c => c.InnerClasses)) { |
|
|
|
foreach (var c in TreeTraversal.PreOrder(pc.GetClasses(), c => c.InnerClasses)) { |
|
|
|
Intern(c.Namespace); |
|
|
|
Intern(c.Namespace); |
|
|
|
Intern(c.Name); |
|
|
|
Intern(c.Name); |
|
|
|
foreach (IMember m in c.Members) { |
|
|
|
foreach (IMember m in c.Members) { |
|
|
|
Intern(m); |
|
|
|
Intern(m); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[Test] |
|
|
|
|
|
|
|
public void PrintStatistics() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
long startMemory = GC.GetTotalMemory(true); |
|
|
|
|
|
|
|
IProjectContent pc = new CecilLoader().LoadAssemblyFile(typeof(object).Assembly.Location); |
|
|
|
|
|
|
|
long memoryWithFullPC = GC.GetTotalMemory(true) - startMemory; |
|
|
|
|
|
|
|
InterningProvider p = new InterningProvider(); |
|
|
|
|
|
|
|
p.InternProject(pc); |
|
|
|
|
|
|
|
PrintStatistics(p); |
|
|
|
|
|
|
|
p = null; |
|
|
|
|
|
|
|
long memoryWithInternedPC = GC.GetTotalMemory(true) - startMemory; |
|
|
|
|
|
|
|
GC.KeepAlive(pc); |
|
|
|
|
|
|
|
Console.WriteLine(memoryWithInternedPC / 1024 + " KB / " + memoryWithFullPC / 1024 + " KB"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void PrintStatistics(InterningProvider p) |
|
|
|
|
|
|
|
{ |
|
|
|
var stats = |
|
|
|
var stats = |
|
|
|
from obj in uniqueObjectsPreIntern |
|
|
|
from obj in p.uniqueObjectsPreIntern |
|
|
|
group 1 by obj.GetType() into g |
|
|
|
group 1 by obj.GetType() into g |
|
|
|
join g2 in (from obj in uniqueObjectsPostIntern group 1 by obj.GetType()) on g.Key equals g2.Key |
|
|
|
join g2 in (from obj in p.uniqueObjectsPostIntern group 1 by obj.GetType()) on g.Key equals g2.Key |
|
|
|
orderby g.Key.FullName |
|
|
|
orderby g.Key.FullName |
|
|
|
select new { Type = g.Key, PreCount = g.Count(), PostCount = g2.Count() }; |
|
|
|
select new { Type = g.Key, PreCount = g.Count(), PostCount = g2.Count() }; |
|
|
|
foreach (var element in stats) { |
|
|
|
foreach (var element in stats) { |
|
|
|
Console.WriteLine(element.Type + ": " + element.PostCount + "/" + element.PreCount); |
|
|
|
Console.WriteLine(element.Type + ": " + element.PostCount + "/" + element.PreCount); |
|
|
|
} |
|
|
|
} |
|
|
|
Console.WriteLine(stats.Sum(r => r.PostCount * SizeOf(r.Type)) / 1024 + " KB / " |
|
|
|
|
|
|
|
+ stats.Sum(r => r.PreCount * SizeOf(r.Type)) / 1024 + " KB"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int SizeOf(Type t) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (t == typeof(string)) |
|
|
|
|
|
|
|
return 16; |
|
|
|
|
|
|
|
long start = GC.GetTotalMemory(true); |
|
|
|
|
|
|
|
object o = FormatterServices.GetUninitializedObject(t); |
|
|
|
|
|
|
|
long stop = GC.GetTotalMemory(true); |
|
|
|
|
|
|
|
GC.KeepAlive(o); |
|
|
|
|
|
|
|
return (int)Math.Max(8, stop - start); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}//*/
|
|
|
|
}//*/
|
|
|
|
} |
|
|
|
} |
|
|
|