Модераторы: Snowy, MetalFan, bems, Poseidon

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Утечка памяти на стыке приложение - WebBrowser, как победить? 
V
    Опции темы
kami
Дата 11.11.2012, 20:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Здравствуйте, дамы и господа!

Имею приложение, содержащее только TWebBrowser.
В него загружается локальная страничка (подгружающая карту из интернета), после чего - начинают выполняться JavaScript, динамически генерируемые программой (машинка передвигается по карте).
Память начинает кушаться (смотрю ProcessExplorer-ом, Private bytes). Причем, это заметно даже на одном объекте. А их предполагается около полутора тысяч. По моим подсчетам, чуть меньше, чем через сутки приложение свалится с Out of memory. А оно должно работать 24х7. На этом тестовом примере за 8 часов работы размер программы (VirtualSize) возрастает до 1 Гб.

FastMM молчит.

если убрать всего одну строчку, а именно - передачу скрипта в TWebBrowser, то потребление памяти не увеличивается:
Код

procedure TForm4.ExecScript(Script: string);
var
  Doc: IHTMLDocument2; // current HTML document
  HTMLWin: IHTMLWindow2; // parent window of current HTML document
begin
  Doc := IHTMLDocument2(wb1.ControlInterface.Document);
  HTMLWin := Doc.parentWindow;
  if Assigned(HTMLWin) then
    begin
      try
        HTMLWin.ExecScript(Script, 'JavaScript');// убирание этой строки приводит к нормальной работе
      except
      end;
    end;
end;

Если использовать этот же код (в смысле - тот, который передается в работающий TwebBrowser) непосредственно на странице, открытой в IE, то память так же не возрастает.

Просмотрел в интернете, что пишется по этому поводу, нашел только одно: рекомендуют не пользоваться свойством TWebBrowser.Document. Перешел на использование TWebBrowser.ControlInterface - не помогло.
Пытался использовать TEmbeddedWB - проблема та же.

Помогите решить...

Примечание: во вложении тестовое приложение и файлы: 2GISMap.html предназначен для работы в составе приложения, "2GISMap - самостоятельная работа.html " - для отображения непосредственно в браузере.

Это сообщение отредактировал(а) kami - 11.11.2012, 23:15

Присоединённый файл ( Кол-во скачиваний: 12 )
Присоединённый файл  test2gis.zip 11,52 Kb
PM MAIL WWW   Вверх
MetalFan
Дата 12.11.2012, 07:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



Ну так правильно, скрипт то какой? видимо в нем ресурсы какие-то выделяются браузером. В жаваскрипте ж нет необходимости очищать память за собой, все по идее сделает уборщик... отсюда и возможны утечки. Это вопрос скорее в раздел по жаваскрипту.
Предлагаю var myMarker объявить в html файле, а в скрипте в pas файле убрать var, т.е. просто работать с этой переменной. для начала. далее наверное в раздел веб-программирования таки. имхо.

кстати, и еще, если планируется работа в оффлайне, то в html файле неплохо бы перелинковать 
Код

<script type="text/javascript" src="http://maps.api.2gis.ru/1.0"></script> 

на локальный файл.

Это сообщение отредактировал(а) MetalFan - 12.11.2012, 07:16


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
kami
Дата 12.11.2012, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(MetalFan @  12.11.2012,  07:11 Найти цитируемый пост)
кстати, и еще, если планируется работа в оффлайне, то в html файле неплохо бы перелинковать 

Не планируется, к сожалению. Более того - это запрещено договорными обязательствами моей компании с 2ГИС.

Цитата(MetalFan @  12.11.2012,  07:11 Найти цитируемый пост)
 далее наверное в раздел веб-программирования таки. имхо.

В том-то и дело, что я уже думал туда обратиться. Но - там мне скажут что-то типа : 
Цитата

родной, в standalone-скрипте всё работает? Работает. "Чего ж тебе еще надо, собака" (с) smile Разбирайся со своим Delphi.


Цитата(MetalFan @  12.11.2012,  07:11 Найти цитируемый пост)
все по идее сделает уборщик... отсюда и возможны утечки

Вот оно!
Моей благодарности нет предела ! smile 

По всей видимости, IE при выполнении динамически "засланного" скрипта просто не закидывает информацию в сборщик мусора. В том числе - не помогают и вынесение переменных в глобальные с обnullением (а так же не обnullением) после использования. Возможно, это связано с достаточно большой частотой выполнения скриптов.
Выход - сотворить необходимые функции непосредственно в html файле с нужными параметрами и вызывать их через TembeddedWB.ExecScriptEx. Почему-то в этом случае GC у IE работает без замечаний.

Правда, в этом случае всплыл один нюанс с обрезанием строк при передаче в качестве параметров... Буду копать исходники EWB, гуглить, если не найду - тогда опять на форум smile
PM MAIL WWW   Вверх
Illusion Dolphin
Дата 12.11.2012, 09:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 5
Всего: 63



Цитата

а в скрипте в pas файле убрать var, т.е. просто работать с этой переменной. для начала.

Это не тру для Javascript, тем более для IE.

Цитата

за 8 часов работы размер программы (VirtualSize) возрастает до 1 Гб.

А что с Private Bytes

А что за скрипт выполняется? Я ркомендую статью на learn.javascript.ru по утечкам памяти в JavaSctipt http://learn.javascript.ru/optimize - там много идей можно подсмотреть, где могут быть утечки.

Цитата

кстати, и еще, если планируется работа в оффлайне, то в html файле неплохо бы перелинковать 
Выделить всёРазметка HTML
1:
    
<script type="text/javascript" src="http://maps.api.2gis.ru/1.0"></script> 

на локальный файл.


Хихи smile Не надо. Это онлайн карта.


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
kami
Дата 12.11.2012, 09:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(Illusion Dolphin @  12.11.2012,  09:08 Найти цитируемый пост)
А что с Private Bytes? 

Не помню уже, но с примерно 24 мегабайт выросло до... чтоб не соврать, где-то на порядок, т.е. где-то до 200

Цитата(Illusion Dolphin @  12.11.2012,  09:08 Найти цитируемый пост)
А что за скрипт выполняется?

В тестовом примере - только один, выполняющийся по таймеру (однократно выполняемый скрипт при загрузке странички рассматривать не будем). Выглядит так:
Код

var myMarker = staticGroup.get(index);
myMarker.setPosition(new DG.GeoPoint(NewLon, NewLat)); // при работе непосредственно в IE утечки нет.


Цитата(Illusion Dolphin @  12.11.2012,  09:08 Найти цитируемый пост)
Я ркомендую статью на learn.javascript.ru по утечкам памяти

Читал, увы - не помогло...

Это сообщение отредактировал(а) kami - 12.11.2012, 09:20
PM MAIL WWW   Вверх
kami
Дата 12.11.2012, 10:16 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(kami @  12.11.2012,  09:03 Найти цитируемый пост)
всплыл один нюанс с обрезанием строк при передаче в качестве параметров...

Поборол с помощью гугла.
Код

EmbeddedWB.ExecScriptEx('myMethod', [WideString(strParam)]); // передача без преобразования, как UnicodeString обрезает строку. Применимо для D2009up, 
// как с этим обстоит в до-юникодных версиях - не знаю, возможно такой проблемы и нет.
// почему так - не разбирался, нет времени копать исходники EWB.

PM MAIL WWW   Вверх
MetalFan
Дата 12.11.2012, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



Цитата(Illusion Dolphin @  12.11.2012,  09:08 Найти цитируемый пост)
Это не тру для Javascript, тем более для IE.

почему?


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
MetalFan
Дата 12.11.2012, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



kami, кстати, поменял твой код немного.
Похоже, что проблемы то с "утечкой" при выполнении то и нет...
Код

  if FFlag then
  begin
    FLatitude := FLatitude + 0.001;
    FLongitude := FLongitude + 0.001;
  end
  else
  begin
    FLatitude := FLatitude - 0.001;
    FLongitude := FLongitude - 0.001;
  end;
  FFlag := not FFlag;

Если дергаем ее "на месте", то память практически не "утекает".
Похоже, что просто динамическая подгрузка карты кушает почуть память...


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
Illusion Dolphin
Дата 13.11.2012, 00:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1198
Регистрация: 3.5.2003

Репутация: 5
Всего: 63



Цитата

почему? 

Для элементов с id некотоные ие автоматически создают переменные (с именем как id) и если не писать var то можно натолкнуться на странные ошибки. 


--------------------
В мире всего две бесконечности: вселенная и человеческая глупость... На счёт вселенной я не уверен.
Шифрование и организация фотографий - Photo Database 4.5
PM MAIL WWW ICQ   Вверх
MetalFan
Дата 13.11.2012, 07:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



Illusion Dolphin, так я предлагал перенести объявление переменной (var)  в тело скрипта на самой странице... а не вообще отказаться от var.


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
kami
Дата 13.11.2012, 07:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(MetalFan @  12.11.2012,  23:01 Найти цитируемый пост)
Похоже, что проблемы то с "утечкой" при выполнении то и нет...

Может, и нет.
Но более реальный код, чем в моем вопросе (300 объектов, на нем как раз-таки и была обнаружена проблема роста памяти), работающий через EmbeddedWB.ExecScriptEx (вместо ExecScript) за те же 8 часов дал прирост PrivateBytes с 33 до 34 Мб. В то время, как работа ExecScript... ну, об этом я писал уже smile .

Еще раз - огромное спасибо за вариант решения проблемы, над которой я бился 3 дня..

Добавлено @ 07:36
Цитата(MetalFan @  12.11.2012,  23:01 Найти цитируемый пост)
Похоже, что просто динамическая подгрузка карты кушает почуть память...

Карта, вообще-то должна была загрузиться 1 раз и всё. Подгрузка данных должна была производиться только при передвижении карты мышкой или изменении ее масштаба.

Upd: кстати, возможно сыграла свою роль и небольшая правка исходников как WB, так и EWB - замена property Document с index ххх на Get_Document. Но - это было нагуглено первым делом до постановки вопроса.

Это сообщение отредактировал(а) kami - 13.11.2012, 07:41
PM MAIL WWW   Вверх
MetalFan
Дата 13.11.2012, 13:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Аццкий Сотона
****


Профиль
Группа: Комодератор
Сообщений: 3815
Регистрация: 2.10.2006
Где: Moscow

Репутация: 22
Всего: 128



Цитата(kami @  13.11.2012,  07:34 Найти цитируемый пост)
небольшая правка исходников как WB, так и EWB - замена property Document с index ххх на Get_Document

а можно по-подробнее, так сказать, для анналов истории)


--------------------
There are always someone smarter than you...
PM MAIL   Вверх
kami
Дата 13.11.2012, 16:30 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



MetalFan, конечно. Собственно, это не является секретом, Яндекс по запросу "WebBrowser утечка памяти" сразу выдает кучу тем, где это обсуждается.
Цитата

 Вы попытаетесь использовать TWebBrowser.Document:IDispatch, то Вы рано или поздно заметите довольно странную "утечку" памяти в процессе навигации. В чем же дело? После анализа ситуации, удалось определить, что для любой интерфейсной ссылки на документ, которая получена через этот свойство, счетчик использования "необоснованно" увеличивается на 1 и соответствующий COM-обьект никогда не будет освобожден. При более детальном изучении нашлась и создательница этой проблемы - function TOleControl.GetIDispatchProp(Index: Integer): IDispatch;, через которую и работает TWebBrowser.Document:IDispatch. При этом, несмотря на наличие функции Get_Document, она нигде не используется.

Подводя итог (все-таки, форум для начинающих):
для TEmbeddedWB - открываем файл SHDocVw_EWB, ищем в классе TEWB строчку
Код
property Document: IDispatch index 203 read GetIDispatchProp;

и меняем ее на
Код
property Document: IDispatch read Get_Document; // index 203 read GetIDispatchProp;

После этого - перебилд пакета, в котором TEmbeddedWB сидит.

Аналогично меняется для TWebBrowser, но думаю, что в этом случае нужно будет перезакинуть новую dcu-шку в папку Lib.
Не мой, правда, случай - у меня навигация по страницам не ведется, так что Document: IHtmlDocument2(3,4,5) будет уничтожаться только вместе с приложением

Кроме того, как я уже писал в вопросе, всезнающий интернет рекомендует использовать как WB, так и EWB исключительно через их свойство ControlInterface. Но, если при использовании WB еще можно с этим смириться, то заниматься копипастом плюшек EWB, как, например, ExecScriptEx считаю излишним.

Это сообщение отредактировал(а) kami - 13.11.2012, 16:35
PM MAIL WWW   Вверх
gonan
Дата 9.5.2017, 16:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 8
Регистрация: 18.7.2011

Репутация: нет
Всего: нет



Цитата(kami @  13.11.2012,  16:30 Найти цитируемый пост)
После этого - перебилд пакета, в котором TEmbeddedWB сидит.

Аналогично меняется для TWebBrowser, но думаю, что в этом случае нужно будет перезакинуть новую dcu-шку в папку Lib.


Подскажите как сделать "перебилд пакета", Что то не могу сообразить. Сам файл SHDocVw.pas (C:\Program Files (x86)\Embarcadero\Studio\16.0\source\internet) подправил.
Компонент TWebBrowser
Делфи XE8,   Win 8.1 x64

Это сообщение отредактировал(а) gonan - 9.5.2017, 16:18
PM MAIL   Вверх
kami
Дата 14.5.2017, 20:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1806
Регистрация: 25.8.2007
Где: Санкт-Петербург

Репутация: 22
Всего: 72



Цитата(gonan @  9.5.2017,  16:16 Найти цитируемый пост)
Подскажите как сделать "перебилд пакета", Что то не могу сообразить.

Вам нужно сделать что-то из нижеперечисленного:
1. просто закинуть измененный pas-файл в папку с dproj-файлом вашего проекта. Этого будет достаточно. Учтите, что в этом случае вы привязываетесь к конкретной версии Delphi, при компиляции на другой версии потребуется удалить этот файл из папки с проектом, чтобы он не подхватывался автоматом.
2. Включить папку, в которой лежит измененный pas, в Project-Options-LibraryPath. Кажется, этого тоже будет достаточно, но можно попробовать поставить брейкпоинт в этом (обращаем внимание на пути!) файле (например - в конструкторе TWebBrowser) и убедиться, что остановка происходит. Т.е. берется именно измененный файл.
3. Если есть dcu измененного pas-файла, то можно заменить его в library-папке Delphi (нежелательно).

Самый предпочтительный вариант, на мой взгляд - первый. Не стоит без очень весомого основания менять генофонд (т.е. исходные исходники).
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1685 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.