2012-06-21 11 views
5

Nie szukam poprawy wydajności lub wykorzystania pamięci, to pytanie było czysto wywołane ciekawością.W jaki sposób są pakowane małe typy danych w C#

Pytanie główne Biorąc pod uwagę następujące klasy będzie kompilator C# (Mono + .NET) zapakować dwie short zmienne do 4 bajtów lub będą one zużywają 8 bajtów (z wyrównaniem)?

public class SomeClass { 
    short a; 
    short b; 
} 

Secondary Pytanie Jeżeli odpowiedź na powyższe pytanie nie było 4 bajty, to w następujący alternatywny oferta jakiekolwiek korzyści (gdzie SomeClass jest stosowany w bardzo dużych ilościach):

// Warning, my bit math might not be entirely accurate! 
public class SomeClass { 
    private int _ab; 

    public short a { 
     get { return _ab & 0x00ff; } 
     set { _ab |= value & 0x00ff; 
    } 
    public short b { 
     get { return _ab >> 8; } 
     set { _ab |= value << 8; } 
    } 
} 
+3

Kompilator C# nie będzie miał z tym nic wspólnego - będzie to środowisko wykonawcze. –

+0

Kiedy mówisz "jest używany w bardzo dużych ilościach" - ilu mówimy i jak są używane? Czy tworzysz tablicę/listę/etc z tych? –

+0

@ReedCopsey Tak, teorią tego kontekstu byłaby duża lista z częstym dostępem do określonych pozycji według indeksu. –

Odpowiedz

5

To zależy od środowiska wykonawczego, a nie kompilator. Można zastąpić domyślne zachowanie za pomocą [StructLayout], co może pomóc - chociaż domyślne zachowanie powinno być w porządku.

W związku z tym, jeśli minimalny całkowity rozmiar jest bezwzględnym wymaganiem, możesz rozważyć wprowadzenie struct zamiast class. Podczas korzystania z klasy każda instancja klasy będzie dodawać znaczny narzut. Pomiędzy synchronizacją, TypeHandle, itp., A także odwołaniem (które w 64-bitowym systemie to kolejne 8 bajtów) instancja obiektu używa sporej ilości "dodatkowej" pamięci powyżej i powyżej twoich szortów. Aby uzyskać szczegółowe informacje, patrz "How the CLR Creates Runtime Objects".

Przechowywanie danych spakowanych w zbiorze typów wartości może całkowicie tego uniknąć i ograniczyć liczbę instancji do 8 bajtów na sumę (plus narzut na zbiór). To zmienia semantykę pod względem użycia, ale jeśli używasz tylko dwóch szortów, zmniejszy to ilość kosztów związanych z typem, szczególnie w systemach 64-bitowych.

+0

Dzięki chłopaki, jest tu kilka fantastycznych odpowiedzi. Dzięki za link, będę musiał przeczytać! –

6

It zależy od środowiska wykonawczego, jak mówi @David_M, ale można go wymusić, używając atrybutu [StructLayout], który ma element Pack, którego można użyć do kontrolowania pakowania. Alternatywnie możesz użyć [FieldOffset], aby ręcznie ułożyć elementy struktury (nawet nakładanie się, czyli w jaki sposób implementujesz związki w .NET).

2

Rzeczywisty układ zależy od środowiska wykonawczego, ponieważ inni skomentowali głównie dlatego, że można uruchomić ten sam kod na wielu platformach.

I tak w przypadku wielu obiektów, które oszczędzają miejsce. To, czego szukasz, to LayoutKind (atrybut StructLayout). Pozwala ci spakować członków, jak chcesz. Na przykład Sekwencyjnie upewni się, że jest ciasno zapakowany.

[StructLayout(LayoutKind.Sequential)] 
public class SomeClass { 
    short a; 
    short b; 
} 

Aby uzyskać więcej informacji sprawdź MSDN- Structlayout

Powiązane problemy