Czy ktoś kiedykolwiek faktycznie używał stackalloc
podczas programowania w C #? Zdaję sobie sprawę z tego, co się dzieje, ale jedyny raz, kiedy pojawia się to w moim kodzie, to przypadek, bo Intellisense podpowiada to np. Gdy zaczynam pisać static
.
Chociaż nie jest to związane ze scenariuszami użytkowania programu stackalloc
, w rzeczywistości wykonuję znaczną ilość starszej współpracy w moich aplikacjach, więc od czasu do czasu mogę uciekać się do używania unsafe
kodu. Niemniej jednak zazwyczaj znajduję sposoby, aby unsafe
całkowicie tego uniknąć .
A ponieważ rozmiar stosu dla pojedynczego wątku w .Net wynosi ~ 1 MB (popraw mnie, jeśli się mylę), jestem jeszcze bardziej ograniczony do używania stackalloc
.
Czy są jakieś praktyczne przypadki, w których można by powiedzieć: „jest to dokładnie taka ilość danych i przetwarzania, które są dla mnie niebezpieczne i używane stackalloc
”?
źródło
System.Numbers
używa go dużo referenceource.microsoft.com/#mscorlib/system/…Odpowiedzi:
Jedynym powodem użycia
stackalloc
jest wydajność (do obliczeń lub międzyoperacyjności). Używającstackalloc
zamiast tablicy przydzielonej na sterty, tworzysz mniejszy nacisk GC (GC musi działać mniej), nie musisz przypinać tablic, alokacja jest szybsza niż tablica sterty, a metoda jest automatycznie zwalniana exit (tablice przydzielone do sterty są zwalniane tylko po uruchomieniu GC). Ponadto, używającstackalloc
zamiast natywnego alokatora (takiego jak malloc lub odpowiednik .Net), zyskujesz również prędkość i automatyczne cofanie alokacji przy wyjściu z zakresu.Jeśli chodzi o wydajność, jeśli używasz
stackalloc
ciebie, znacznie zwiększasz prawdopodobieństwo trafienia pamięci podręcznej do procesora ze względu na lokalizację danych.źródło
Użyłem stackalloc do przydzielenia buforów do pracy DSP [prawie] w czasie rzeczywistym. To był bardzo specyficzny przypadek, w którym wydajność musiała być jak najbardziej spójna. Zauważ, że istnieje różnica między spójnością a ogólną przepustowością - w tym przypadku nie przejmowałem się zbyt wolnym alokowaniem sterty, tylko brak determinizmu czyszczenia pamięci w tym punkcie programu. Nie użyłbym go w 99% przypadków.
źródło
stackalloc
dotyczy tylko niebezpiecznego kodu. W przypadku kodu zarządzanego nie możesz zdecydować, gdzie przydzielić dane. Typy wartości są domyślnie przydzielane na stosie (chyba że są częścią typu referencyjnego, w którym to przypadku są przydzielane na stercie). Typy odwołań są przydzielane na stercie.Domyślny rozmiar stosu dla zwykłej waniliowej aplikacji .NET to 1 MB, ale można to zmienić w nagłówku PE. Jeśli jawnie uruchamiasz wątki, możesz również ustawić inny rozmiar za pomocą przeciążenia konstruktora. W przypadku aplikacji ASP.NET domyślny rozmiar stosu to tylko 256 KB, o czym należy pamiętać, jeśli przełączasz się między dwoma środowiskami.
źródło
Inicjalizacja spansów metodą Stackalloc. W poprzednich wersjach języka C # wynik stackalloc mógł być przechowywany tylko w zmiennej lokalnej wskaźnika. Począwszy od C # 7.2, stackalloc może być teraz używany jako część wyrażenia i może być przeznaczony dla zakresu, a można to zrobić bez użycia niebezpiecznego słowa kluczowego. Tak więc zamiast pisać
Możesz po prostu napisać:
Jest to również niezwykle przydatne w sytuacjach, w których potrzebujesz trochę miejsca na zarysowania do wykonania operacji, ale chcesz uniknąć przydzielania pamięci sterty dla stosunkowo małych rozmiarów
Źródło: C # - All About Span: Exploring a New .NET Mainstay
źródło
Span
niestety nie jest dostępny w .NET framework 4.7.2, a nawet nie w 4.8 ... Tak więc nowa funkcja językowa jest w tej chwili ograniczona.Jest kilka świetnych odpowiedzi na to pytanie, ale chcę tylko na to zwrócić uwagę
Stackalloc może również służyć do wywoływania natywnych interfejsów API
Wiele funkcji natywnych wymaga, aby obiekt wywołujący przydzielił bufor w celu uzyskania zwracanego wyniku. Na przykład funkcja CfGetPlaceholderInfo w
cfapi.h
ma następujący podpis.Aby wywołać to w C # przez interop,
Możesz skorzystać z stackalloc.
źródło