Browse Source

Add interning support to DefaultAccessor.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
57da5ff3de
  1. 57
      ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs
  2. 4
      ICSharpCode.NRefactory/TypeSystem/DomRegion.cs
  3. 18
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs
  4. 4
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs

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

@ -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);
} }
}//*/ }//*/
} }

4
ICSharpCode.NRefactory/TypeSystem/DomRegion.cs

@ -113,7 +113,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
public override int GetHashCode() public override int GetHashCode()
{ {
unchecked { unchecked {
return BeginColumn + 1100009 * BeginLine + 1200007 * BeginColumn + 1300021 * EndColumn; int hashCode = fileName != null ? fileName.GetHashCode() : 0;
hashCode ^= BeginColumn + 1100009 * BeginLine + 1200007 * BeginColumn + 1300021 * EndColumn;
return hashCode;
} }
} }

18
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs

@ -10,7 +10,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
/// <summary> /// <summary>
/// Default implementation of <see cref="IAccessor"/>. /// Default implementation of <see cref="IAccessor"/>.
/// </summary> /// </summary>
public sealed class DefaultAccessor : AbstractFreezable, IAccessor public sealed class DefaultAccessor : AbstractFreezable, IAccessor, ISupportsInterning
{ {
static readonly DefaultAccessor[] defaultAccessors = CreateDefaultAccessors(); static readonly DefaultAccessor[] defaultAccessors = CreateDefaultAccessors();
@ -74,5 +74,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return attributes; return attributes;
} }
} }
void ISupportsInterning.PrepareForInterning(IInterningProvider provider)
{
attributes = provider.InternList(attributes);
}
int ISupportsInterning.GetHashCodeForInterning()
{
return (attributes != null ? attributes.GetHashCode() : 0) ^ region.GetHashCode() ^ (int)accessibility;
}
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{
DefaultAccessor a = other as DefaultAccessor;
return a != null && (attributes == a.attributes && accessibility == a.accessibility && region == a.region);
}
} }
} }

4
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs

@ -105,13 +105,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
int ISupportsInterning.GetHashCodeForInterning() int ISupportsInterning.GetHashCodeForInterning()
{ {
return attributeType.GetHashCode() ^ (positionalArguments != null ? positionalArguments.GetHashCode() : 0) ^ (namedArguments != null ? namedArguments.GetHashCode() : 0); return attributeType.GetHashCode() ^ (positionalArguments != null ? positionalArguments.GetHashCode() : 0) ^ (namedArguments != null ? namedArguments.GetHashCode() : 0) ^ region.GetHashCode();
} }
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) bool ISupportsInterning.EqualsForInterning(ISupportsInterning other)
{ {
DefaultAttribute a = other as DefaultAttribute; DefaultAttribute a = other as DefaultAttribute;
return a != null && attributeType == a.attributeType && positionalArguments == a.positionalArguments && namedArguments == a.namedArguments; return a != null && attributeType == a.attributeType && positionalArguments == a.positionalArguments && namedArguments == a.namedArguments && region == a.region;
} }
} }
} }

Loading…
Cancel
Save