Skip to content

Commit

Permalink
Type "where used" analyzer - reduce memory usage
Browse files Browse the repository at this point in the history
Discard method bodies after use to reduce memory usage.
This lowers the overall memory required, and improves performance by
reducing the number of higher GC gen collections, promotions and heap
expansions
  • Loading branch information
EdHarvey committed Feb 28, 2015
1 parent 313f8f6 commit 70b1927
Showing 1 changed file with 26 additions and 6 deletions.
32 changes: 26 additions & 6 deletions ILSpy/TreeNodes/Analyzer/AnalyzedTypeUsedByTreeNode.cs
Expand Up @@ -126,18 +126,38 @@ private bool IsUsedInMethodReference(MethodReference method)
private bool IsUsedInMethodDefinition(MethodDefinition method)
{
return IsUsedInMethodReference(method)
|| IsUsedInMethodBody(method.Body)
|| IsUsedInMethodBody(method)
|| IsUsedInCustomAttributes(method.CustomAttributes);
}

private bool IsUsedInMethodBody(MethodBody body)
private bool IsUsedInMethodBody(MethodDefinition method)
{
if (body == null)
if (method.Body == null)
return false;

return body.Instructions.Select(ins => ins.Operand as TypeReference).Any(IsUsedInTypeReference)
|| body.Instructions.Select(ins => ins.Operand as MethodReference).Any(IsUsedInMethodReference)
|| body.Instructions.Select(ins => ins.Operand as FieldReference).Any(IsUsedInFieldReference);
bool found = false;

foreach (var instruction in method.Body.Instructions) {
TypeReference tr = instruction.Operand as TypeReference;
if (IsUsedInTypeReference(tr)) {
found = true;
break;
}
FieldReference fr = instruction.Operand as FieldReference;
if (IsUsedInFieldReference(fr)) {
found = true;
break;
}
MethodReference mr = instruction.Operand as MethodReference;
if (IsUsedInMethodReference(mr)) {
found = true;
break;
}
}

method.Body = null; // discard body to reduce memory pressure & higher GC gen collections

return found;
}

private bool IsUsedInMethodParameters(IEnumerable<ParameterDefinition> parameters)
Expand Down

1 comment on commit 70b1927

@EdHarvey
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've also converted this function from Linq to an explicit loop.
In the vast majority of Methods (where the type is not used) the Linq constructs added a significant overhead; We had to loop through the instructions 3 times, and Linq had to create a predicate for each select...

Please sign in to comment.