Управление памятью (кешем) 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-й загрузки:
На 10-й загрузке память достигает 270МБ. Это нормально? Как мне это исправить?
Как ни странно, в зависимости от адреса, потребление может колебаться, но оставаться ниже определенного порога (здесь это 90 МБ):
1 ответ
Наткнулись на этот ответ. Цитировать комментарий в источниках QT:
Мертвые ресурсы в кеше хранятся в неочищаемой памяти.
Когда мы удаляем мертвые ресурсы, а не освобождаем их, мы помечаем их память как очищаемую и сохраняем ресурсы до тех пор, пока ядро не освободит очищаемую память.
Оставляя мертвые ресурсы в кеше в грязной резидентной памяти, мы уменьшаем вероятность того, что ядро получит эту память и заставит нас повторно извлечь ресурс (например, когда пользователь нажимает обратно).
Этот вид решает это.. и оживляет мою беспокойную душу.
Следуя советам 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