Название: Memory issues Отправлено: Igors от Сентябрь 13, 2009, 21:50 Добрый вечер
Обнаружил проблему с памятью на своей платформе (Mac). Не хочу "предъявлять претензий" (все равно решать самому :)) но сообщить о проблеме по-моему надо. ---------------------------- Hello Qt I've got a problem with QList memory allocation. Platform: Mac OSX 10.5.2 Qt versioion: 4.5.2 (Carbon) Problem description: memory is not released as it's expected. The listing is: Код: #include <QtCore/QCoreApplication> However, the Activity Monitor shows no memory released at point "2" (see screenshot). Using several such QList(s) I have qFatal (no memory exception) very fast. Looking source codes I can guess the problem is related with using ::realloc that does not release memory in fact. Thank you Igor & Igor (Russian Qt forum) --------------------- Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 14, 2009, 10:33 Добрый вечер Деструктор Qlist в точке 2 еще не отработал, поэтому и память не отдал.Обнаружил проблему с памятью на своей платформе (Mac). Не хочу "предъявлять претензий" (все равно решать самому :)) но сообщить о проблеме по-моему надо. Название: Re: Memory issues Отправлено: Tonal от Сентябрь 14, 2009, 10:43 Кроме того, в точке 2 не вызывался деструктор QCoreApplication-а, а так же деструкторы глобальных и статических объектов, которые вызавутся только после окончания работы main.
Так что пока нужно учить язык а не багрепорты отправлять. :) Название: Re: Memory issues Отправлено: Igors от Сентябрь 14, 2009, 11:35 Деструктор Qlist в точке 2 еще не отработал, поэтому и память не отдал. Деструктор здесь ни при чем. Я сказал контейнеру выкинуть половину элементов, но это не освободило часть памяти - занято столько же. Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 14, 2009, 12:32 Деструктор Qlist в точке 2 еще не отработал, поэтому и память не отдал. Деструктор здесь ни при чем. Я сказал контейнеру выкинуть половину элементов, но это не освободило часть памяти - занято столько же. Note that the internal array only ever gets bigger over the life of the list. It never shrinks. The internal array is deallocated by the destructor and by the assignment operator, when one list is assigned to another. Название: Re: Memory issues Отправлено: Igors от Сентябрь 14, 2009, 13:00 http://qt.nokia.com/doc/main-snapshot/qlist.html Оба-нв! Спасибо, я это просмотрел. Хорошо что запостил сначала здесь :)Note that the internal array only ever gets bigger over the life of the list. It never shrinks. The internal array is deallocated by the destructor and by the assignment operator, when one list is assigned to another. Но у меня и QVector не освобождает Код: #include <QtCore/QCoreApplication> Спасибо Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 14, 2009, 13:11 Есть ли какой-то контейнер который память нормально отдает? Не всегда можно память просто так отдать, если она большими кусками выделяется. Например, в стандартных stl-аллокаторах метода realloc нет. Для этого надо выделить новый кусок, скопировать туда то, что нужно сохранить, затем отдать весь старый кусок.Спасибо То есть заводишь временный контейнер, делаешь qSwap с используемым, затем, если такой метод есть, делаешь reserve с нужным новым размером контейнера, и копируешь туда что надо из старого. Все это делаешь в отдельном scope {}, чтобы при выходе из него память из временного объекта освободилась. Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 13:13 При реализации подобных списков, обычно имеем:
- Count - кол-во элементов в списке - Capacity - кол-во места под элементы списка При добавлении элементов проверяется кол-во доступного места и при нехватке делается переаллокация обычно с запасом. При удалении элементов кол-во доступного места под элементы не сокращается, соответственно память не освобождается. Обычно для уменьшения кол-ва выделенной памяти (Capacity == Count или Capacity = Value) делается специальный метод. Насколько я понял в QList его нет и это очень плохо! У QVector смотри: void QVector::squeeze () int QVector::capacity () const void QVector::reserve ( int size ) Название: Re: Memory issues Отправлено: Igors от Сентябрь 14, 2009, 13:25 Для полноты картины (мол, чем проверяешь и можно ли этому верить).
Код: #define NUM_TEST (200LL * 1024 * 1024) Код: [Session started at 2009-09-14 13:11:02 +0300.] Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 14, 2009, 13:58 А так если?
Код
Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 14:01 Так работает
Код
Так падает Код хотя до theVector1->reserve - Mem Usage & VM Size < 10MB после theVector1->reserve - Mem Usage & VM Size > 700MB а после theVector1->squeeze- Mem Usage & VM Size снова < 10MB Видно что squeeze освобождает память! Не могу понять прикола, в чем разница между этими двумя вариантами? Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 14:21 Как ни странно, но Igors прав! Это явный глюк QVector, осталось понять в чем он заключается.
Тест на моем классе проходит отличнно. sbw::Indices - аналогичен QVector<int> (тоже список int, но без template, полностью своя реализация) Код C Mem Usage & VM Size на соответствующих шагах все точно так же! Но без падения! Название: Re: Memory issues Отправлено: Igors от Сентябрь 14, 2009, 14:29 А так если? Winstrol, я Вас понял, но при этом теряется удобство/простота. Плюс для больших данных неизвестно хватит ли памяти для "переброски". Поэтому я себе соорудил велосипед из chunk'ов :)Название: Re: Memory issues Отправлено: SABROG от Сентябрь 14, 2009, 14:34 Видно что squeeze освобождает память! Не могу понять прикола, в чем разница между этими двумя вариантами? Разница похоже в squeeze, не срабатывает что ли. В первом случае первые 800Мб освобождает delete и второй вектор выделяет снова 800Мб. Во втором случае squeeze похоже ничего не делает в итоге идет попытка откушать память до 1600Мб. Про squeeze() написано, что он освобождает память, которая не требуется для содержания элементов. Есть мысль, что через метод reserve() мы эту память делаем "нужной" для содержания элементов. Возможно нужно делать все-таки clean/erase + resize. Название: Re: Memory issues Отправлено: Igors от Сентябрь 14, 2009, 14:37 Как ни странно, но Igors прав! Это явный глюк QVector, осталось понять в чем он заключается. Из Ваших примеров я не могу понять почему я прав :)На Mac есть подлянка с ::realloc и т.к. Qt его активно использует... Про Вындоуз не знаю. Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 16:02 Видно что squeeze освобождает память! Не могу понять прикола, в чем разница между этими двумя вариантами? Разница похоже в squeeze, не срабатывает что ли. В первом случае первые 800Мб освобождает delete и второй вектор выделяет снова 800Мб. Во втором случае squeeze похоже ничего не делает в итоге идет попытка откушать память до 1600Мб. Единственно в чем может быть разница между QVector<int> и моим sbw::Indices - я не использую realloc! Я создаю новый массив и копирую данные в него через memcpy. Может проблема в использовании realloc в QVector(если он использует именно realloc)? Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 16:04 Как ни странно, но Igors прав! Это явный глюк QVector, осталось понять в чем он заключается. Из Ваших примеров я не могу понять почему я прав :)На Mac есть подлянка с ::realloc и т.к. Qt его активно использует... Про Вындоуз не знаю. Потому что с QVector<int> - глючит А с мим аналогичным классом sbw::Indices - нет. Смотри вверху тесты для QVector<int> и sbw::Indices Да и кстати, я тестировал под Windows, ты на сколько понял тестировал под Mac. Но глюк одинаковый и там и там :( Название: Re: Memory issues Отправлено: Igors от Сентябрь 14, 2009, 16:23 Может проблема в использовании realloc в QVector(если он использует именно realloc)? Файл qmalloc.cppvoid *qRealloc(void *ptr, size_t size) { return ::realloc(ptr, size); } На Mac это память НЕ освобождает, на Вындоуз - не в курсе Название: Re: Memory issues Отправлено: Igors от Сентябрь 14, 2009, 16:34 Да и кстати, я тестировал под Windows, ты на сколько понял тестировал под Mac. Но глюк одинаковый и там и там :( Уточните плз: то есть отот код (theVector[10]) валится и на Вындоуз?И еще одна мелочь: потянет ли на Вындоуз QVector<int> theV; theV.reserve(400 * 1024 * 1024); // то есть > 1Gb На Mac - нет, хотя на борту 4Gb Спасибо Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 17:27 Да и кстати, я тестировал под Windows, ты на сколько понял тестировал под Mac. Но глюк одинаковый и там и там :( Уточните плз: то есть отот код (theVector[10]) валится и на Вындоуз?И еще одна мелочь: потянет ли на Вындоуз QVector<int> theV; theV.reserve(400 * 1024 * 1024); // то есть > 1Gb На Mac - нет, хотя на борту 4Gb Спасибо theV.reserve(400 * 1024 * 1024); - валиться на Windows сразу(Windows XP). Название: Re: Memory issues Отправлено: Igors от Сентябрь 14, 2009, 17:48 Да этот код(приведенный вами) валиться на Windows. И тот упрощенный код(который я приводил) тоже. Ага, спасибо, SpectretheV.reserve(400 * 1024 * 1024); - валиться на Windows сразу(Windows XP). Давайте сочинять баг репорт (vers 2.0)? :) Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 18:30 Да этот код(приведенный вами) валиться на Windows. И тот упрощенный код(который я приводил) тоже. Ага, спасибо, SpectretheV.reserve(400 * 1024 * 1024); - валиться на Windows сразу(Windows XP). Давайте сочинять баг репорт (vers 2.0)? :) Код: int* a; Не помню чтобы что-то подобное было описано в его спецификации(посмотрел сейчас в MSDN и ничего токого не нашел), хотя я им в последний раз пользовался лет 10 назад, поскольку он практически не нужен(так сходу и не придумать нормальной задачи где нужен - оптимален realloc). Название: Re: Memory issues Отправлено: SABROG от Сентябрь 14, 2009, 18:44 Ноги похоже отсюда растут: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove
erase не удаляет ничего, он подчищает мусор, который остается после использования метода remove(). Название: Re: Memory issues Отправлено: BRE от Сентябрь 14, 2009, 18:47 Погонял тесты под linux. Полет нормальный.
Код с двумя векторами работает нормально: захватывает - освобождает. С выделением: theV.reserve(400 * 1024 * 1024); // то есть > 1Gb тоже все Ок. Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 18:48 Ноги похоже отсюда растут: http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove Ноги ростут от кривой работы realloc! Что показано на предыдущем тесте.erase не удаляет ничего, он подчищает мусор, который остается после использования метода remove(). А то что ты привел связано с различием между "Count/Size" и "Capacity/AllocSize" Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 18:55 Погонял тесты под linux. Полет нормальный. 1) Возможно под Linux - realloc работает другим образом?Код с двумя векторами работает нормально: захватывает - освобождает. С выделением: theV.reserve(400 * 1024 * 1024); // то есть > 1Gb тоже все Ок. 2) Скольки разрядный Linux, если 64, то возможно разница в этом? Название: Re: Memory issues Отправлено: BRE от Сентябрь 14, 2009, 19:07 1) Возможно под Linux - realloc работает другим образом? linux - 32bit.2) Скольки разрядный Linux, если 64, то возможно разница в этом? Код Вывод: 0x85fb8008 0x53fb7008 Код Вывод: 0x53ed6008 0x0 Т.е. realloc освобождает блок, malloc пытается захватить такой же, но обламывается т.к. ему не хватает адресного пространства для нового блока (хотя память есть). Вроде все согласно документации. А вот так новый блок выделиться в перераспределенном: Код Вывод: 0x54087008 0x54487008 Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 20:25 Кроче, я тут проконсультировался. Абсолютно гарантировать что все точно так не могу, но схема работы с памятью примерна такова:
1) Программа имеет кучу(heap) 2) Максимальный размер кучи определятся системой. 3) Куча может иметь несколько страниц. 4) Страницы могут имет различный размер. Максимальный/минимальный размер страницы и их кол-во(для программы) видимо определяется процом и системой(не очень точно). 5) При выделении памяти программой идет просмотр страниц(в ее куче), - если в одной из них есть свободный непрерывный кусок, то память выделяется из этой страницы - если ни в одной нет, то идет запрос к системе на добавление страницы достаточного размера(к нашей куче) под запрашиваемый нами непрерывный кусок памяти 6) Память может быть выделена только из одной страницы!!! 7) Страницы памяти самой программой не могут быть объединены!!! Собственно и получаем - последний пример(под Linux от BRE): Код: a = (int*) malloc(400*1024*1024*sizeof(int)); Вот такая фигня :) Название: Re: Memory issues Отправлено: SABROG от Сентябрь 14, 2009, 20:43 Ну вот erase под WindowsXP у меня тоже не сработал (список стал пуст, а память осталась занятой), хотя clean работает идеально. Remove тоже работает, но медленно.
Еще Qt у меня отказалась выделять 800Мб памяти, выдало в консоль "Out of memory". При этом программа на BCB, основанная на обычном std::vector, спокойно выделила 2Гб памяти (в системе всего 1.5Гб ОЗУ). Я так понимаю, чтобы решить проблему это надо в Qt некий аналог дефрагментатора памяти писать? Название: Re: Memory issues Отправлено: spectre71 от Сентябрь 14, 2009, 21:16 Ну вот erase под WindowsXP у меня тоже не сработал (список стал пуст, а память осталась занятой), хотя clean работает идеально. Remove тоже работает, но медленно. Еще Qt у меня отказалась выделять 800Мб памяти, выдало в консоль "Out of memory". При этом программа на BCB, основанная на обычном std::vector, спокойно выделила 2Гб памяти (в системе всего 1.5Гб ОЗУ). Я так понимаю, чтобы решить проблему это надо в Qt некий аналог дефрагментатора памяти писать? Читай топик выше, а лучше внимательно с самого начала, все уже разъяснили! То что ты написал совершенно не относиться к делу, возможно ты не совсем понял о чем было обсуждение. Название: Re: Memory issues Отправлено: SABROG от Сентябрь 14, 2009, 23:59 Читай топик выше, а лучше внимательно с самого начала, все уже разъяснили! То что ты написал совершенно не относиться к делу, возможно ты не совсем понял о чем было обсуждение. Все-таки не понимаю чем радикально отличается clean от erase? Первый работает, второй нет. Название: Re: Memory issues Отправлено: BRE от Сентябрь 15, 2009, 08:24 2) Максимальный размер кучи определятся системой. Максимальный размер кучи зависит от самого процесса, ограничение связано с размером адресного пространства к которому может обращаться процесс. Для 32-битной системы он составляет 4 Gb.Под linux пользовательскому коду предоставляется 3 Gb (0x00000000-0xBFFFFFFF), 1 Gb отводиться для ядра (0xC0000000-0xFFFFFFFF). Под вендой XP (если я правильно помню): 2 Gb - пользователь, 2 Gb - ядро. В пользовательской адресном пространстве расположены: * разделяемые библиотеки (младшие адреса) * код * данные * хип * стек (старшие адреса) Т.е. чем больше кода/данных тем меньше адресного пространства остается хипу, даже если система (с учетом свопа) имеет кучу свободной памяти, больше она процессу предоставить не сможет (т.к. процесс не сможет ее адресовать). Название: Re: Memory issues Отправлено: kuzulis от Сентябрь 15, 2009, 09:27 Фон-неймановские заморочки :)
Название: Re: Memory issues Отправлено: Igors от Сентябрь 15, 2009, 13:32 Добрый день
(просто инфа, может пригодится). Насчет блока > 1 Gb. Ничего не меняется в 64-bits, получаю все тот же NULL. Ничего не меняется и если стоит больше памяти (я эту проблему узнал от пользователя у которого стояло восемь) По поводу баг репорта - по-моему все-таки надо сообщить. В документации ясно сказано: Цитировать void QVector::squeeze () Releases any memory not required to store the items. The sole purpose of this function is to provide a means of fine tuning QVector's memory usage. In general, you will rarely ever need to call this function. Нам память освободить обещали? Да, обещали, более того, прозрачно намекали что, мол, и без этого освободят. Так что пусть освобождают в следующих версиях. А будут они это делать через ::realloc или еще как - это их дело. И QVector там не один такой - все что завязано на ::realloc тоже будет так себя вести Название: Re: Memory issues Отправлено: BRE от Сентябрь 15, 2009, 14:14 По поводу баг репорта - по-моему все-таки надо сообщить. В документации ясно сказано: Не уверен, что это баг. Это фича, причем не Qt, а стратегии распределения памяти конкретной операционной системы.Цитировать void QVector::squeeze () Releases any memory not required to store the items. The sole purpose of this function is to provide a means of fine tuning QVector's memory usage. In general, you will rarely ever need to call this function. Нам память освободить обещали? Да, обещали, более того, прозрачно намекали что, мол, и без этого освободят. Так что пусть освобождают в следующих версиях. А будут они это делать через ::realloc или еще как - это их дело. В любом случае для выделения/перераспределения памяти будут использованы malloc и realloc, а их разработчики Qt переделать уже не смогут. (Кроме случае, если программа при старте будут откушивать всю памяти и потом сама ее распределять. Что будет совсем не гуд). Проще не захватывать непрерывные куски памяти такого размера. Название: Re: Memory issues Отправлено: Igors от Сентябрь 15, 2009, 18:25 Проще не захватывать непрерывные куски памяти такого размера. Это точно, но тогда надо признать: проще не использовать QVector для больших данных, т.к. QVector внутри и есть непрерывный кусок. Контейнер который бы распределял память порциями (вместо одного большого куска) был бы ОЧЕНЬ нужен/полезен. Но я такого не нашел.Название: Re: Memory issues Отправлено: BRE от Сентябрь 15, 2009, 18:34 Контейнер который бы распределял память порциями (вместо одного большого куска) был бы ОЧЕНЬ нужен/полезен. Но я такого не нашел. QList, QMap, QHash.А этим еще и свой аллокатор можно назначить (для повышения эффективности): std::vector, std::list, std::map, std::deque, ... Название: Re: Memory issues Отправлено: SABROG от Сентябрь 15, 2009, 18:36 Для эксперимента хотел попробовать провернуть тоже самое на std::list. Метод max_size() сказал, что я могу поместить в контейнер 357913941 итем типа int. Реально же я попытался выделить память под 100*1024*1024 итемов. В теории это не должно было занять больше 400Мб. На деле программа почему-то кушает до 1,6Гб после чего падает. А после этого компьютер начинает очень дико тормозить на любых операциях, даже если все программы позакрывать и открыть заново. Пришлось перезагружаться, на этом мои эксперименты закончились.
Название: Re: Memory issues Отправлено: BRE от Сентябрь 15, 2009, 18:41 Реально же я попытался выделить память под 100*1024*1024 итемов. В теории это не должно было занять больше 400Мб. Должно было занять больше.std::list это список и по мимо рабочих данных (int value), в элементе для адресации списка нужен как минимум указатель на следующий элемент списка. Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 15, 2009, 18:53 std::list это список и по мимо рабочих данных (int value), в элементе для адресации списка нужен как минимум указатель на следующий элемент списка. Как и на предыдущий.Название: Re: Memory issues Отправлено: Igors от Сентябрь 15, 2009, 19:08 Контейнер который бы распределял память порциями (вместо одного большого куска) был бы ОЧЕНЬ нужен/полезен. Но я такого не нашел. QList, QMap, QHash.А этим еще и свой аллокатор можно назначить (для повышения эффективности): std::vector, std::list, std::map, std::deque, ... Остается QVector (обсудили) и QList - этот немного лучше. Но он бросается сразу делать new (если sizeof(T) > sizeof(void *), иначе тот же QVector) для каждого нового элемента :-[ А это не очень подходит, да и памяти отъест. Вот и получается - проще самопальный контейнер писать :) Название: Re: Memory issues Отправлено: BRE от Сентябрь 15, 2009, 19:11 Вот и получается - проще самопальный контейнер писать :) А stl-ные контейнеры?Быстрее и эффективней Qt-ишных. Почему не использовать их? Название: Re: Memory issues Отправлено: SABROG от Сентябрь 15, 2009, 21:41 А мне кажется, что программа плохо спроектировна, если ей требуется столько оперативной памяти. Если винда полезет в своп, то на то и выйдет, что ты чанки будешь читать с винта, что из памяти, скорость будет та же.
С удовольствием почитал бы, почему Qtшные контейнеры хуже STL'ных. Кстати чьей реализации? Они по-разному работают с памятью. Я не знаю, является ли QList аналогом std::list, но я четко вижу, что QList кушает как и положено не больше 500Мб при попытке поместить в контейнер ~100млн. int'ов, в то время как std::list'у при аналогичном коде не хватает 1,6Гб съеденной оперативы после чего программа падает, даже не ругнувшись в отладчик о нехватке памяти. Название: Re: Memory issues Отправлено: BRE от Сентябрь 15, 2009, 21:54 С удовольствием почитал бы, почему Qtшные контейнеры хуже STL'ных. Кстати чьей реализации? Они по-разному работают с памятью. Не знаю где про это можно почитать, это мое мнение после тестовых прогонов.Про QStack и std::stack разговор на crossplatform помнишь? На моей машине QStack из-за того что он реализован на базе QVector, проигрывает std::stack (сделанного на базе deque) точно не помню но примерно в 12 раз. Недавнии тесты QMap и std::map уверенно показывают, что QMap проигрывает в скорости. Зачем искать, что почитать - проверь сам? Я не знаю, является ли QList аналогом std::list, но я четко вижу, что QList кушает как и положено не больше 500Мб при попытке поместить в контейнер ~100млн. int'ов, Ты уверен?Сегодня завтра посмотрю, но пока для меня это выглядит фантастикой. ;) Название: Re: Memory issues Отправлено: BRE от Сентябрь 15, 2009, 22:22 Посмотрел.
Сравнивались QList и std::deque. В список вставлялись 100 * 1024 * 1024 элементов int. Process 1 (QList) Time elapsed: 3207 ms Process 2 (std::deque) Time elapsed: 2674 ms QList не является связанным списком, это массив указателей на T, т.е. его прямой аналог std::vector<T*>. Название: Re: Memory issues Отправлено: SABROG от Сентябрь 16, 2009, 08:46 Тут, как я понял, не правильно сравнивать контейнеры только по скорости добавления элементов. По идее у std::list должны быть быстрее операции удаления и добавления в произвольное место списка.
Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 08:53 Тут, как я понял, не правильно сравнивать контейнеры только по скорости добавления элементов. По идее у std::list должны быть быстрее операции удаления и добавления в произвольное место списка. Согласен, но как я написал выше, QList<T> это std::vector<T*>. А что бы сравнить скорости нужно писать функционал вставки/удаления в произвольном месте для std::vector<T*>, а мне лениво. :)Сейчас еще посмотрю, но по моему для T <= (void*), QList вообще превращается std::vector<T>. Название: Re: Memory issues Отправлено: Igors от Сентябрь 16, 2009, 09:53 QList не является связанным списком, это массив указателей на T, т.е. его прямой аналог std::vector<T*>. Да если sizeof(T) > sizeof(void *), иначе это аналог std::vector<T>. (::isLarge в исходниках). Это разумно, незачем тратить указатель например на int который сам <= указателяНазвание: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 09:56 Да если sizeof(T) > sizeof(void *), иначе это аналог std::vector<T>. (::isLarge в исходниках). Это разумно, незачем тратить указатель например на int который сам <= указателя Ну я вроде выше и писал. :)Название: Re: Memory issues Отправлено: Igors от Сентябрь 16, 2009, 10:07 А stl-ные контейнеры? Я не берусь утверждать кто из них быстрее/эффективней. И с удовольствием пользуюсь STL, намного меньше писать. Просто не везде он подходит. НапримерБыстрее и эффективней Qt-ишных. Почему не использовать их? struct Point { float x, y, z; }; Для такого элемента неэффективно использовать new и создавать служебные данные (которые превысят начальный размер). Остается std::vector но он страдает теми же недостатками что и QVector. Проще написать свой класс - невеликое дело. Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 10:12 Проще написать свой класс - невеликое дело. Для таких данных, по мне, проще написать свой аллокатор.Также для таких классов удобно переопределить оператор new, для более эффективного их хранения. Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 16, 2009, 10:20 Вот и получается - проще самопальный контейнер писать :) А stl-ные контейнеры?Быстрее и эффективней Qt-ишных. Почему не использовать их? Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 16, 2009, 10:24 Я не знаю, является ли QList аналогом std::list, но я четко вижу, что QList кушает как и положено не больше 500Мб при попытке поместить в контейнер ~100млн. int'ов, в то время как std::list'у при аналогичном коде не хватает 1,6Гб съеденной оперативы после чего программа падает, даже не ругнувшись в отладчик о нехватке памяти. Скорее всего, реализация вызывает new/delete на каждый чих.Для наглядности можно поэкспериментировать с таким фрагментом. Код В этой ситуации надо -отказаться от использования std::allocator, заменив на какой-нибудь small object allocator. -во все том же stlport используется достаточно пристойный node allocator. Название: Re: Memory issues Отправлено: SABROG от Сентябрь 16, 2009, 11:55 +1 Никогда не понимал порнографии вроде Qlist. Причем hardcore. А обычный std::list тоже thread safe, implicit shared и reentrant? вставки/удаления в произвольном месте для std::vector<T*>, а мне лениво. :) В Qt есть не все контейнеры как в stl, но есть еще тот же QLinkedList. Говорить, что контейнеры Qt медленнее, сравнивая лишь по одной операции добавления и по 1-2ум контейнерам не лень, а делать тесты лень. Если в Qt что-то хуже или работает не так, почему бы не спросить троллей как правильно или чтобы это исправили? Я понимаю, что всем надо в срок уложиться, сдать заказ и времени клепать багрепорты нет, легче выбрать что-то другое. Но ведь проблема никуда не пропадет, если вы о ней не сообщите. Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 12:17 В Qt есть не все контейнеры как в stl, но есть еще тот же QLinkedList. Говорить, что контейнеры Qt медленнее, сравнивая лишь по одной операции добавления и по 1-2ум контейнерам не лень, а делать тесты лень. Я написал о том, с чем столкнулся в недалеком прошлом сам. Я не занимался специальным тестированием контейнеров.Если в Qt что-то хуже или работает не так, почему бы не спросить троллей как правильно или чтобы это исправили? Я понимаю, что всем надо в срок уложиться, сдать заказ и времени клепать багрепорты нет, легче выбрать что-то другое. Но ведь проблема никуда не пропадет, если вы о ней не сообщите. Да я если честно языкам не обучен. :)Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 16, 2009, 12:44 А обычный std::list тоже thread safe, implicit shared и reentrant? И std::list и Qlist не thread-safe.Что касается implicit shared, особой пользы от этого не вижу. А если надо, то всегда легко сделать explicit sharing Код Если собираемся менять sharedObj, то делаем. Код
Название: Re: Memory issues Отправлено: Igors от Сентябрь 16, 2009, 13:02 Если в Qt что-то хуже или работает не так, почему бы не спросить троллей как правильно или чтобы это исправили? Я понимаю, что всем надо в срок уложиться, сдать заказ и времени клепать багрепорты нет, легче выбрать что-то другое. Но ведь проблема никуда не пропадет, если вы о ней не сообщите. Да я если честно языкам не обучен. :)Предлагаю: -------------------- Hello Qt We've got a problem. The following fragment runs out of memory under Windows XP and Mac OSX 10.5.2 (Carbon) although memory is released Ok under Linux Код: #define NUM_TEST (200LL * 1024 * 1024) Thank you Russian Qt Forum --------------------- Так пойдет? Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 16, 2009, 13:06 Looking sources files we can guess the problem is related with ::realloc that does not release memory in fact Стало быть и отсылать надо команде разработчиков realloc.Название: Re: Memory issues Отправлено: Igors от Сентябрь 16, 2009, 13:12 Стало быть и отсылать надо команде разработчиков realloc. А кто их заставлял пользоваться realloc? И realloc ли это вообще? (не 100%). И почему мы имеем разные результаты на разных платформах? У BRE работает у меня нет. Что это за кросс-платформенность такая? Обещали по squeeze память освобождать - вот пусть и освобождают.Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 13:12 Стало быть и отсылать надо команде разработчиков realloc. +1. :)Я уже писал, но повторюсь. Это не проблема Qt, это проблема (а точнее особенность) стратегии менеджера памяти конкретной OS. Тролли эту проблему/особенность обойти не смогут. Конечно, можно написать репорт. Только ответ скорее всего будет один: для конкретной задачи нужно подбирать правильный контейнер, учитывая его особенности. Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 13:14 И почему мы имеем разные результаты на разных платформах? Ограничения конкретной платформы.У BRE работает у меня нет. Что это за кросс-платформенность такая? Обещали по squeeze память освобождать - вот пусть и освобождают. Если я увеличу количество элементов, у меня возникнут такие же проблемы. Название: Re: Memory issues Отправлено: Igors от Сентябрь 16, 2009, 13:20 Я уже писал, но повторюсь. Это не проблема Qt, это проблема (а точнее особенность) стратегии менеджера памяти конкретной OS. Тролли эту проблему/особенность обойти не смогут. Откуда мы с Вами знаем чего они могут/не могут? Мы здесь в роли пользователей, наше дело сообщатьКонечно, можно написать репорт. Ладно, не надо - так не надо :)Только ответ скорее всего будет один: для конкретной задачи нужно подбирать правильный контейнер, учитывая его особенности. Название: Re: Memory issues Отправлено: SABROG от Сентябрь 16, 2009, 13:34 И std::list и Qlist не thread-safe. А написано, что все контейнеры Qt thread-safe. Цитировать In addition, they are thread-safe in situations where they are used as read-only containers by all threads used to access them. Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 16, 2009, 13:53 А написано, что все контейнеры Qt thread-safe. Цитировать In addition, they are thread-safe in situations where they are used as read-only containers by all threads used to access them. Тут идет речь о basic thread-safety. Т.е. безопасных одновременных вызовах const методов. Для list естественно это тоже справедливо, хотя текущий стандарт языка, частью которого является stl, про потоки ничего не знает. http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2669.htm Цитировать Thread-Safety in the Standard Library (Rev 2) ... Basic thread-safety guarantee The basic thread-safety guarantee would be that standard library functions are required to be reentrant, and non-mutating uses of objects of standard library types are required to not introduce data races. This has little or no impact on performance. It does actually deliver the promised safety. Thus this basic thread-safety guarantee is required of implementations. Strong thread-safety guarantee The strong thread-safety guarantee would be that mutating uses of objects of standard library types are required to not introduce data races. This would have a severe negative impact on performance. Furthermore, real safety often requires locking across several member function calls, so providing per function-call locking would create a illusion of safety that did in fact not exist. For these reasons, a blanket strong thread-safety guarantee for mutating shared objects is not provided, and constraints are put on programs accordingly. Название: Re: Memory issues Отправлено: kuzulis от Сентябрь 16, 2009, 14:04 Цитировать Обещали по squeeze память освобождать - вот пусть и освобождают. +500И архитектура ОС тут не причем! Всё должно одинаково/аналогично работать на разных платформах.. Название: Re: Memory issues Отправлено: Igors от Сентябрь 16, 2009, 14:10 Тут идет речь о basic thread-safety. Т.е. безопасных одновременных вызовах const методов. Для list естественно это тоже справедливо, хотя текущий стандарт языка, частью которого является stl, про потоки ничего не знает. Я с этим не работал но мне это интересно. Нельзя ли это как-то выделить в новую тему и обсудить более подробно?Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 14:15 Цитировать Обещали по squeeze память освобождать - вот пусть и освобождают. +500И архитектура ОС тут не причем! Всё должно одинаково/аналогично работать на разных платформах.. И на всех платформах все работает одинаково. Что могут сделать Тролли, если для процесса в linux отдается 3 Гб, а в венде 2. Это особенности ОС. Название: Re: Memory issues Отправлено: Igors от Сентябрь 16, 2009, 16:31 Камрады, squeeze освобождает. Проверяю на в 10 раз меньших блокахИ на всех платформах все работает одинаково. Что могут сделать Тролли, если для процесса в linux отдается 3 Гб, а в венде 2. Это особенности ОС. Код: #define NUM_TEST (20 * 1024 * 1024) Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 19:56 Igors, попробуй на Мас такой код:
Код В linux точно (в венде я думаю тоже), v2 выделяется в адресном пространстве, которое раньше принадлежало v1. Т.е. squeeze нормально отдает память. Код А этот код показывает как будет мигрировать непрерывный кусок памяти по адресному пространству, пока не исчерпает его. Вроде все логично и предсказуемо. Название: Re: Memory issues Отправлено: Авварон от Сентябрь 16, 2009, 21:29 1й код
Код: ASSERT failure in QVector<T>::operator[]: "index out of range", file /Library/Frameworks/QtCore.framework/Headers/qvector.h, line 337 macbook, 4ГБ ОП на борту Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 21:37 1й код А на каком qDebug падает: первом или втором?Код: ASSERT failure in QVector<T>::operator[]: "index out of range", file /Library/Frameworks/QtCore.framework/Headers/qvector.h, line 337 macbook, 4ГБ ОП на борту :o ??? Название: Re: Memory issues Отправлено: Авварон от Сентябрь 16, 2009, 21:45 вывод приложения я привел) на 1м видимо в v1[ 99999 ]
added: так, стоп, я ушел курить, почему она всегда падает О_о added2: то ли место не резервируется, то ли я криворук Название: Re: Memory issues Отправлено: BRE от Сентябрь 16, 2009, 22:17 вывод приложения я привел) на 1м видимо в v1[ 99999 ] reserve только резервирует место, но не увеличивает размер вектора (v1.size() == 0).added: так, стоп, я ушел курить, почему она всегда падает О_о added2: то ли место не резервируется, то ли я криворук У тебя скорее всего используется debug версия Qt и там отрабатывает Q_ASSERT_X. Вместо reserve попробуй использовать resize. Новая версия тестовой программы (показывает точную область с учетом capacity()): Код
Название: Re: Memory issues Отправлено: Igors от Сентябрь 17, 2009, 11:09 Igors, попробуй на Мас такой код: На Вашей платформе - да. На моей - нет. Я немного добавил кода чтобы избежать "out of range"... В linux точно (в венде я думаю тоже), v2 выделяется в адресном пространстве, которое раньше принадлежало v1. Т.е. squeeze нормально отдает память. Вроде все логично и предсказуемо. Код: QVector<int> v1; Консоль Код: [Session started at 2009-09-17 10:57:06 +0300.] Название: Re: Memory issues Отправлено: BRE от Сентябрь 17, 2009, 11:15 Igors, попробуй последний пример.
Он показывает на сколько элементов реально выделяется буфер и соответственно точное расположение его в памяти. Еще попробуй изменять размер второго вектора и смотреть на реальный размер буфера. Код
Название: Re: Memory issues Отправлено: Igors от Сентябрь 17, 2009, 11:20 Проблема здесь совсем не в squeeze (это только частный случай). Почему они написали что обычно squeeze не нужна? Да потому что они затачивали resize и erase на освобождение (с пулом). В исходниках это хорошо видно. И это была хорошая и правильная задумка.
BRE, по смыслу у Вас должна память освобождаться по resize (пусть не вся, что-то на пул), без всякого squeeze. Проверьте когда будет возможность. Но у них дыра в базовом распределении памяти, и это вылазит в виде самых разнообразных (у)течек. Я вообще столкнулся с этим на QByteArray. Название: Re: Memory issues Отправлено: BRE от Сентябрь 17, 2009, 11:35 Проблема здесь совсем не в squeeze (это только частный случай). Почему они написали что обычно squeeze не нужна? Да потому что они затачивали resize и erase на освобождение (с пулом). В исходниках это хорошо видно. И это была хорошая и правильная задумка. QVector из-за его особенности (необходимость непрерывного участка памяти) затачивался захватывать буфер с запасом и чем больше пользователь задает размер, тем больший запас делает QVector. Делается это что бы уменьшить фрагментацию памяти, но при превышении запаса необходимо было перезахватить новый буфер. Память, которую раньше занимал буфер освобождается, из нее в дальнейшем выделяется память для объектов не превышающих ее.BRE, по смыслу у Вас должна память освобождаться по resize (пусть не вся, что-то на пул), без всякого squeeze. Проверьте когда будет возможность. Она освобождается. Только буфер становится размером больше чем указал пользователь (резерв). Если после resize вызвать capacity(), то он сообщит на сколько элементов реально выделен буфер. (последний пример это хорошо показывает, если поиграться с размерами QVector).Но у них дыра в базовом распределении памяти, и это вылазит в виде самых разнообразных (у)течек. Я вообще столкнулся с этим на QByteArray. Ну тогда у них еще огромная дыра: никак не получается запустить сразу миллион QThread.Название: Re: Memory issues Отправлено: Igors от Сентябрь 17, 2009, 11:40 Igors, попробуй последний пример. Подправьте пожалуйста оригинал чтобы не было путаницы (если Вы добавляете к адресу, домножать на sizeof не надо).Код
Название: Re: Memory issues Отправлено: BRE от Сентябрь 17, 2009, 11:43 Подправьте пожалуйста оригинал чтобы не было путаницы (если Вы добавляете к адресу, домножать на sizeof не надо). Почему?capacity() возвращает количество элементов для которых зарезервирован буфер. Размер элемента sizeif( int ). Нужно умножать. Название: Re: Memory issues Отправлено: Igors от Сентябрь 17, 2009, 11:51 Почему? &v1[0] есть указатель на int. Значит, сама адресная арифметика размер учтет. Вот если Вы бы привели его к (char *) - тогда надо.capacity() возвращает количество элементов для которых зарезервирован буфер. Размер элемента sizeif( int ). Нужно умножать. Название: Re: Memory issues Отправлено: BRE от Сентябрь 17, 2009, 11:59 &v1[0] есть указатель на int. Значит, сама адресная арифметика размер учтет. Вот если Вы бы привели его к (char *) - тогда надо. Туплю уже. :)Вот немного измененный пример: Код
Вывод: 100000 131068 0xb7f80018 0xb8000008 1 2 0xb7f80018 0xb7f80020 60000 65532 0xb7fc0018 0xb8000008 По моему все по адресам видно. P.S. На счет адресов: в linux большие буферы выделяются с конца хипа, маленькие с начала. Название: Re: Memory issues Отправлено: Igors от Сентябрь 17, 2009, 12:13 Вывод: А у меня 100000 131068 0xb7f80018 0xb8000008 1 2 0xb7f80018 0xb7f80020 60000 65532 0xb7fc0018 0xb8000008 По моему все по адресам видно. Код: 100000 131068 0x1c010 0x9c000 Название: Re: Memory issues Отправлено: BRE от Сентябрь 17, 2009, 12:20 А у меня Да, как-то это грустно и неправильно. ::)Код: 100000 131068 0x1c010 0x9c000 Но все таки, IMHO, это проблемы MacOS. Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 17, 2009, 13:55 Код: 100000 131068 0x1c010 0x9c000 http://www.hoard.org/ Под WinXp Код: 100000 131068 0x7fe80050 0x7ff00040 Название: Re: Memory issues Отправлено: Igors от Сентябрь 17, 2009, 16:14 Попробуй использовать сторонний распределитель За ссылку спасибо. Если я правильно понял:http://www.hoard.org/ Не используйте QVector, а используйте std::vector, усиленный кастомным аллокатором Хорошо, проживу я без QVector. Но ведь у меня и с QString то же самое Код: #define NUM_TEST (20 * 1024 * 1024) "Абыдно, слюший" (классика советского кино) Название: Re: Memory issues Отправлено: SABROG от Сентябрь 17, 2009, 16:23 Не используйте QVector, а используйте std::vector, усиленный кастомным аллокатором А я бы сказал иначе: "не пишите нестабильные программы, которые съедят всю доступную оперативную память в погоне за скоростью, вместо того, чтобы написать программу, которая будет делать свою работу как часы и не мешать работать другим программам, которым тоже нужна память". Название: Re: Memory issues Отправлено: Igors от Сентябрь 17, 2009, 16:30 А я бы сказал иначе: "не пишите нестабильные программы, которые съедят всю доступную оперативную память в погоне за скоростью, вместо того, чтобы написать программу, которая будет делать свою работу как часы и не мешать работать другим программам, которым тоже нужна память". Но ведь я так и делаю :) Взял 120Mb (разве это сейчас "вся память"?), обработал этот кусок, освободил память, беру следующий. Вернее - хотел освободить :) Название: Re: Memory issues Отправлено: Winstrol от Сентябрь 17, 2009, 16:30 Попробуй использовать сторонний распределитель За ссылку спасибо. Если я правильно понял:http://www.hoard.org/ Не используйте QVector, а используйте std::vector, усиленный кастомным аллокатором Хорошо, проживу я без QVector. Но ведь у меня и с QString то же самое Hoard переопределяет вызовы malloc/new. Про кастомные аллокаторы stl верно само собой, но это более высокого уровня пушка. Название: Re: Memory issues Отправлено: SABROG от Сентябрь 17, 2009, 16:35 А я бы сказал иначе: "не пишите нестабильные программы, которые съедят всю доступную оперативную память в погоне за скоростью, вместо того, чтобы написать программу, которая будет делать свою работу как часы и не мешать работать другим программам, которым тоже нужна память". Но ведь я так и делаю :) Взял 120Mb (разве это сейчас "вся память"?), обработал этот кусок, освободил память, беру следующий. Вернее - хотел освободить :) Ну и используй clean(), он работает нормально :) Название: Re: Memory issues Отправлено: BRE от Сентябрь 17, 2009, 16:52 Взял 120Mb (разве это сейчас "вся память"?), обработал этот кусок, освободил память, беру следующий. Вернее - хотел освободить :) IMHO из-за этого все проблемы. Захотел 120Mb - получил - освободил, захотел 300Mb - получил - освободил, ... , захотел 500Mb - а адресное пространство исчерпалось. Хотя у нас остались свободные блоки 120Mb, 300Mb, ...Наверное стоит изменить алгоритм хранения этих данных, что бы не было необходимости в больших непрерывных блоках памяти На счет менеджера памяти на Mac это отдельный разговор, с ним наверное нужно по разбираться или заменить... Название: Re: Memory issues Отправлено: BRE от Сентябрь 17, 2009, 16:58 Не используйте QVector, а используйте std::vector, усиленный кастомным аллокатором На сколько я помню std::vector будет вести себя аналогично QVector при увеличении его размера, т.е. пытаться получить новый блок памяти, скопировать в него данные и освободить старый блок. И аллокатор здесь не причем. Поправьте если я ошибаюсь.Название: Re: Memory issues Отправлено: Igors от Сентябрь 17, 2009, 17:10 Ладно, давайте закругляться, а то разговор получается слишком длинным. Я имел те же проблемы без Qt так что я ничего не потерял :)
Итого: собака здесь явно порылась и жаловаться на (у)течки нечего - по крайней мере на одной из платформ Название: Re: Memory issues Отправлено: SABROG от Сентябрь 21, 2009, 18:40 Еще 5 копеек в пользу Qt'шных контейнеров. STL есть не на всех платформах, речь идет в основном об Embedded Systems. Т.ч. используя std::vector/list и т.д. вы урезаете переносимость вашего приложения.
Название: Re: Memory issues Отправлено: Rcus от Сентябрь 21, 2009, 19:25 Еще 5 копеек в пользу Qt'шных контейнеров. STL есть не на всех платформах, речь идет в основном об Embedded Systems. Т.ч. используя std::vector/list и т.д. вы урезаете переносимость вашего приложения. Интересно, даже очень. Давно не видел сказочных платформ (честно говоря самое необычное что приходилось видеть это armv5), но неужели Qt портировали обратно в 95й год, когда STL была, а стандарта не было?Название: Re: Memory issues Отправлено: SABROG от Сентябрь 21, 2009, 20:14 Интересно, даже очень. Давно не видел сказочных платформ (честно говоря самое необычное что приходилось видеть это armv5), но неужели Qt портировали обратно в 95й год, когда STL была, а стандарта не было? Тролли прямо не указывают названия таких платформ, но тем не менее: http://qt.nokia.com/developer/faqs/559?hotspoturl=http%3A//qt.nokia.com/developer/faqs/qt Я нашел информацию о том, что портированный gcc компилятор - WinArm портирован не до конца в связи с чем в нем отсутствует STL тут: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=index Название: Re: Memory issues Отправлено: Tonal от Сентябрь 22, 2009, 07:38 И stlport там не заводится?
Название: Re: Memory issues Отправлено: SABROG от Сентябрь 22, 2009, 11:19 И stlport там не заводится? Пишут, что stlport не собирается под AVR. |