Thread View: pl.comp.lang.c
8 messages
8 total messages
Started by RW
Sun, 03 Jan 2016 21:37
std::shared_ptr<N>(new N) vs std::make_shared<N>()
Author: RW
Date: Sun, 03 Jan 2016 21:37
Date: Sun, 03 Jan 2016 21:37
18 lines
2222 bytes
2222 bytes
Mam taki problem: klasa N bedzie duza (sizeof(N) ~ 100, plus jeszcze dodatkowe alokacje na stercie). Obiektow klasy N bedzie duzo (miliony), beda przechowywane w roznych kontenerach poprzez std::shared_ptr, beda zawieraly w sobie wskazniki shared_ptr i weak_ptr (zeby nie dopuscic do powstanie zamknietych cykli wskaznikow) do innych obiektow klasy N. Wiem ze std::make_shared<N> utworzy mi troche mniejszy obiekt, ale za to czesc pamieci zostanie zdealokowana dopiero wtedy kiedy ostatni weak_ptr wskazujacy na obiekt zostanie zniszczony (czyli mam memory leak). Tworzenie obiektu przez std::shared_ptr<N>(new N) unika tego zagrozenia, ale za to zuzywa nieco wiecej pamieci (ile?). Moje pytanie: co jest w sytuacji lepsze? Czy w ogole powinienem zrezygnowac z shared_ptr i np. zaczac samemu zarzadzac czasem zycia tych obiektow? Myslalem o wektorach std::vector<std::unique_ptr<N>> i przekazywaniu w kodzie referencji / indeksow do elementow tych wektorow. RW
Re: std::shared_ptr<N>(new N) vs std::make_shared<N>()
Author: Sebastian Biały
Date: Sun, 03 Jan 2016 21:40
Date: Sun, 03 Jan 2016 21:40
10 lines
1445 bytes
1445 bytes
On 2016-01-03 22:37, RW wrote: > Moje pytanie: co jest w sytuacji lepsze? Czy w ogole powinienem zrezygnowac > z shared_ptr i np. zaczac samemu zarzadzac czasem zycia tych obiektow? Zacznij od boost::intrusive_ptr i zobacz czy overheat na jednego inta więcej w obiekcie to jest jakiś problem. Natomiast w pewnych sytuacjach może się okazać że prawidłowy pool allokator sprawdzi się znakomicie (razem z boost::intrusive_ptr można zrobić ciekawe zarządzanie *grupą* obiektów).
Re: std::shared_ptr<N>(new N) vs std::make_shared<N>()
Author: Roman W
Date: Sun, 03 Jan 2016 22:57
Date: Sun, 03 Jan 2016 22:57
9 lines
1632 bytes
1632 bytes
On Sun, 3 Jan 2016 22:40:46 +0100, Sebastian Biały<heby@poczta.onet.pl> wrote: > Zacznij od boost::intrusive_ptr i zobacz czy overheat na jednego inta > więcej w obiekcie to jest jakiś problem. A co z weak pointers? RW
Re: std::shared_ptr<N>(new N) vs std::make_shared<N>()
Author: Sebastian Biały
Date: Sun, 03 Jan 2016 23:25
Date: Sun, 03 Jan 2016 23:25
40 lines
2587 bytes
2587 bytes
On 2016-01-03 23:57, Roman W wrote:
>> Zacznij od boost::intrusive_ptr i zobacz czy overheat na jednego
> inta
>> więcej w obiekcie to jest jakiś problem.
> A co z weak pointers?
Zamiast nich masz raw pointers. raw_ptr zamienia się w intrusive wprost
(konstruktor). Tak samo możesz zamienić this na intrusive na siebie (a
więc emulować shared_from_this) Tracisz funckjonalnośc obserwatora bo
raw nie wie że jest zwolniony, ale za to masz lightweight smart_ptr.
Innymi słowy:
class A
{
...
intrusive_ptr< A > m_child;
A* m_parent;
...
};
Tak więc do czasu aż nie potrzebujesz aby weak_ptr czasem zwrócil null
to intrusive_ptr praktycznie zastępuje smart_ptr przy znacznie mniejszym
obciązeniu.
Używam na codzień obu i kod wyraźnie przyspiesza po zamianie shared_ptr
na intrusive_ptr (zysk na zbednych allokacjach refcounterów). Intrusive
pozwala też na obłąkane sztuczki z gatunku jeden refcounter na grupę.
Intrusive_ptr mają tez wady:
a) jesli trzymasz je jako pola w klasach to albo inkludujesz wlaściwe
nagłowki albo tworzysz pusty destruktor w cpp (sposob zwalniania i_ptr
musi być znany na etapie zwalniania klasy zawierającej)
b) intrusive nie ma magicznego deletera, więc polimorficzne klasy muszą
mieć zazwyczaj wirtualne destruktory. shared_ptr wybacza znacznie
więcej, w intrusive dostaniesz zabawne błędy na tygodnie debugowania.
Mimo tych wad intrusive_ptr jest pierwszym co powinienes zrobić aby
poprawić wydajnośc/mem footprint. Bo prawie nie wymaga zmian w kodzie.
Re: std::shared_ptr<N>(new N) vs std::make_shared<N>()
Author: keiichi
Date: Mon, 04 Jan 2016 16:57
Date: Mon, 04 Jan 2016 16:57
15 lines
1752 bytes
1752 bytes
W dniu 2016-01-03 o 22:37, RW pisze: > Wiem ze std::make_shared<N> utworzy mi troche mniejszy obiekt, ale za to > czesc pamieci zostanie zdealokowana dopiero wtedy kiedy ostatni weak_ptr > wskazujacy na obiekt zostanie zniszczony (czyli mam memory leak). > Tworzenie obiektu przez std::shared_ptr<N>(new N) unika tego zagrozenia, > ale za to zuzywa nieco wiecej pamieci (ile?). Mógłbyś sprecyzować co masz na myśli pisząc „trochę mniejszy obiekt”? Obiekt to obiekt i zawsze zajmuje tyle samo, czyli sizeof N. Masz na myśli to, że make_shared może (ale nie musi) przydzielić pamięć na właściwy obiekt i blok kontrolny obiektu za pomocą jednej alokacji pamięci, natomiast new + konstruktor zawsze użyje dwóch alokacji? O memory leaku to już w ogóle nie zrozumiałem… Pozdrawiam
Re: std::shared_ptr<N>(new N) vs std::make_shared<N>()
Author: RW
Date: Mon, 04 Jan 2016 19:06
Date: Mon, 04 Jan 2016 19:06
25 lines
2456 bytes
2456 bytes
On Mon, 04 Jan 2016 17:57:34 +0100, keiichi wrote: > W dniu 2016-01-03 o 22:37, RW pisze: >> Wiem ze std::make_shared<N> utworzy mi troche mniejszy obiekt, ale za >> to czesc pamieci zostanie zdealokowana dopiero wtedy kiedy ostatni >> weak_ptr wskazujacy na obiekt zostanie zniszczony (czyli mam memory >> leak). Tworzenie obiektu przez std::shared_ptr<N>(new N) unika tego >> zagrozenia, >> ale za to zuzywa nieco wiecej pamieci (ile?). > > Mógłbyś sprecyzować co masz na myśli pisząc „trochę mniejszy obiekt”? Chodzi o calkowity rozmiar pamieci alokowanej przez dany sposob tworzenia oibektu na stercie. > Obiekt to obiekt i zawsze zajmuje tyle samo, czyli sizeof N. Masz na > myśli to, że make_shared może (ale nie musi) przydzielić pamięć na > właściwy obiekt i blok kontrolny obiektu za pomocą jednej alokacji > pamięci, natomiast new + konstruktor zawsze użyje dwóch alokacji? > O memory leaku to już w ogóle nie zrozumiałem… Patrz tu: http://stackoverflow.com/questions/13535827/do-stdweak-ptrs- affect-when-the-memory-allocated-by-stdmake-shared-is-deallo RW
Re: std::shared_ptr<N>(new N) vs std::make_shared<N>()
Author: keiichi
Date: Wed, 06 Jan 2016 21:16
Date: Wed, 06 Jan 2016 21:16
48 lines
3320 bytes
3320 bytes
W dniu 2016-01-04 o 20:06, RW pisze: > On Mon, 04 Jan 2016 17:57:34 +0100, keiichi wrote: > >> W dniu 2016-01-03 o 22:37, RW pisze: >>> Wiem ze std::make_shared<N> utworzy mi troche mniejszy obiekt, ale za >>> to czesc pamieci zostanie zdealokowana dopiero wtedy kiedy ostatni >>> weak_ptr wskazujacy na obiekt zostanie zniszczony (czyli mam memory >>> leak). Tworzenie obiektu przez std::shared_ptr<N>(new N) unika tego >>> zagrozenia, >>> ale za to zuzywa nieco wiecej pamieci (ile?). >> >> Mógłbyś sprecyzować co masz na myśli pisząc „trochę mniejszy obiekt”? > > Chodzi o calkowity rozmiar pamieci alokowanej przez dany sposob tworzenia > oibektu na stercie. Dobra, chyba rozumiem o co chodzi. Można odpowiedzieć, że i tak, i nie. Bez względu na sposób tworzenia „użytecznej” pamięci zostanie przydzielone tyle samo. Przykładowo zakładając 100 B na sam obiekt, 8 B na blok kontrolny shared_ptr i wyrównanie do 16 B przy każdej alokacji, kompilator przydzieli przy new + konstruktor 112 + 16 = 128 B w dwóch częściach, a przy make_shared też 128 B, ale w jednej części. Czyli efektywnie tyle samo. Jeśli jednak mówiąc całkowity rozmiar na stercie masz na myśli pamięć łącznie z „magią kompilatora” na obsługę samej sterty, to oczywiście dwie alokacje zajmą więcej. Ale to tak samo jak alokacja 64 razy po 160 B w porównaniu do 10 kb na raz. Też zajmie więcej rzeczywistej pamięci, mimo że w obu przypadkach efektywnie dla programu masz zawsze 10 kB. Ile więcej, to już zależy od konkretnego kompilatora i systemu i nie ma na nie prostej odpowiedzi. >> O memory leaku to już w ogóle nie zrozumiałem… > > Patrz tu: http://stackoverflow.com/questions/13535827/do-stdweak-ptrs- > affect-when-the-memory-allocated-by-stdmake-shared-is-deallo Jeśli zwolnienie pamięci dopiero w momencie zniszczenia wszystkich weak_prt nazywasz memory leakiem, to tak. Przy jednej alokacji (make_shared) pamięć na obiekt i blok kontrolny będzie zwolniona dopiero, gdy zakończą życie wszystkie weak_ i shared_ptr. Sam obiekt oczywiście zostanie zniszczony już przy końcu ostatniego shared_ptr. Zostanie po nim tylko nieużywana, ale przydzielona już pamięć. > > RW > Pozdrawiam
Re: std::shared_ptr<N>(new N) vs std::make_shared<N>()
Author: RW
Date: Thu, 07 Jan 2016 21:52
Date: Thu, 07 Jan 2016 21:52
41 lines
3234 bytes
3234 bytes
On Wed, 06 Jan 2016 22:16:42 +0100, keiichi wrote: > W dniu 2016-01-04 o 20:06, RW pisze: >> On Mon, 04 Jan 2016 17:57:34 +0100, keiichi wrote: >> >>> W dniu 2016-01-03 o 22:37, RW pisze: >>>> Wiem ze std::make_shared<N> utworzy mi troche mniejszy obiekt, ale za >>>> to czesc pamieci zostanie zdealokowana dopiero wtedy kiedy ostatni >>>> weak_ptr wskazujacy na obiekt zostanie zniszczony (czyli mam memory >>>> leak). Tworzenie obiektu przez std::shared_ptr<N>(new N) unika tego >>>> zagrozenia, >>>> ale za to zuzywa nieco wiecej pamieci (ile?). >>> >>> Mógłbyś sprecyzować co masz na myśli pisząc „trochę mniejszy obiekt”? >> >> Chodzi o calkowity rozmiar pamieci alokowanej przez dany sposob >> tworzenia oibektu na stercie. > > Dobra, chyba rozumiem o co chodzi. > Można odpowiedzieć, że i tak, i nie. Bez względu na sposób tworzenia > „użytecznej” pamięci zostanie przydzielone tyle samo. OK. To ciekawe, bo jak sprawdzalem w VS 2015, to make_shared zuzywalo ciut mniej pamieci, widac VS podaje calkowity rozmiar zajety na stercie. >>> O memory leaku to już w ogóle nie zrozumiałem… >> >> Patrz tu: http://stackoverflow.com/questions/13535827/do-stdweak-ptrs- >> affect-when-the-memory-allocated-by-stdmake-shared-is-deallo > > Jeśli zwolnienie pamięci dopiero w momencie zniszczenia wszystkich > weak_prt nazywasz memory leakiem, to tak. Przy jednej alokacji > (make_shared) pamięć na obiekt i blok kontrolny będzie zwolniona > dopiero, gdy zakończą życie wszystkie weak_ i shared_ptr. Sam obiekt > oczywiście zostanie zniszczony już przy końcu ostatniego shared_ptr. > Zostanie po nim tylko nieużywana, ale przydzielona już pamięć. Czyli ewentualnie oplaca sie "masywna" czesc obiektu wydzielic do pod- struktury trzymanej przez unique_ptr? RW
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads