深入对比:Chromium的base::RefCounted与std::shared_ptr——从线程安全到性能优化

Chromium入坑之旅:base库之timer时间操作学习 base::TimeDelta s=秒,ms=毫秒,us=微秒,ns=纳秒; 1s=1000ms=1000000us=1000000000ns; int main() { std::cout << "------TimeDelta------\n"; std::cout << L"FromDays(天):" << base::TimeDelta::FromDays(1)<<"\n"; std::cout << L"FromHours(小 阅读详情

1. 引言:为什么需要对比两者?

在现代C++开发中,引用计数(Reference Counting)是一种常见的内存管理技术,用于自动管理对象的生命周期。C++标准库提供了std::shared_ptr作为通用的引用计数智能指针,而Chromium项目则自定义了一套引用计数系统(base::RefCounted和base::RefCountedThreadSafe)。

为什么Chromium不直接使用std::shared_ptr?

  1. 性能优化:Chromium对内存和CPU效率要求极高,std::shared_ptr的全局原子操作可能带来不必要的开销。

  2. 线程模型控制:Chromium的线程模型(如UI线程、IO线程、GPU线程)需要更细粒度的线程安全控制。

  3. 内存占用优化:std::shared_ptr的控制块(Control Block)会增加额外内存开销,而Chromium的base::RefCounted将引用计数直接嵌入对象,减少内存占用。

本文将深入对比base::RefCounted(Chromium风格)和std::shared_ptr(C++标准库)的设计差异,涵盖线程安全、性能优化、内存模型、功能扩展等方面,帮助开发者理解它们的适用场景。


2. 线程安全性:最关键的差异

2.1 base::RefCountedThreadSafe(线程安全版本)

Chromium提供了两种引用计数模板:

  • base::RefCounted(非线程安全,引用计数无原子保护)

  • base::RefCountedThreadSafe(线程安全,引用计数使用原子操作)

关键特点
  1. 仅保证引用计数的原子性

    • AddRef()和Release()使用std::atomic保证线程安全。

    • 但对象的析构仍需开发者控制(通常需回到创建线程析构,避免竞态条件)。

  2. 适用于跨线程共享对象

    • 例如网络模块、异步任务等需要多线程访问的场景。

示例代码
class NetworkResource : public base::RefCountedThreadSafe<NetworkResource> {
 public:
  void Fetch() { /* 跨线程操作 */ }
};

// 跨线程传递
scoped_refptr<NetworkResource> resource = base::MakeRefCounted<NetworkResource>();
io_thread.PostTask(FROM_HERE, base::BindOnce(&NetworkResource::Fetch, resource));

2.2 std::shared_ptr(全局线程安全)

std::shared_ptr的设计目标是通用性,因此它的线程安全策略更加严格:

  1. 控制块(Control Block)完全线程安全

    • 强引用计数、弱引用计数、删除器(Deleter)均使用原子操作。

  2. 对象析构可能发生在任意线程

    • 最后一个shared_ptr释放时,对象析构可能不在创建线程(可能影响线程局部存储)。

示例代码
auto resource = std::make_shared<NetworkResource>();
std::thread([resource] { 
  resource->Fetch();  // 可能在任何线程析构
}).detach();

2.3 对比总结

维度base::RefCountedThreadSafestd::shared_ptr
引用计数原子性仅AddRef/Release原子控制块全原子(强/弱引用+删除器)
析构线程安全性需手动控制(如PostTask回原线程)可在任意线程析构
适用场景需要精细线程控制的系统(如浏览器)通用跨平台代码

关键结论:

  • 如果需要在特定线程析构对象(如UI线程),base::RefCountedThreadSafe更合适。

  • 如果希望自动管理析构线程,std::shared_ptr更方便,但可能牺牲性能。


3. 性能优化:内存与原子操作开销

3.1 内存占用对比

实现方式base::RefCountedstd::shared_ptr
存储位置引用计数嵌入对象(无额外开销)额外控制块(多2个指针大小)
内存占用更小更大(除非使用make_shared优化)
std::shared_ptr的内存布局
+-------------------+      +-------------------+
| shared_ptr<T>     | ---> | Control Block      |
| - 对象指针        |      | - 强引用计数       |
+-------------------+      | - 弱引用计数       |
                           | - 删除器           |
                           | - 对象内存(可选) |
                           +-------------------+
  • 如果使用new T + shared_ptr,对象和控制块分开分配(2次内存分配)。

  • 如果使用make_shared,对象和控制块可能合并(1次分配)。

base::RefCounted的内存布局
+-------------------+
| RefCounted<T>     |
| - ref_count_      |  // 引用计数直接存储在对象内
| - 其他成员        |
+-------------------+
  • 无额外控制块,内存更紧凑。


3.2 原子操作开销

操作base::RefCounted(非线程安全)base::RefCountedThreadSafestd::shared_ptr
引用计数增减普通整数操作(无锁)原子操作(std::atomic)原子操作
适用场景单线程(如UI线程)多线程共享通用多线程

性能影响:

  • 原子操作(如fetch_add)比普通操作慢约2-10倍(取决于CPU架构)。

  • Chromium的base::RefCounted允许在单线程场景禁用原子操作,提升性能。


4. 功能扩展:弱引用与循环引用处理

4.1 std::shared_ptr的weak_ptr机制

std::weak_ptr用于解决循环引用问题,例如:

struct Node {
  std::shared_ptr<Node> next;
  std::weak_ptr<Node> prev;  // 避免循环引用
};
  • 优点:自动检测对象是否存活,避免内存泄漏。

  • 缺点:控制块需额外维护弱引用计数,增加内存开销。

4.2 Chromium的替代方案

Chromium未内置弱引用,但提供了base::WeakPtrFactory:

class Document : public base::RefCounted<Document> {
 public:
  base::WeakPtr<Document> GetWeakPtr() { 
    return weak_factory_.GetWeakPtr(); 
  }
 private:
  base::WeakPtrFactory<Document> weak_factory_{this};
};
  • 缺点:需手动管理,不如weak_ptr方便。

  • 优点:无额外控制块,内存更高效。


5. 设计哲学:为何Chromium选择自定义实现?

  1. 极致性能优化

    • 浏览器对内存和CPU敏感,std::shared_ptr的通用性带来额外开销。

  2. 明确线程模型

    • Chromium的线程任务需精细控制(如UI线程仅允许特定操作)。

  3. 减少依赖

    • 自定义实现避免受标准库实现的限制(如ABI兼容性问题)。


6. 最佳实践:如何选择?

场景推荐方案
高性能单线程对象base::RefCounted
跨线程共享对象base::RefCountedThreadSafe
通用代码,需弱引用支持std::shared_ptr + weak_ptr
内存敏感型应用Chromium风格(无控制块开销)

7. 总结

维度base::RefCountedstd::shared_ptr
线程安全可定制(安全/非安全)全局原子(可能性能损失)
内存开销更小(无控制块)更大(控制块+弱引用)
适用场景高性能、线程模型明确的系统通用代码、需要弱引用

最终建议:

  • 如果是Chromium开发或高性能中间件,优先使用base::RefCounted。

  • 如果是通用C++项目,std::shared_ptr更方便。


延伸阅读:

Chromium源码—base基础库说明 Chromium 基础库概览 Chromium 基础库包括的内容十分繁杂,我把其中的主要部分大致分为以下几类: 1. 容器类型 Chromium 的代码主要使用 STL 容器类型,比如 std::vector,std::list,另外 GCC 和 MSVC 提供的 STL 扩展容器类型 hash_map 和 hash_set 也在 Chromium 中使用,不过统一放在 base 名字空间里... 阅读详情

相关推荐

Chromium入坑之旅:base库之Files文件操作学习

base::FilePath path = base::FilePath(L"C:\Users\JinLuSa\Desktop\T.txt"); base::File fIle = base::File(const FilePath& path, uint32_t flags); flags取值(可以用 “|”) enum Flags { FLAG_OPEN = 1 <&...

jshiya的博客 1940

chromium中的base库 ipc进程间通信 ChannelProxy分析

1. chromium进程通信的基本模式 进程间通信,叫做IPC(Inter-Process Communication),在Chrome不多的文档中,有一篇就是介绍这个的,在这里。Chrome最主要有三类进程,一类是Browser主进程,我们一直尊称它老人家为老大;还有一类是各个Render进程,前面也提过了;另外还有一类一直没说过,是Plugin进程,每一个插件,在Chrome中都是以进程的形式呈现,等到后面说插件的时候再提罢了。Render进程和Plugin进程都与老大保持进程间的通信,Rende.

sway913的博客 2180

跟Google学写代码--Chromium/base--windows_version源码学习及应用

Chromium是一个伟大的、庞大的开源工程,很多值得我们学习的地方。 前面写道: 《跟Google学写代码–Chromium/base–stl_util源码学习及应用》今天与大家分享的就是Chromium下base中的windows_version,对于你的win32应用程序一定会有很多的帮助。1 定义version枚举enum Version { VERSION_PRE_XP = 0,

一蓑烟雨任平生 也无风雨也无晴 1万+

Chromium 基础库使用说明

转自:https://www.zybuluo.com/rogeryi/note/56894 Chromium 基础库使用说明 chromiumbase 作者: 易旭昕 (@roger2yi) Chromium 提供了一个类似 WTF 的基础库,甚至包含了更多的内容。这个基础库在 Blink 之外被广泛使用(Blink 里面仍然使用的是 WTF),了解它的使用对我们实际的代码编写是十分重要的。本文主要介绍 Chromium 基础库包括的主要内容,并详细说明一些重要类型的使用方式。如果需要了解某...

along 1979

chromium中的同步机制

chromium中的同步机制我们可以在base\synchronization中看到chromium实现的同步机制,具体的有condition_variable, Lock,Spin_wait, Waitable_event,这几个比较常见的方式。LockLock的使用Lock的实现位于 base\synchronization\Lock*.* 中,在synchronization文件夹中,主要是实

飞鸟的专栏 2697

chromium base::bind 用法

Chromium 提供了 base::Bind 和模版类型 base::Callback 对函数回调提供了支持,下面是一个简单的使用例程,将一个全局函数绑定到一个 Callback 对象,并通过 Callback.Run 调用这个函数: int Return5() { return 5; } base::Callback<int(void)> func_cb = base::Bind(&Return5); LOG(INFO) << func_cb.Run(); // Pr.

juruiyuan111的专栏 2256

Chromium base库介绍

AtExitManager 类似于linux下的atexit,注册退出清理函数,不过base库的实现机制是利用了C++的RAII。void exit_first(void *data) { LOG(INFO) << "first"; }void exit_last(void *data) { LOG(INFO) << "second"; }void exit_task(void *data) { L

zyfforlinux 7376

chromium-base:修剪过的 Chromium 基础库,基于 zcbenzbase-minimal 和 mini_chromium,但有更多有用的东西。 目前仅在 linux 和 windows 下工作

最小基数 修剪 Chromium 的基础库,只需将base.gyp:base添加到您的base.gyp:base文件即可使用它们。 建造 $ cd chromium-base $ gyp --depth=. base.gyp -I src/build/common.gypi $ ninja -C out/Debug

chromium basethread使用

不会写博客。慢慢学着写吧。将chromium的base模块分离出来,使用thread方式 #include "stdafx.h" #include #include "./base/threading/thread.h" #include "./base/bind.h" #include "./base/callback.h" #include "./base/message_

moonmuzi的博客 750

思科9117AP从零配置EWC模式实战:Wi-Fi6网络搭建避坑指南

本文详细介绍了思科9117AP在Wi-Fi6网络环境下配置EWC模式的实战指南,涵盖镜像准备、网络环境配置、模式转换步骤及高级运维技巧。通过EWC模式,企业可实现控制器与AP的一体化部署,显著降低成本和简化运维,特别适合中小企业Wi-Fi6网络搭建。

weixin_28318011的博客 332

[Linux外设驱动详解]RK3588 U-Boot网络功能深度分析

本文深入分析了RK3588平台上U-Boot的网络功能实现,主要内容包括: 网络架构:详细剖析了从硬件层到协议层的完整网络栈架构,包括GMAC驱动、TFTP/NFS启动、网络命令等关键组件。 驱动实现:重点介绍了RK3588 GMAC驱动结构,包含关键数据结构、专用操作函数集、设备树兼容性配置和GRF寄存器设置。 功能实现:详细说明了驱动初始化流程、RGMII速度适配机制以及PHY接口配置过程。 高级特性:涵盖了网络启动功能、镜像更新和MAC地址传递到Linux内核的机制。 文档通过代码片段和流程图清晰展示

Just Linux! 1111

Chromium Base库中常用的功能

Chromium Base库中常用的功能

silenceye的专栏 895

LLC混合滞回控制 vs 电压模/电流模:UCC25640x仿真对比与选型指南

在开关电源设计中,LLC谐振变换器的环路补偿是核心难点。传统电压模控制(VMC)和电流模控制(CMC)在LLC拓扑上存在环路增益漂移、动态响应慢等局限。混合滞回控制通过滞回比较器直接调制开关频率,并融合输出电压与谐振腔电流信息,实现了自适应环路增益和快速瞬态响应。该技术显著提升轻载效率与动态性能,适用于高密度适配器、快充及车载充电机等场景。本文基于UCC25640x系列,通过仿真对比三种控制策略,为工程选型与调试提供实践参考。

weixin_33925615的博客 333

chromium - 测试程序使用base空间的类

上个实验,只在chromium中加了一个标准的win32console的工程,现在实验了,使用base命令空间的类的工程修改。不只是程序要包含base类的头文件, Z:\chromium\src\base\test\BUILD.gn 也要修改,依赖base命名空间,才能编译过。

博客标题不能为空 741

开放词汇目标检测(Open-Vocabulary Object Detection, OVOD)综述

综上,大多数工作均基于CLIP预训练的图像编码器和文本编码器。GlIP为解决目标检测任务提供了先例,后续很多工作常与目前较为广泛使用的目标检测网络结构相结合,从而构建新的开放词汇目标检测器。如ViLD基于Mask R-CNN、RegionCLIP基于R-CNN、VLDet和BARON基于Faster R-CNN。更具有创新性的工作是Detic,提出了使用图像分类的数据集来对目标检测器的分类头进行训练。

yangsn0719的博客 4399

告别外置天线!手把手教你用HFSS仿真设计一个20x40mm的433MHz PCB蛇形天线

本文详细介绍了如何使用HFSS仿真工具设计一个20x40mm的433MHz PCB蛇形天线,解决物联网设备小型化中的天线集成难题。通过对比外置天线与PCB天线的性能差异,深入解析蛇形天线的电磁学原理,并提供从建模到优化的全流程实战指南,帮助工程师实现高效、低成本的微型化天线设计。

weixin_30606461的博客 430

chromium的base源码阅读之Timer

简介 本文介绍chromium的base的timer的源码,地址在https://github.com/chromium/chromium/tree/master/base,我们讨论在base中是如何实现一个timer的。 windows下的timer 我们先来看看windows下如何实现一个简单的timer的 class A { public: void static CALLBACK ...

leapmotion的博客 2287

避坑指南:OpenWRT改AP模式必做的5个关键设置(DHCP/防火墙/WAN口处理)

本文详细解析了将OpenWRT设备从路由模式切换为AP模式时,必须完成的五个关键设置步骤。核心在于理解AP模式本质是带无线的智能交换机,需彻底关闭DHCP服务、调整防火墙策略、正确桥接所有物理接口(包括WAN口处理),并集成无线网络,以确保设备能透明接入主路由网络,避免出现设备隔离或无法互访等常见问题。

t1u2v的博客 732

chromium中的TimeTicks和TimeDelta

在chromium中,base::TimeDelta定义在文件中,}FromXxx的函数在中没有定义,只有中有,所以include的base/time/time.h是不能直接适用的:可以直接适用。

技术笔记 993

用Excel或WPS做两独立样本的T检验

一般情况下收集数据时常用的是Excel或者WPS,但统计时却用SPSS等软件进行统计学分析,经常很多人找不到SPSS的安装包,或者苦于正版激活或忘记教程,其实Excel或WPS自带函数就足够了,均数、标准差以及统计检验都是一个函数而已。解释:先做F检验,如果F>0.05就做T检验,Ttset里的数据为两组的数据的比较,结果如下。A组的均数计算 =AVERAGE(B2:B6)A组的标准差计算 =STDEV(B2:B6)B组的标准差计算=STDEV(B7:B19)分组 数值 A组均数 A组标准差 p值。

Mrrunsen的博客 6751

在 ABAP Push Channel 里玩转 Detached Client:用 Attach Handle 把 WebSocket 连接交接给业务逻辑

摘要:本文介绍了ABAP Push Channels (APC)中的Detached Client技术,该技术通过将WebSocket连接建立与后续处理分离,实现更高效的实时通信。核心流程包括创建连接、使用connect_and_detach交接连接、以及通过attach handle重新附着发送消息。文章还探讨了PCP协议和AMC技术在企业级推送场景中的应用,并通过示例代码展示了Detached Client的具体实现方式。这种设计解决了传统轮询的资源浪费问题,特别适用于生产线监控、客服系统等需要服务端主

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 2308

漫谈 C++ 的各种检查

以下文章来源于BOTManJL,作者BOT ManWhat you don't use you don't pay for. (zero-overhead princi...

腾讯技术工程 1408

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

chromium的base源码阅读之Callback一

简介 本文描述下chromium使用base库中的callback,相关代码位于base库的根目录下的callback及callback相关,bind及bind相关的,本系列本人只是简单说一下自己的感受,有些存在的问题还望大家一块讨论。 相关base库timer讲解可参考 chromium的base源码阅读之Timer. callback是chromium自己封装的回调函数,需要配合bind使用,...

leapmotion的博客 1249

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Chromium Blink项目最新技术报告和下一步发展方向

摘要:BlinkOn3会议11月份刚在Google的MountainView办公地点举行,本文选取了BlinkOn3的几个话题,如为Blink绘图瘦身的SlimmingPaint,多优先级的Blink调度器,Oilpan垃圾回收机制,用JavaScript开发新的DOM特性等等,和大家一起分享Blink项目目前取得的进展和下一步发展方向。

Chromium技术分享 7022

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Chromium base库使用的例子

Chromium base库很丰富,里面包含了google对Chromium的架构思想,很多东西可以学习学习。为了能完美的阅读代码,把libbase.a用起来,自己写写小例子GDB一把,对理解代码有如虎添翼的功效。 怎么架起来,看以下小例子: #include "build_config.h" #include "at_exit.h" #include "bind.h" void exit_...

weijun23的专栏 1987

学习使用chromium里的线程类(1)

Chromium就好比是一个宝藏,里面有很多宝贝。其中我最喜欢的宝贝是base库和ipc(进程间通信) 。这两件宝贝在大型项目开发中会给我们带来极大的帮助。所以值得我们去花大功夫研究、学习的。在来到我现在所在的公司前,我对chromium的了解几乎没有,那时我常常认为

jujueduoluo的专栏 1950
上一篇: 深入理解 depot_tools:Chromium 源码开发全流程(fetch/gclient/git cl 使用详解与踩坑经验)
下一篇: 从 base 出发:深入理解 Chromium 自研基础库的体系结构与设计哲学(兼谈为什么不直接用 STL)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ปรัชญา แค้วคำมูล

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值