一、引言为什么要优化渲染进程在 Chromium 浏览器中每个渲染进程都占用相当可观的内存资源通常 50-200MB。对于功能丰富的浏览器如 xxx浏览器打开多个标签页或特殊 WebUI 页面时进程数量可能迅速膨胀导致内存占用过高、系统响应变慢。本文将以chrome://desktop_view这个特殊 WebUI 页面的优化为例深入探讨如何通过渲染进程合并策略来显著降低内存占用同时保持功能完整性。二、Chrome 多进程架构回顾在深入优化策略前我们需要理解 Chrome 的进程模型┌─────────────────────────────────────────────┐ │ Browser Process (1个) │ │ - UI 线程、网络线程、存储线程等 │ └─────────────────────────────────────────────┘ │ │ │ ↓ ↓ ↓ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Renderer │ │ Renderer │ │ Renderer │ │ Process 1 │ │ Process 2 │ │ Process 3 │ │ (tab A) │ │ (tab B) │ │ (tab C) │ └─────────────┘ └─────────────┘ └─────────────┘2.1 进程隔离机制Chrome 的Site Isolation特性会将不同站点的页面隔离到不同进程// 默认行为不同站点使用不同进程 https://google.com → Process A https://facebook.com → Process B chrome://settings → Process C这种设计带来安全性提升但也增加了进程数量。2.2 备用渲染进程Spare RendererChrome 会预创建备用渲染进程来加速页面加载// Chrome 源码预先创建空闲进程 void SpareRenderProcessHostManager::MaybeStartSpare() { if (!spare_process_ ShouldHaveSpare()) { spare_process_ RenderProcessHost::CreateSpareProcess(); } }三、优化目标desktop_view 的特殊性chrome://desktop_view是 xxx 浏览器扩展的 WebUI 页面具有以下特点用户可能同时打开多个实例页面间有频繁的通信需求对启动速度要求不高但对内存占用敏感包含大量 iframe 子页面优化目标将多个desktop_view页面合并到同一渲染进程减少 50% 以上的内存占用。四、核心优化策略详解4.1 策略一禁用备用渲染进程问题Chrome 会为desktop_view预创建备用进程但该页面有特殊配置要求不适合使用预创建进程。解决方案在ShouldUseSpareRenderProcessHost函数中拦截。// chrome/browser/chrome_content_browser_client.cc bool ChromeContentBrowserClient::ShouldUseSpareRenderProcessHost( Profile* profile, const GURL site_url) { #ifdef USE_HACK // 禁用 desktop_view 的备用渲染进程 // 原因desktop_view 需要特殊进程配置预创建的进程不符合要求 if (IsDesktopViewWebUIURL(site_url)) { return SpareProcessRefusedByEmbedderReason::DefaultDisabled; } // 同样处理 xxx 内嵌扩展 if (extensions::util::IsxxxOwnerInlineExtensions(site_url.host())) { return SpareProcessRefusedByEmbedderReason::DefaultDisabled; } #endif // ... 其他逻辑 }效果避免为desktop_view浪费内存创建不必要的进程减少约 50-100MB 的内存占用4.2 策略二打破进程锁定Site Isolation问题Chrome 默认会将每个站点锁定到特定进程导致不同desktop_view实例无法共享进程。解决方案在DoesOriginRequireDedicatedProcess中返回false。// chrome/browser/chrome_content_browser_client.cc bool ChromeContentBrowserClient::DoesOriginRequireDedicatedProcess( const GURL effective_url) { #ifdef USE_HACK // desktop_view 不需要专用进程允许与其他站点共享 if (IsDesktopViewWebUIURL(effective_url)) { return false; // 关键禁用进程锁定 } #endif // ... 其他逻辑 return true; // 默认其他站点需要锁定 }原理优化前 desktop_view_1 → Process A (锁定) desktop_view_2 → Process B (锁定即使同源) 优化后 desktop_view_1 → Process A desktop_view_2 → Process A (复用)4.3 策略三跨源进程共享问题即使禁用了锁定Chrome 的其他安全检查仍可能阻止跨源共享。解决方案在ShouldAllowCrossOriginProcessSharing中明确允许。// chrome/browser/chrome_content_browser_client.cc bool ChromeContentBrowserClient::ShouldAllowCrossOriginProcessSharing( const GURL url) { #if defined(USE_HACK) // 明确允许 desktop_view 与跨源页面共享进程 if (IsDesktopViewWebUIURL(url)) { return true; } #endif // ... 其他逻辑 return false; }实际效果// 现在可以安全地共享进程 Process A: - chrome://desktop_view/page1 (chrome scheme) - https://example.com (https scheme) - chrome://desktop_view/page2 (另一个实例)4.4 策略四核心复用逻辑这是最关键的改动直接在进程决策的核心函数ShouldSwapProcessesForNavigation中注入复用逻辑。// content/browser/site_instance_impl.cc bool SiteInstanceImpl::ShouldSwapProcessesForNavigation( const GURL last_successful_url, const GURL dest_url, bool for_outermost_main_frame) { #ifdef USE_HACK // 判断源页面和目标页面是否都是 desktop_view bool src_is_desktop_view last_successful_url.host() desktop_view || last_committed_origin.host() desktop_view; bool dest_is_desktop_view dest_url.host() desktop_view; // 核心复用条件 if (src_is_desktop_view dest_is_desktop_view || src_is_desktop_view !for_outermost_main_frame) { return true; // 不切换进程直接复用 } #endif // ... 原始判断逻辑 }逻辑解析条件说明是否复用src_is_desktop_view dest_is_desktop_view在 desktop_view 页面间跳转✅ 复用src_is_desktop_view !for_outermost_main_framedesktop_view 中的 iframe 导航✅ 复用其他情况按原始逻辑判断视情况关键细节for_outermost_main_frame标识是否为主框架最外层iframe 复用父进程避免子页面创建额外进程4.5 策略五延迟进程创建问题提前创建进程可能浪费资源特别是对于不常用的页面。解决方案延长渲染进程的延迟创建时间。// chrome/browser/chrome_content_browser_client.cc base::TimeDelta ChromeContentBrowserClient::GetRendererProcessDelay( Profile* profile, const GURL site_url) { #if defined(USE_HACK) // desktop_view 使用 350 秒的超长延迟 if (IsDesktopViewWebUIURL(site_url)) { return base::Seconds(350); // 接近 6 分钟 } if (extensions::util::IsxxxOwnerInlineExtensions(site_url.host())) { return base::Seconds(350); } #endif // 默认延迟仅 2 秒 return base::Seconds(2); }优化效果延迟 350 秒意味着即使用户打开了页面渲染进程也不会立即创建适合低频访问的页面配合其他策略进一步减少进程占用4.6 辅助函数统一识别 desktop_view// chrome/browser/ui/webui/top_chrome/webui_url_utils.h #if defined(USE_HACK) bool IsDesktopViewWebUIURL(const GURL url); #endif // chrome/browser/ui/webui/top_chrome/webui_url_utils.cc #if defined(USE_HACK) bool IsDesktopViewWebUIURL(const GURL url) { return url.SchemeIs(content::kChromeUIScheme) url.DomainIs(desktop_view); } #endif这个函数提供了统一的判断标准方便其他模块调用。五、优化效果分析5.1 进程数量对比场景优化前进程数优化后进程数节省1 个 desktop_view110%3 个 desktop_view3166.7%5 个 desktop_view 2 个普通页面7357.1%包含 iframe 的 desktop_view2-3150-66%5.2 内存占用估算假设单个渲染进程内存占用80MB 优化前5个 desktop_view 5 × 80MB 400MB 优化后5个共享1个进程 1 × 80MB 80MB 节省内存320MB5.3 代码改动总结修改文件 1. chrome/browser/chrome_content_browser_client.cc (5处改动) 2. content/browser/site_instance_impl.cc (1处核心改动) 3. chrome/browser/ui/webui/top_chrome/webui_url_utils.{h,cc} (新增函数) 核心逻辑 - 禁用备用进程避免浪费 - 打破进程锁定允许共享 - 强制复用进程核心策略 - 延迟创建减少空闲进程六、技术风险与权衡6.1 安全性降低风险禁用 Site Isolation 可能增加侧信道攻击如 Spectre的风险。缓解措施仅对特定可信的 WebUI 页面禁用保持其他所有站点的隔离保护使用宏USE_HACK控制不影响主线代码6.2 稳定性风险风险一个页面崩溃会影响所有共享进程的页面。实际场景// 如果 Process A 崩溃 Process A (包含 5 个 desktop_view 页面) 崩溃 → 所有 5 个页面同时消失用户体验下降权衡接受此风险因为 desktop_view 页面本身比较稳定减少进程数带来的内存收益大于稳定性损失6.3 调试复杂度增加问题多个页面共享进程时调试变得更复杂。解决方案添加详细日志记录进程分配决策在 Chrome 的about://process-internals页面查看进程分配七、最佳实践总结基于这个优化案例总结出渲染进程合并的通用策略7.1 适合合并的场景同源或同站点的页面对安全性要求不高的内部页面用户可能同时打开多个实例的页面包含大量 iframe 的页面7.2 不适合合并的场景敏感页面银行、支付等不同来源的第三方页面稳定性要求极高的页面可能存在内存泄漏的页面7.3 优化优先级text1. 禁用备用进程最简单收益直接 2. 同源页面复用安全风险小 3. iframe 复用父进程减少子框架进程 4. 跨源共享需要仔细评估安全性八、总结通过这套优化策略我们成功地将多个chrome://desktop_view页面合并到单个渲染进程在保持功能完整的前提下减少了 50-70% 的进程数节省了数百 MB 的内存。核心经验理解 Chrome 的进程模型是优化的基础精确识别优化目标避免影响其他页面在正确的决策点注入逻辑如ShouldSwapProcessesForNavigation权衡安全与性能谨慎禁用保护机制充分的测试验证确保不会引入稳定性问题这个案例展示了如何深入 Chromium 源码进行性能优化希望能为读者提供有价值的参考。对于其他浏览器的优化也可以借鉴类似的思路识别特殊页面 → 打破隔离限制 → 强制进程复用 → 延迟资源创建。