Russian Qt Forum
Ноябрь 24, 2024, 18:03 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: postEvent - Утечка памяти  (Прочитано 6710 раз)
Dodge
Гость
« : Октябрь 05, 2014, 13:20 »

Столкнулся с проблемой утечки памяти при обработке событий поставленных в очередь через postEvent.

Описание:
Есть объект обработчик сообщений.
Есть функция которая посылает сообщения объекту обработчику при помощи QCoreApplication::postEvent.
После обработки всех сообщений утекает некоторое количество памяти.

Как я это определил:
Очень просто, запускаю приложение без отправки сообщения - объем памяти занимаемый приложением V.
Запускаю приложение с отправкой n сообщений, объем памяти - Vn (>V).
Запускаю приложение с отправкой n1 сообщений, объем памяти - Vn1 (>Vn).

При этом в результате тестов выяснил следующие факты:
Объем утекшей памяти зависит от продолжительности обработки каждого сообщения (usleep в обработчике).
Не важно в каком потоке отправлять сообщения.
Объекты сообщений однозначно удаляются.

Тестировал на Win7 x64 и Linux x64.

Текст программы в приложении.

Прошу помощи.
Записан
Bepec
Гость
« Ответ #1 : Октябрь 05, 2014, 15:07 »

Если удаляется, значит всё в порядке. Кода вы не привели, смотреть не на что.
Если имеется N созданий и N удалений, всё в порядке.

Менеджер памяти на Windows не забирает сразу свободную память. Она продолжает числиться за приложением до тех пор, пока менеджеру не понадобится.
Записан
Dodge
Гость
« Ответ #2 : Октябрь 05, 2014, 18:11 »

Если удаляется, значит всё в порядке. Кода вы не привели, смотреть не на что.
Если имеется N созданий и N удалений, всё в порядке.

Менеджер памяти на Windows не забирает сразу свободную память. Она продолжает числиться за приложением до тех пор, пока менеджеру не понадобится.
Код в приложении.
Про менеджер я понял, но память течет пропорционально времени обработки сообщений и количеству этих сообщений. Если задать достаточное количество, то можно легко уйти в своп.
Для контроля количества объектов сообщений используется счетчик.
Записан
Bepec
Гость
« Ответ #3 : Октябрь 05, 2014, 18:19 »

А где здесь удаление? я что то не вижу delete.
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #4 : Октябрь 05, 2014, 18:25 »

Ну так все согласно вашим желаниям. Улыбающийся

Согласно вашему коду, вы вначале создаете пять миллионов объектов класса Event, а только потом начинаете их обрабатывать (при запуске exec). Т.е. память будет освобождаться по мере их обработки.
Записан
Bepec
Гость
« Ответ #5 : Октябрь 05, 2014, 18:39 »

Old, не напомните ли, каков алгоритм удаления QEvent или где это можно почитать. К сожалению я уже подзабыл кто и когда его должен удалять.

update: уже нашёл сам. Диспетчер сам удаляет.

to Dodge - В вашем примере всё просто. Из-за задержки при обработке, скорость обработки очереди ОЧЕНЬ ОЧЕНЬ низкая. Уберите оттуда задержку и у вас память будет чиститься при нормальных скоростях.

Вы ддосите диспетчер event'ов и сознательно замедляете его обработку при помощи usleep - в этот момент вся программа стоит. Т.е. обработка 5 миллионов записей будет произведена за
5 000 000 * задержку(50 микросекунд) * вызов QObject::event * работу диспетчера * на удаление event'a.
« Последнее редактирование: Октябрь 05, 2014, 18:47 от Bepec » Записан
Dodge
Гость
« Ответ #6 : Октябрь 05, 2014, 19:05 »

Обсалютно со всеми согласен.
Но есть одно но: объем памяти до обработки и после различается, хотя по логике должен быть одинаковый. Задержку я внес намерено, если изменять значение задержки, объем откушанной памяти после окончания обработки изменяется.
 После обработки прилоение занимает гораздо больше памяти чем чем до. Меня это и смущает. Причем очевидно это не связано с особенностями диспетчера памяти конкретной ОС, т.к. под вин и линукс результат воспроизводится.
Записан
Old
Джедай : наставник для всех
*******
Online Online

Сообщений: 4350



Просмотр профиля
« Ответ #7 : Октябрь 05, 2014, 19:14 »

Но есть одно но: объем памяти до обработки и после различается, хотя по логике должен быть одинаковый.
Давайте разберемся, что для вас до обработки и что после. В каких местах вы это замеряете?

Записан
Bepec
Гость
« Ответ #8 : Октябрь 05, 2014, 19:20 »

Ну это имеет место быть, с 1 мб памяти  увеличивается до 9 после обработки.
Собственно мой тестовый проект сейчас обрабатывает 500000 и я вам точно скажу сколько чего осталось Веселый

update:
Ну, все объекты типа myEvent удалились успешно и освобождённо взмыли в небеса.

А почему увеличивается размер - я думаю что это диспетчер увеличил зарезервированное место под очередь. Собственно других объяснений я не вижу Улыбающийся
« Последнее редактирование: Октябрь 05, 2014, 19:23 от Bepec » Записан
Dodge
Гость
« Ответ #9 : Октябрь 05, 2014, 21:21 »

...
А почему увеличивается размер - я думаю что это диспетчер увеличил зарезервированное место под очередь. Собственно других объяснений я не вижу Улыбающийся
Под Linux видно зарезервированную память и реально используемою. Увеличивается реально используемый объем. И как я уже писал, объем сильно зависит от скорости обработки каждого сообщения, если их посылать в бесконечном цикле, то рано или поздно память заполняется на столько, на сколько это возможно.
Записан
Dodge
Гость
« Ответ #10 : Октябрь 05, 2014, 21:25 »

Но есть одно но: объем памяти до обработки и после различается, хотя по логике должен быть одинаковый.
Давайте разберемся, что для вас до обработки и что после. В каких местах вы это замеряете?
Я уже писал, что я замерил память в запущенном приложении, в котором отправка сообщений не производилась (просто закоментировал код, который формирует сообщения).
После чего раскоментировал код, собрал и запустил приложение, дождался когда последнее сообщение будет удалено и замерил снова.
Записан
Bepec
Гость
« Ответ #11 : Октябрь 05, 2014, 21:51 »

Если запускать в бесконечном, то обрабатываться они не будут вообще. Ибо цикл сообщений не будет запущен Веселый Потому будет простая перегрузка.

Зависимость от времени неявная. Завтра потестю с увеличенной задержкой, но мне кажется бред Веселый
Записан
Dodge
Гость
« Ответ #12 : Октябрь 05, 2014, 22:20 »

Если запускать в бесконечном, то обрабатываться они не будут вообще. Ибо цикл сообщений не будет запущен Веселый Потому будет простая перегрузка.
Чтобы этого избежать, нужно запустить функцию в параллельном потоке. Для этого в файле достаточно раскомментить строчку:
Код:
//QtConcurrent::run( spam, &recevier, 5000000 );
Ну и дополнить код функции так, чтобы она, скажем значение -1 интерпретировала как бесконечный цикл.
и закоментить синхронный вызов соответственно.

Зависимость от времени неявная. Завтра потестю с увеличенной задержкой, но мне кажется бред Веселый
Такое ощущение, что в меня пытаетесь уличить во лжи. Я не вру, честное слово. ))
Записан
Bepec
Гость
« Ответ #13 : Октябрь 05, 2014, 23:56 »

Ммм... Вы можете заблуждаться Улыбающийся А там святое дело )
Записан
Dodge
Гость
« Ответ #14 : Октябрь 06, 2014, 00:46 »

Ммм... Вы можете заблуждаться Улыбающийся А там святое дело )
Ага, тут вариантов не много, либо я что-то не так делаю, либо в кутэ баг. ))
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.052 секунд. Запросов: 23.