Russian Qt Forum

Qt => Общие вопросы => Тема начата: Igors от Сентябрь 13, 2009, 21:50



Название: 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>
#include <iostream>
#include <stdio.h>

#define  NUM_TEST   (200LL * 1024 * 1024)

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

int i;
QList<int> theList;
for (i = 0; i < NUM_TEST; ++i)
theList.append(qrand());

printf("Press Enter 1\r");
getc(stdin);

theList.erase(theList.begin() + NUM_TEST / 4, theList.begin() + NUM_TEST / 4 * 3);

printf("Press Enter 2\r");
getc(stdin);

return 0;
}

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
Добрый вечер

Обнаружил проблему с памятью на своей платформе (Mac). Не хочу "предъявлять претензий" (все равно решать самому  :)) но сообщить о проблеме по-моему надо.
Деструктор Qlist в точке 2 еще не отработал, поэтому и память не отдал.


Название: 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 еще не отработал, поэтому и память не отдал.
Деструктор здесь ни при чем. Я сказал контейнеру выкинуть половину элементов, но это не освободило часть памяти - занято столько же. 
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.


Название: 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>
#include <iostream>
#include <stdio.h>
#include <QVector>

#define  NUM_TEST (200LL * 1024 * 1024)

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

int i;
QVector<int> theVector;
for (i = 0; i < NUM_TEST; ++i)
theVector.append(qrand());

printf("Press Enter 1\r");
getc(stdin);

theVector.resize(NUM_TEST / 2);

printf("Press Enter 2\r");
getc(stdin);

return 0;
}
Есть ли какой-то контейнер который память нормально отдает?
Спасибо


Название: 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)

int i, j;
QVector<int> theVector[10];

for (i = 0; i < 10; ++i) {
theVector[i].reserve(NUM_TEST);
for (j = 0; j < NUM_TEST; ++j)
theVector[i].append(1);
theVector[i].resize(2);
theVector[i].squeeze();
}
Вылетает, консоль пишет
Код:
[Session started at 2009-09-14 13:11:02 +0300.]
realloc(508) malloc: *** mmap(size=838864896) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Ну вот, хотел наконец подучить стандартные классы да видно не судьба  :P


Название: Re: Memory issues
Отправлено: Winstrol от Сентябрь 14, 2009, 13:58
А так если?
Код
C++ (Qt)
#include <vector>
...
   int i, j;
   std::vector<int> theVector[10];
 
   for (i = 0; i < 10; ++i)
   {
       theVector[i].reserve(NUM_TEST);
       for (j = 0; j < NUM_TEST; ++j)
           theVector[i].push_back(1);
       theVector[i].resize(2);
       {
           std::vector<int> t;
           std::swap(theVector[i],t);
           theVector[i]=t;
           std::cout << theVector[i].capacity() << std::endl;
       }
   }


Название: Re: Memory issues
Отправлено: spectre71 от Сентябрь 14, 2009, 14:01
Так работает
Код
C++ (Qt)
QVector<int> *theVector1;
QVector<int> *theVector2;
 
theVector1 = new QVector<int>;
theVector1->reserve(200*1024*1024);
theVector1->squeeze();
delete theVector1;
 
theVector2 = new QVector<int>;
theVector2->reserve(200*1024*1024);
delete theVector2;

Так падает
Код
C++ (Qt)
QVector<int> *theVector1;
QVector<int> *theVector2;
 
theVector1 = new QVector<int>;
theVector1->reserve(200*1024*1024);
theVector1->squeeze();
 
theVector2 = new QVector<int>;
theVector2->reserve(200*1024*1024);
 
delete theVector1;
delete theVector2;
хотя до 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++ (Qt)
sbw::Indices* theVector1;
sbw::Indices* theVector2;
 
theVector1 = new sbw::Indices;
theVector1->maxCapacity(250*1024*1024);
theVector1->minCapacity();
 
theVector2 = new sbw::Indices;
theVector2->maxCapacity(250*1024*1024);
 
delete theVector1;
delete theVector2;
 
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Мб.
Я же писал про Mem Usage & VM Size, останавливал в дебагере и смотрел. Так что squeeze работает.
Единственно в чем может быть разница между 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.cpp

void *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

Спасибо

Да этот код(приведенный вами) валиться на Windows. И тот упрощенный код(который я приводил) тоже.
theV.reserve(400 * 1024 * 1024);  -  валиться на Windows сразу(Windows XP).


Название: Re: Memory issues
Отправлено: Igors от Сентябрь 14, 2009, 17:48
Да этот код(приведенный вами) валиться на Windows. И тот упрощенный код(который я приводил) тоже.
theV.reserve(400 * 1024 * 1024);  -  валиться на Windows сразу(Windows XP).
Ага, спасибо, Spectre
Давайте сочинять баг репорт (vers 2.0)?  :)


Название: Re: Memory issues
Отправлено: spectre71 от Сентябрь 14, 2009, 18:30
Да этот код(приведенный вами) валиться на Windows. И тот упрощенный код(который я приводил) тоже.
theV.reserve(400 * 1024 * 1024);  -  валиться на Windows сразу(Windows XP).
Ага, спасибо, Spectre
Давайте сочинять баг репорт (vers 2.0)?  :)
Это проблемы использования realloc
Код:
  int* a;
  int* b;
 
  a = (int*) malloc(200*1024*1024*sizeof(int));
  a = (int*) realloc(a, sizeof(int));
  b = (int*) malloc(200*1024*1024*sizeof(int));
// b == NULL Error !!!
  delete a;
  delete b;
Видимо эта зараза(realloc) не освобождает память, в надежде на то, что ее снова будут аллоцировать для данного указателя, идиотизм!
Не помню чтобы что-то подобное было описано в его спецификации(посмотрел сейчас в 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
erase не удаляет ничего, он подчищает мусор, который остается после использования метода remove().
Ноги ростут от кривой работы realloc! Что показано на предыдущем тесте.
А то что ты привел связано с различием между "Count/Size" и "Capacity/AllocSize"


Название: Re: Memory issues
Отправлено: spectre71 от Сентябрь 14, 2009, 18:55
Погонял тесты под linux. Полет нормальный.
Код с двумя векторами работает нормально: захватывает - освобождает.
С выделением: theV.reserve(400 * 1024 * 1024);  // то есть > 1Gb
тоже все Ок.

1) Возможно под Linux - realloc работает другим образом?
2) Скольки разрядный Linux, если 64, то возможно разница в этом?


Название: Re: Memory issues
Отправлено: BRE от Сентябрь 14, 2009, 19:07
1) Возможно под Linux - realloc работает другим образом?
2) Скольки разрядный Linux, если 64, то возможно разница в этом?
linux - 32bit.

Код
C++ (Qt)
 a = (int*) malloc(200*1024*1024*sizeof(int));
 a = (int*) realloc(a, sizeof(int));          
 b = (int*) malloc(200*1024*1024*sizeof(int));
 
 qDebug() << a;
 qDebug() << b;
 
Вывод:
0x85fb8008               
0x53fb7008               

Код
C++ (Qt)
 //#1 - Откушано памяти: 19 Мб
 a = (int*) malloc(400*1024*1024*sizeof(int));
 //#2 - Откушано памяти: 1,5 Гб
 a = (int*) realloc(a, sizeof(int));          
 //#3 - Откушано памяти: 19 Мб
 b = (int*) malloc(400*1024*1024*sizeof(int));
 //#4 - Откушано памяти: 19 Мб
 
 qDebug() << a;
 qDebug() << b;
 
Вывод:
0x53ed6008
0x0

Т.е. realloc освобождает блок, malloc пытается захватить такой же, но обламывается т.к. ему не хватает адресного пространства для нового блока (хотя память есть). Вроде все согласно документации.

А вот так новый блок выделиться в перераспределенном:
Код
C++ (Qt)
 //#1 - Откушано памяти: 19 Мб
 a = (int*) malloc(400*1024*1024*sizeof(int));
 //#2 - Откушано памяти: 1,5 Гб
 a = (int*) realloc(a, sizeof(int));          
 //#3 - Откушано памяти: 19 Мб
 b = (int*) malloc(399*1024*1024*sizeof(int));
 //#4 - Откушано памяти: 1,5 Гб
 
 qDebug() << a;
 qDebug() << b;
 
Вывод:
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)); 
// ОК получили страницу памяти 1600 MB
// Имеем теперь 2 страницы в куче, изначальную, не очень большую и большую на 1600 MB
  a = (int*) realloc(a, sizeof(int));                   
// Освободили во второй странице 1600 MB без 4 byte
  b = (int*) malloc(400*1024*1024*sizeof(int));
// Просим 1600 MB.
// В первой странице совсем мало памяти
// Во второй странице не хватает 4 байт
// Просим у системы новую страницу для програмной кучи под наши 1600 MB, облом, превысили лимит!

/* Во втором варианте */

  b = (int*) malloc(399*1024*1024*sizeof(int));
// А в данном случае во второй странице памяти хватило (1600 MB - 4 byte > 1596 MB)

Вот такая фигня :)


Название: 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
По поводу баг репорта - по-моему все-таки надо сообщить. В документации ясно сказано:
Цитировать
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 или еще как - это их дело.
Не уверен, что это баг. Это фича, причем не Qt, а стратегии распределения памяти конкретной операционной системы.
В любом случае для выделения/перераспределения памяти будут использованы 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, ...
Есть большие объемы данных, они встречаются редко (обычно 1-2 раза в задаче) но они есть. Это как правило тупенькие структурки (не бывает "много" да еще и "сложно"). Весь этот интеллект QMap, QHash мне для них совсем не нужен, мне их надо просто хранить и добавлять в хвост новые, упаковывать (лучше самому, без erase) . Иногда сортировать.

Остается 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-ные контейнеры?
Быстрее и эффективней Qt-ишных. Почему не использовать их?
Я не берусь утверждать кто из них быстрее/эффективней. И с удовольствием пользуюсь STL, намного меньше писать. Просто не везде он подходит. Например

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-ишных. Почему не использовать их?
+1 Никогда не понимал порнографии вроде Qlist. Причем hardcore.


Название: Re: Memory issues
Отправлено: Winstrol от Сентябрь 16, 2009, 10:24
Я не знаю, является ли QList аналогом std::list, но я четко вижу, что QList кушает как и положено не больше 500Мб при попытке поместить в контейнер ~100млн. int'ов, в то время как std::list'у при аналогичном коде не хватает 1,6Гб съеденной оперативы после чего программа падает, даже не ругнувшись в отладчик о нехватке памяти.
Скорее всего, реализация вызывает new/delete на каждый чих.
Для наглядности можно поэкспериментировать с таким фрагментом.
Код
C++ (Qt)
for (j = 0; j < NUM_TEST; ++j)
{
   new int[3];
}
 
В этой ситуации надо
-отказаться от использования 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
Код
C++ (Qt)
boost::shared_ptr<SharedClass> sharedObj = anotherObj;
 
Если собираемся менять sharedObj, то делаем.
Код
C++ (Qt)
template <class T>
void unsharePtr(boost::shared_ptr<T>& ptr)
{
   if (!ptr.unique()) ptr=boost::make_shared<T>(*ptr.get());
}
...
unsharePtr(sharedObj);
sharedObj->не const метод
 



Название: Re: Memory issues
Отправлено: Igors от Сентябрь 16, 2009, 13:02
Если в Qt что-то хуже или работает не так, почему бы не спросить троллей как правильно или чтобы это исправили? Я понимаю, что всем надо в срок уложиться, сдать заказ и времени клепать багрепорты нет, легче выбрать что-то другое. Но ведь проблема никуда не пропадет, если вы о ней не сообщите.
Да я если честно языкам не обучен. :)
Как будто роман собираемся писать:) Взял да написал за 5 минут, а что ошибки в языке будут - стесняться нечего, если что отвечайте: My English is much better than your Russian.
Предлагаю:

--------------------
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)

int i, j;
QVector<int> theVector[10];

for (i = 0; i < 10; ++i) {
theVector[i].reserve(NUM_TEST);
for (j = 0; j < NUM_TEST; ++j)
theVector[i].append(1);
theVector[i].resize(2);
theVector[i].squeeze();
}
Looking sources files we can guess the problem is related with ::realloc that does not release memory in fact

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

И архитектура ОС тут не причем! Всё должно одинаково/аналогично работать на разных платформах..
Камрады, squeeze освобождает.
И на всех платформах все работает одинаково.
Что могут сделать Тролли, если для процесса в linux отдается 3 Гб, а в венде 2. Это особенности ОС.



Название: Re: Memory issues
Отправлено: Igors от Сентябрь 16, 2009, 16:31
Камрады, squeeze освобождает.
И на всех платформах все работает одинаково.
Что могут сделать Тролли, если для процесса в linux отдается 3 Гб, а в венде 2. Это особенности ОС.
Проверяю на в 10 раз меньших блоках

Код:
#define  NUM_TEST	(20 * 1024 * 1024)

int i, j;
QVector<int> theVector[100];

for (i = 0; i < 100; ++i) {
theVector[i].reserve(NUM_TEST);
for (j = 0; j < NUM_TEST; ++j)
theVector[i].push_back(i);
theVector[i].resize(2);
theVector[i].squeeze();
}
Расход памяти непрерывно растет до 3 Gb, затем - вылет


Название: Re: Memory issues
Отправлено: BRE от Сентябрь 16, 2009, 19:56
Igors, попробуй на Мас такой код:
Код
C++ (Qt)
       QVector<int> v1;
       v1.reserve( 100000 );
       qDebug() << &v1[ 0 ] << &v1[ 99999 ];
       v1.resize(2);                        
       v1.squeeze();                        
 
       QVector<int> v2;
       v2.reserve( 90000 );
       qDebug() << &v2[ 0 ] << &v2[ 89999 ];
 
В linux точно (в венде я думаю тоже), v2 выделяется в адресном пространстве, которое раньше принадлежало v1. Т.е. squeeze нормально отдает память.

Код
C++ (Qt)
       const uint NUM_TEST = 1000 * 1024 * 1024;
 
       QVector<int> theVector;
       int *old_pos = 0;      
 
       for( uint i = 0; i < NUM_TEST; ++i )
       {                                  
               theVector.push_back( i );  
               if( old_pos != &theVector[ 0 ] )
               {                              
                       old_pos = &theVector[ 0 ];
                       qDebug() << hex << qSetFieldWidth( 8 ) << i << &theVector[ 0 ];
               }                                                                      
       }                                                                              
 
А этот код показывает как будет мигрировать непрерывный кусок памяти по адресному пространству, пока не исчерпает его.

Вроде все логично и предсказуемо.


Название: 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
Abort trap
падает
macbook, 4ГБ ОП на борту


Название: Re: Memory issues
Отправлено: BRE от Сентябрь 16, 2009, 21:37
1й код
Код:
ASSERT failure in QVector<T>::operator[]: "index out of range", file /Library/Frameworks/QtCore.framework/Headers/qvector.h, line 337
Abort trap
падает
macbook, 4ГБ ОП на борту

А на каком qDebug падает: первом или втором?
 :o ???


Название: Re: Memory issues
Отправлено: Авварон от Сентябрь 16, 2009, 21:45
вывод приложения я привел) на 1м видимо в v1[ 99999 ]
added: так, стоп, я ушел курить, почему она всегда падает О_о
added2: то ли место не резервируется, то ли я криворук


Название: Re: Memory issues
Отправлено: BRE от Сентябрь 16, 2009, 22:17
вывод приложения я привел) на 1м видимо в v1[ 99999 ]
added: так, стоп, я ушел курить, почему она всегда падает О_о
added2: то ли место не резервируется, то ли я криворук
reserve только резервирует место, но не увеличивает размер вектора (v1.size() == 0).
У тебя скорее всего используется debug версия Qt и там отрабатывает Q_ASSERT_X.
Вместо reserve попробуй использовать resize.

Новая версия тестовой программы (показывает точную область с учетом capacity()):
Код
C++ (Qt)
       QVector<int> v1;
       QVector<int> v2;
       const int sizeV1 = 100000;
       const int sizeV2 = 60000;
 
       v1.resize( sizeV1 );
       qDebug() << v1.size() << v1.capacity() << &v1[ 0 ] << &v1[ 0 ] + v1.capacity() * sizeof( int );
       v1.resize( 2 );                                                                
       v1.squeeze();                                                                  
 
       v2.resize( sizeV2 );
       qDebug() << v2.size() << v2.capacity() << &v2[ 0 ] << &v2[ 0 ] + v2.capacity() * sizeof( int );
 


Название: Re: Memory issues
Отправлено: Igors от Сентябрь 17, 2009, 11:09
Igors, попробуй на Мас такой код:
...
В linux точно (в венде я думаю тоже), v2 выделяется в адресном пространстве, которое раньше принадлежало v1. Т.е. squeeze нормально отдает память.

Вроде все логично и предсказуемо.
На Вашей платформе - да. На моей - нет. Я немного добавил кода чтобы избежать "out of range"

Код:
QVector<int> v1; 
v1.reserve( 100000 );
for (int i = 0; i < 100 * 1000; ++i) v1.push_back(i);
qDebug() << &v1[ 0 ] << &v1[ 99999 ];
v1.resize(2);                       
v1.squeeze();                       

QVector<int> v2;
v2.reserve( 90000 );
for (int i = 0; i < 90 * 1000; ++i) v2.push_back(i);
qDebug() << &v2[ 0 ] << &v2[ 89999 ];

Консоль
Код:
[Session started at 2009-09-17 10:57:06 +0300.]
0x1c010 0x7da8c
0x7e010 0xd5e4c


Название: Re: Memory issues
Отправлено: BRE от Сентябрь 17, 2009, 11:15
Igors, попробуй последний пример.
Он показывает на сколько элементов реально выделяется буфер и соответственно точное расположение его в памяти. Еще попробуй изменять размер второго вектора и смотреть на реальный размер буфера.
Код
C++ (Qt)
       QVector<int> v1;
       QVector<int> v2;
       const int sizeV1 = 100000;
       const int sizeV2 = 60000;
 
       v1.resize( sizeV1 );
       qDebug() << v1.size() << v1.capacity() << &v1[ 0 ] << &v1[ 0 ] + v1.capacity() * sizeof( int );
       v1.resize( 2 );                                                                
       v1.squeeze();                                                                  
 
       v2.resize( sizeV2 );
       qDebug() << v2.size() << v2.capacity() << &v2[ 0 ] << &v2[ 0 ] + v2.capacity() * sizeof( int );
 


Название: 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, попробуй последний пример.
Код
C++ (Qt)
       qDebug() << v1.size() << v1.capacity() << &v1[ 0 ] << &v1[ 0 ] + v1.capacity() * [b]sizeof( int )[/b];
 
Подправьте пожалуйста оригинал чтобы не было путаницы (если Вы добавляете к адресу, домножать на sizeof не надо).


Название: Re: Memory issues
Отправлено: BRE от Сентябрь 17, 2009, 11:43
Подправьте пожалуйста оригинал чтобы не было путаницы (если Вы добавляете к адресу, домножать на sizeof не надо).
Почему?
capacity() возвращает количество элементов для которых зарезервирован буфер. Размер элемента sizeif( int ).
Нужно умножать.


Название: Re: Memory issues
Отправлено: Igors от Сентябрь 17, 2009, 11:51
Почему?
capacity() возвращает количество элементов для которых зарезервирован буфер. Размер элемента sizeif( int ).
Нужно умножать.
&v1[0] есть указатель на int. Значит, сама адресная арифметика размер учтет. Вот если Вы бы привели его к (char *) - тогда надо.


Название: Re: Memory issues
Отправлено: BRE от Сентябрь 17, 2009, 11:59
&v1[0] есть указатель на int. Значит, сама адресная арифметика размер учтет. Вот если Вы бы привели его к (char *) - тогда надо.
Туплю уже.  :)

Вот немного измененный пример:
Код
C++ (Qt)
       QVector<int> v1;
       QVector<int> v2;
       const int sizeV1 = 100000;
       const int sizeV2 = 60000;
 
       v1.resize( sizeV1 );
       for( int i1 = 0; i1 < sizeV1; ++i1 )
               v1[ i1 ] = i1;              
       qDebug() << v1.size() << v1.capacity() << &v1[ 0 ] << &v1[ 0 ] + v1.capacity();
       v1.resize( 1 );                                                                
       qDebug() << v1.size() << v1.capacity() << &v1[ 0 ] << &v1[ 0 ] + v1.capacity();
 
       v2.resize( sizeV2 );
       for( int i2 = 0; i2 < sizeV2; ++i2 )
               v2[ i2 ] = i2;              
       qDebug() << v2.size() << v2.capacity() << &v2[ 0 ] << &v2[ 0 ] + v2.capacity();
 

Вывод:
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 
1 2 0x1c010 0x1c018
60000 65532 0x9c010 0xdc000
И, судя по тому что Spectre проверял, - то же на Вындоуз


Название: Re: Memory issues
Отправлено: BRE от Сентябрь 17, 2009, 12:20
А у меня

Код:
100000 131068 0x1c010 0x9c000 
1 2 0x1c010 0x1c018
60000 65532 0x9c010 0xdc000
И, судя по тому что Spectre проверял, - то же на Вындоуз

Да, как-то это грустно и неправильно.  ::)
Но все таки, IMHO, это проблемы MacOS.


Название: Re: Memory issues
Отправлено: Winstrol от Сентябрь 17, 2009, 13:55
Код:
100000 131068 0x1c010 0x9c000 
1 2 0x1c010 0x1c018
60000 65532 0x9c010 0xdc000
Попробуй использовать сторонний распределитель
http://www.hoard.org/

Под WinXp
Код:
100000 131068 0x7fe80050 0x7ff00040
1 2 0x7ff701b8 0x7ff701c0
60000 65532 0x7fec0050 0x7ff00040




Название: Re: Memory issues
Отправлено: Igors от Сентябрь 17, 2009, 16:14
Попробуй использовать сторонний распределитель
http://www.hoard.org/
За ссылку спасибо. Если я правильно понял:

Не используйте QVector, а используйте std::vector, усиленный кастомным аллокатором

Хорошо, проживу я без QVector. Но ведь у меня и с QString то же самое

Код:
#define NUM_TEST (20 * 1024 * 1024)

int i, j;
QString theS[100];

for (i = 0; i < 100; ++i) {
        for (j = 0; j < NUM_TEST; ++j)
theS[i] += "abc";
printf("String %d\r", i);
theS[i].truncate(2);   // вместо этого можно и theS[i].resize(2); эффект тот же
theS[i].squeeze();
}
Вылетает. Так что же, мне и QString избегать? :)  Или все время думать "а не будет ли моя строка слишком большой"? Или "зачищать" ее каждый раз через копирование в др. строку?

"Абыдно, слюший" (классика советского кино)


Название: 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.