2011-11-21 10 views
5

Chciałbym sprawdzić, jak duży jest skompilowany kod niektórych klas (w bajtach). Chciałbym je zoptymalizować pod względem rozmiaru, ale muszę wiedzieć, od czego zacząć.Określ rozmiar kodu C#

+2

Używasz niewłaściwego języka. – ordag

+2

Eksplorator Windows? ;-) – jadarnel27

+1

Czy to pragnienie ma jakieś praktyczne uzasadnienie, czy jest to czysto bezczynna ciekawość? – LukeH

Odpowiedz

3

Jeśli chcesz poznać rozmiar w bajtach potrzebny do zapisania klasy/typu w środowisku wykonawczym.

Dla value types użyj sizeof(type), dla reference types, użyj sizeof dla każdego pola/właściwości.


Jeśli chcesz poznać rozmiar zarządzanych bibliotek DLL, oczywistym sposobem jest skompilowanie biblioteki dll i sprawdzenie rozmiaru pliku. Aby to zrobić programowo, spójrz na odpowiedź user1027167 i klasę CodeDomProvider.

Coś jeszcze, co może być zrobione w kodzie, to wygenerowanie wygenerowanej IL każdej metody w twoich klasach oraz sizeof pól jako miary (może tylko względnej) wielkości.

Do tego celu można użyć metody MethodBase.GetMethodBody.

Po Roslyn (compiler as a service) zwolnieniu (preview available) prawdopodobnie można dostać łatwiej i ewentualnie dokładnie (jak to nie tylko metod i pól, które tworzą klasę Il.


Jeśli chcesz wiedzieć rozmiar kodu używanego do utworzenia biblioteki DLL, będziesz musiał sprawdzić coś w stylu: Reflector

+0

Chciałbym znać rozmiar kodu każdej klasy w zarządzanej DLL. –

+0

Kiedy mówisz o rozmiarze kodu, masz na myśli rozmiar biblioteki DLL lub rozmiar kodu użytego do utworzenia biblioteki DLL? –

+0

Rozmiar skompilowanego kodu = DLL :) –

1

Zakładając, że chcesz poznać rozmiar w bajtach skompilowanego kodu, myślę, że musisz go skompilować. Jeśli chcesz zautomatyzować to, spójrz na to:

ICodeCompiler comp = (new CSharpCodeProvider().CreateCompiler()); 
CompilerParameters cp = new CompilerParameters(); 
cp.ReferencedAssemblies.Add("system.dll"); 
cp.ReferencedAssemblies.Add("system.data.dll"); 
cp.ReferencedAssemblies.Add("system.xml.dll"); 
cp.GenerateExecutable = false; 
cp.GenerateInMemory = true; 
CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString()); 
if (cr.Errors.HasErrors) 
{ 
    StringBuilder error = new StringBuilder(); 
    error.Append("Error Compiling Expression: "); 
    foreach (CompilerError err in cr.Errors) 
    { 
     error.AppendFormat("{0}\n", err.ErrorText); 
    } 
    throw new Exception("Error Compiling Expression: " + error.ToString()); 
} 
Assembly a = cr.CompiledAssembly; 

Zmienna "kod" (tutaj: StringBuilder) musi zawierać poprawny kod źródłowy klasy, którą chcesz zmierzyć. Po kompilacji wystarczy spojrzeć na rozmiar zespołu wyjściowego.

+0

Należy zauważyć, że metoda 'CSharpCodeProvider.CreateCompiler' jest już nieaktualna. Możesz użyć metod 'ICodeCompiler' na' CSharpCodeProvider' bezpośrednio. –

+0

Może być rozwiązaniem. Będę musiał dokonać refaktoryzacji, ale to może zadziałać. –

3

Jedną z metod będzie uzyskanie rozmiaru MSIL z odbiciem. Będziesz musiał przechodzić przez wszystkie metody, selektory i pobierające właściwości oraz konstruktory, aby określić rozmiar MSIL. Ponadto będą różnice w wielkości w zależności od wersji Debug i wersji Release.

using System.Reflection; 

int totalSize = 0; 

foreach(var mi in typeof(Example).GetMethods(BindingFlags.Public | BindingFlags.NonPublic |BindingFlags.Static | BindingFlags.Instance | BindingFlags.GetProperty | BindingFlags.SetProperty)) 
{ 
    MethodInfo mi = typeof(Example).GetMethod("MethodBodyExample"); 
    MethodBody mb = mi.GetMethodBody(); 
    totalSize += mb.GetILAsByteArray().Length; 
} 
+0

Szukałem, jak znaleźć rozmiar MSIL jednej metody, aby odgadnąć, czy metoda będzie prawdopodobnie inline, i to było dla mnie rozwiązanie. Dzięki! –