Управление памятью (кешем) QWebView

Вот код, который загружает одну и ту же страницу 10 раз:

app = QApplication([])
event = threading.Event()

def load(url):
  def _load_finished(ok):
    event.set()

  web_view = QWebView()
  web_view.loadFinished.connect(_load_finished)
  event.clear()
  web_view.setUrl(QUrl(url));
  while not event.wait(.05): app.processEvents()
  web_view.loadFinished.disconnect(_load_finished)
  return web_view.page().mainFrame().documentElement()

QWebSettings.setMaximumPagesInCache(0)
QWebSettings.setObjectCacheCapacities(0, 0, 0)

if __name__ == '__main__':
  for i in range(10):
    load('http://www.huffingtonpost.com/')
    QWebSettings.clearMemoryCaches()
    QWebSettings.clearIconDatabase()
    print(i)
  app.exec_()

А вот снимок Process Explorer после 7-й загрузки:

Увеличение памяти с 50 МБ до 170 МБ

На 10-й загрузке память достигает 270МБ. Это нормально? Как мне это исправить?

Как ни странно, в зависимости от адреса, потребление может колебаться, но оставаться ниже определенного порога (здесь это 90 МБ):

Память остается в пределах 70..90MB

1 ответ

Решение

Наткнулись на этот ответ. Цитировать комментарий в источниках QT:

  1. Мертвые ресурсы в кеше хранятся в неочищаемой памяти.

  2. Когда мы удаляем мертвые ресурсы, а не освобождаем их, мы помечаем их память как очищаемую и сохраняем ресурсы до тех пор, пока ядро ​​не освободит очищаемую память.

Оставляя мертвые ресурсы в кеше в грязной резидентной памяти, мы уменьшаем вероятность того, что ядро ​​получит эту память и заставит нас повторно извлечь ресурс (например, когда пользователь нажимает обратно).

Этот вид решает это.. и оживляет мою беспокойную душу.

Следуя советам bms20, я бегу QtWebKit код в отдельном процессе (используя subprocess.Popen) и кешировать веб-ресурсы на диск (PyQt5.QtNetwork.QNetworkDiskCache) для сохранения трафика:

def ExecuteCode(code):
  import os
  os.environ['PYTHONIOENCODING'] = 'utf-8' #Optionally
  from subprocess import Popen, PIPE, STDOUT
  proc = Popen('python.exe', stdin=PIPE)
  out, err = proc.communicate(code.encode())

Часть code содержание:

cache = QNetworkDiskCache()
cache.setCacheDirectory('cache')
web_view = QWebView()
web_view.page().networkAccessManager().setCache(cache)
# Do stuff with web_page
Другие вопросы по тегам