QWebView 的内存(缓存)管理

Posted

技术标签:

【中文标题】QWebView 的内存(缓存)管理【英文标题】:QWebView's memory (cache) management 【发布时间】:2013-11-22 02:40:59 【问题描述】:

这是下载同一页面 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_()

这是第 7 次下载后 Process Explorer 的快照:

第 10 次下载内存达到 270MB。 这是正常的吗?我该如何解决?

奇怪的是,根据地址,消耗可能会波动,但会保持在一定的阈值以下(这里是 90MB):

【问题讨论】:

【参考方案1】:

偶然发现this 的答案。在 QT 资源中引用 comment:

    缓存中的死资源保存在不可清除的内存中。

    当我们修剪死资源而不是释放它们时,我们将它们的内存标记为可清除并 保留资源直到 内核回收可清除内存。

通过离开缓存 脏常驻内存中的死资源,我们降低了 内核声称该内存并迫使我们重新获取 资源(例如,当用户按下回时)。

这种方式解决了它..并重温我不安的灵魂。

按照 bms20 的建议,我在单独的进程中运行 QtWebKit 代码(使用 subprocess.Popen)并将 Web 资源缓存在磁盘上(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

【讨论】:

感谢您的提问和回答。是否可以从主解释器访问 web_view 对象(将其添加到布局中)? @user3479125,“主解释器”==主程序?如果是这样,那么我认为不会,因为code 在单独的进程中运行(通过Popen)。但是,您可以通过将其(内容)打印到控制台来返回子进程页面的内容。子进程退出后,内容将存储在out。此外,似乎整个 QtWebKit 正在被 QtWebEngine 取代。没试过,不过内存消耗可能没有问题。

以上是关于QWebView 的内存(缓存)管理的主要内容,如果未能解决你的问题,请参考以下文章

Linux 内核 内存管理内存管理架构 ③ ( Linux 内核中的内存管理模块 | 页分配器 | 不连续页分配器 | 内存控制组 | 硬件设备内存管理 | MMU | 页表缓存 | 高速缓存 )

Linux 内核 内存管理内存管理架构 ③ ( Linux 内核中的内存管理模块 | 页分配器 | 不连续页分配器 | 内存控制组 | 硬件设备内存管理 | MMU | 页表缓存 | 高速缓存 )

单片机模块化程序: 数据缓存封包-内存管理实现

操作系统--文件管理2

Redis系列1—内存管理缓存淘汰策略

架构设计 | 缓存管理模式,监控和内存回收策略