Zajmuje się głownie programowaniem w C# . Szczegółowo zacząłem studiować C++ od niedawna
W jednej z książek wyczytałem, że funkcja push_back klasy vector świetnie nadaje się do wczytywania danych z dysku bajt po bajcie..
Mam poważne **wątpliwości odnośnie wydajności **bo wiem jak to jest zrobione w klasie List<T> na platformie NET. Przeglądałem też pobieżnie kody źródłowe klasy VECTOR
Czy ktoś wie więcej na ten temat ?
Jakież to wątpliwości masz?
@Zimny Krawiec: No ale vector
jest całkiem inaczej skonstruowany niż List
. Weź dokumentacje i zobacz jakie są wytyczne co do wydajności różnych operacji:
https://en.cppreference.com/w/cpp/container/vector/push_back
No i możesz sam zrobić trochę benchmarków, to się przekonasz...
PS. Ale w ogóle wczytywanie po bajcie to nie wiem czy jest najlepszy pomysł... Choć pewnie bufory biblioteczne i systemowe pomogą.
@kq: Ja sobie to tak wyobrażam że niezależnie od języka miejsce w którym są przechowywane dane musi być jakimś ciągłym obszarem pamięci a nie luźno rozsypanymi danymi jak na dysku półprzewodnikowym. A skoro tak jest jak ja przypuszczam . To trzeba albo wcześniej zarezerwować jakiś większy obszar pamięci a potem jak zabraknie miejsca trzeba utworzyć nowy większy bufor i dane przepisać. Tak jest na platformie NET.
@Zimny Krawiec: Ale vector
ma dane w ciągłym obszarze... Natomiast tak być nie musi, w każdym języku mogą być takie i owakie struktury -- i ciągłe i rozsypane...
@koszalek-opalek: A na czy polegają główne różnice między klasą vector a List na platformie NET.
https://code.woboq.org/llvm/libcxx/include/vector.html#_ZNKSt3__16vectorIbT_E11__recommendENS_16allocator_traitsIS1_E9size_typeE - vector
https://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,cf7f4095e4de7646 - LIST<T>
Co jest elementem listy?
A) jeden znak
B) jedna linia pliku
C) caly plik
List<T>
prawdopodobnie jest odpowiednikiem std::vector
, ale nie czytalem zrodel obu...
@Zimny Krawiec: Przeczytałem źródła, wygląda, że są bardzo podobne (przynajmniej Add
i push_back
), ale spróbuj zrobić benchmarki...
@Zimny Krawiec: jak potrzebujesz żeby to było wydajne to zmierz. Jeśli nie potrzebujesz jeszcze - nie martw się na zapas.
Ale skoro to aż taki problem, to podpowiem, że po coś tam jest metoda reserve ;)
Dużo tutaj było powiedziane, ale nadal nie rozumiem jaki jest problem z realokacją co jakiś czas? I tak wielkość alokacji jest podwajana jak braknie miejsca, tym samym powodując że stracisz max 2x pamięci. Przy ciągłych push_backach, koszt czasowy się amortyzuje do stałego. A jeśli zmierzyłeś, że masz potrzebę ominięcia tych realokacji, jak już było zauważone, można użyć reserve (czy też innych, jak chcesz skrócić wektor a nie wydłużyć).
Z dysku nie da się wczytać 1 bajta, zawsze wczytuje się jeden sektor 512 bajtów minimum i potem masz abstrakcję, która ci podaje buffor jako formę dysku, ale już w pamięci ram, i z poziomu C po prostu jeśli będziesz chciał więcej niż te 512 to ci doczyta z tego dysku, kolejny sektor.
Ale w C masz seek i możesz sobie ustawić pozycję w buforze od którego bajta ma wczytywać.
Ale jaki w ogóle sens wczytywać dane z dysku "bajt po bajcie"? Jeśli czytamy z dysku pojedyncze bajty i każdy bajt osobno będzie trafiał do vectora za pomocą push_back to to rzeczywiście będzie powolne. Ale tak się nie robi. Jak masz do odczytania N bajtów to przekaż to N do fread czy do ifstream::read i czytaj N bajtów, a nie N razy po bajcie.
W vectorze mozna swoja droga zarezerowac pamiec. Mowimy mu ze pewnie bedzie mial z 1000 elementow (vect.reserve(1000)
czy jakos tak) wiec realokacja sie przestaje dziac :)
już tradycyjnie: należy użyć file mapping zamiast vector, hahaha!
i nie potrzeba żadnej rezerwacji, realokacji, ani nawet demokracji!