TL; DR: zacznij bez boksu, a następnie profilu.
Stos Alokacja vs Boxed Alokacji
Jest to chyba bardziej jednoznaczne:
- Kij do stosu,
- Jeżeli wartość ta jest na tyle duża, że byłoby dmuchać to.
Podczas semantycznie pisanie fn foo() -> Bar
zakłada przeniesienie Bar
z ramy odbierającego do ramy rozmówcy, w praktyce jest bardziej prawdopodobne, aby skończyć z równoważnikiem fn foo(__result: mut * Bar)
podpisu gdzie dzwoniący przydziela miejsca na stosie i przechodzi wskaźnik do kanclerza.
To nie zawsze może być wystarczająca, aby zapobiec kopiowaniu, ponieważ niektóre wzory mogą uniemożliwić pisanie bezpośrednio w gnieździe powrotnej:
fn defeat_copy_elision() -> WithDrop {
let one = side_effectful();
if side_effectful_too() {
one
} else {
side_effects_hurt()
}
}
Tu nie ma żadnej magii:
- jeśli zastosowań kompilatora szczelinę zwrotną dla
one
, następnie w przypadku, gdy oddział oceni na false
, musi przenieść one
, a następnie utworzyć nowy WithDrop
i ostatecznie zniszczyć one
,
- , jeśli kompilator utworzy na bieżącym stosie
one
i musi go zwrócić, to musi wykonać kopię.
Jeśli typ nie był potrzebny Drop
, problem nie wystąpił.
Mimo tych dziwacznych przypadków, radzę trzymać się stosu, jeśli to możliwe, chyba że profilowanie ujawnia miejsce, w którym byłoby korzystne dla pudełka.
Inline Użytkownik lub pudełkowany Użytkownik
Ta sprawa jest znacznie bardziej skomplikowana:
wielkość struct
/enum
ma wpływu, a zatem zachowanie cache procesora wpływa:
- mniej za stosowane równomiernie duże warianty są dobrym kandydatem do boksu (lub ich części bokserskich),
- rzadziej dostępni wielcy członkowie są dobrym kandydatem do boksu.
w tym samym czasie, są koszty boksie:
- to niezgodne z
Copy
typów, a pośrednio realizuje Drop
(która, jak widać powyżej, wyłącza pewne optymalizacje)
- alokację/zwalnianie pamięci ma nieograniczone opóźnienie: ,
- uzyskiwanie dostępu do pamięci pudełkowej wprowadza zależność od danych: nie można określić, która linia pamięci podręcznej ma zażądać przed poznaniem adresu.
W rezultacie jest to bardzo dobrze balansowanie. Boksowanie lub rozpakowywanie członka może poprawić wydajność niektórych części kodu, zmniejszając przy tym wydajność innych.
Nie ma jednego uniwersalnego rozmiaru.
Tak więc, raz jeszcze, radzę unikać boksowania, dopóki profilowanie nie ujawni miejsca, w którym byłoby korzystne dla skrzynki.
Uważają, że na Linuksie, każda alokacja pamięci, dla których nie ma zapasowego pamięci w procesie może wymagać wywołania systemowego, który jeśli nie ma zapasowego pamięci w systemie operacyjnym może wywołać zabójcy OOM zabić proces, w którym to momencie pamięć zostaje uratowana i udostępniona. Prosta wersja malloc(1)
może z łatwością wymagać milisekund.