bigywater.tech
爬虫工程 · 55

headless Chrome:启动耗时与内存占用

用浏览器渲染页面比 requests 重得多:启动要多久、每个标签页占多少内存、一个页面里的图片和样式要不要加载,这些决定了你的爬虫一台机器能同时开多少页面。这篇在本机量一量 headless Chrome 的启动耗时、进程与内存,以及资源拦截的收益。

396 对 24 ms
启动浏览器与新开一个标签页加载简单页面的耗时(中位数)
约 +109 MiB
每多开一个标签页,进程树 RSS 之和增加的量(共享内存重复计算,偏大)
2052 → 1 KiB
拦截图片和样式表后,同一个页面的传输量

启动

实测 · 本机执行输出
  调试端口可用:中位 396 ms(各次 [457, 556, 396, 366, 361]);新建标签页并加载简单页面:中位 24 ms(各次 [26, 45, 24, 24, 22])

从启动进程到调试端口可用约 396 ms,之后新开一页并加载简单页面只要约 24 ms。所以浏览器应当启动一次、反复开页。

内存

实测 · 本机执行输出
      标签页数     进程数      RSS 之和  进程构成
         0       9     1177 MiB  {'浏览器主进程': 1, 'GPU 进程': 1, '工具进程': 2, '渲染进程': 5}
         1      10     1325 MiB  {'浏览器主进程': 1, 'GPU 进程': 1, '工具进程': 2, '渲染进程': 6}
         5      14     1778 MiB  {'浏览器主进程': 1, 'GPU 进程': 1, '工具进程': 2, '渲染进程': 10}
        10      19     2266 MiB  {'浏览器主进程': 1, 'GPU 进程': 1, '工具进程': 2, '渲染进程': 15}

刚启动就有 9 个进程(浏览器主进程、GPU 进程、工具进程和几个渲染进程),RSS 之和约 1177 MiB;每多一个标签页多一个渲染进程,多约 109 MiB。把各进程的 RSS 相加会重复计算共享内存,实际占用比这个数小,但趋势是线性增长。

进程与站点

实测 · 本机执行输出
  打开的页面                              进程数     渲染进程数      RSS 之和
  1 个站点 × 1 页                     10         6     1309 MiB
  同一站点再开 4 页(共 5 页)               14        10     1841 MiB
  4 个不同站点各 1 页(再加 4 页)            18        14     2360 MiB
  再加 5 个不同站点各 1 页                 23        19     3009 MiB

在这个实验里,新标签页不管是同一站点还是不同站点,渲染进程数都是每页 +1(通过 CDP 新建的标签页)。我没有测同一标签页内的 iframe 或 window.open 打开的页面是否共享渲染进程。

拦截资源

实测 · 本机执行输出
  不拦截:加载 31 ms,传输 2052 KiB,被拦截的请求 0 个
  拦截 *.png 和 *.css:加载 13 ms,传输 1 KiB,被拦截的请求 21 个

用 Network.setBlockedURLs 拦截图片和样式表,传输量从 2052 KiB 降到 1 KiB,加载从 31 ms 降到 13 ms。拦截样式和图片可能让依赖它们的页面逻辑(布局判断、懒加载)失效,这点没有测。

分步演示

启动耗时与内存
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 arm64 / Python 3.14.8 / requests 2.34.2 / aiohttp 3.14.3 / lxml 6.1.1(系统 Python);所有请求只发给本机自己起的测试服务器(127.0.0.1,端口 9960 以上,不访问任何真实网站);服务器可以按实验需要制造延迟、断连、压缩、重定向等行为,并记录收到的原始请求;计时用 time.perf_counter,数字每次运行会有小幅抖动。Chrome 154.0.8037.98 通过 pcdp.py 启动(--headless=new、独立 --user-data-dir、--no-sandbox、--disable-gpu、--disable-extensions 等),调试端口只监听 127.0.0.1;进程树与 RSS 来自 ps -axo pid=,ppid=,rss=,command=,从 Chrome 主进程起递归取所有子孙进程,按命令行里的 --type 区分种类;RSS 之和重复计算共享页,偏大;冷启动 5 次,拦截对比每组 5 次取中位数;每次实验后按唯一的 user-data-dir 结束这批 Chrome 进程
    • 没有验证:Linux 容器里的资源占用与 --disable-dev-shm-usage 等参数;chrome-headless-shell 这种精简版的开销;--single-process、--renderer-process-limit 等降低进程数的参数;真实复杂页面的内存;Firefox 或 WebKit 的开销;用 footprint 等工具得到更准确的内存;页面关闭后内存是否释放(下一篇讨论复用)
    京ICP备2026067502号-1京公网安备11010502063487号