Rust写时复制Cow<T>
写时复制(Copy on Write)技术是一种程序中的优化策略,多应用于读多写少的场景。主要思想是创建对象的时候不立即进行复制,而是先引用(借用)原有对象进行大量的读操作,只有进行到少量的写操作的时候,才进行复制操作,将原有对象复制后再写入。这样的好处是在读多写少的场景下,减少了复制操作,提高了性能。
Rust中对应这种思想的是智能指针Cow<T>
,定义如下:
pub enum Cow<'a, B>
where
B: 'a + ToOwned + 'a + ?Sized,
{
Borrowed(&'a B), //用于包裹引用
Owned(<B as ToOwned>::Owned), //用于包裹所有者
}
可以看到是一个枚举体,包括两个可选值,一个是“借用”,一个是“所有”。具体含义是:以不可变的方式访问借用内容,在需要可变借用或所有权的时候再克隆一份数据。
下面举个例子说明Cow<T>
的应用:
use std::borrow::Cow;
fn abs_all(input: &mut Cow<[i32]>) {
for i in 0..input.len() {
let v = input[i];
if v < 0 {
input.to_mut()[i] = -v;
}
}
println!("value: {:?}", input);
}
fn main() {
// 只读,不写,没有发生复制操作
let a = [0, 1, 2];
let mut input = Cow::from(&a[..]);
abs_all(&mut input);
assert_eq!(input, Cow::Borrowed(a.as_ref()));
// 写时复制, 在读到-1的时候发生复制
let b = [0, -1, -2];
let mut input = Cow::from(&b[..]);
abs_all(&mut input);
assert_eq!(input, Cow::Owned(vec![0,1,2]) as Cow<[i32]>);
// 没有写时复制,因为已经拥有所有权
let mut input = Cow::from(vec![0, -1, -2]);
abs_all(&mut input);
assert_eq!(input, Cow::Owned(vec![0,1,2]) as Cow<[i32]>);
let v = input.into_owned();
assert_eq!(v, [0, 1, 2]);
}
上面这个用例已经讲明了Cow<T>
的使用,下面我们继续探索一下Cow<T>
的实现细节。重点关注to_mut
及into_owned
的实现。
to_mut
:就是返回数据的可变引用,如果没有数据的所有权,则复制拥有后再返回可变引用;into_owned
:获取一个拥有所有权的对象(区别与引用),如果当前是借用,则发生复制,创建新的所有权对象,如果已拥有所有权,则转移至新对象。
impl<B: ?Sized + ToOwned> Cow<'_, B> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
// 如果时借用,则进行复制;如果已拥有所有权,则无需进行复制
match *self {
Borrowed(borrowed) => {
*self = Owned(borrowed.to_owned());
match *self {
Borrowed(..) => unreachable!(),
Owned(ref mut owned) => owned,
}
}
Owned(ref mut owned) => owned, //这里解释了上个例子中,已拥有所有权的情况,无需再复制
}
}
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_owned(self) -> <B as ToOwned>::Owned {
// 如果当前是借用,则发生复制,创建新的所有权对象,如果已拥有所有权,则转移至新对象。
match self {
Borrowed(borrowed) => borrowed.to_owned(),
Owned(owned) => owned,
}
}
}
最后,欢迎关注微信公众号,及时更新最新文章:
Rust写时复制Cow<T>的更多相关文章
- rust漫游 - 写时拷贝 Cow<'_, B>
rust漫游 - 写时拷贝 Cow<'_, B> Cow 是一个写时复制功能的智能指针,在数据需要修改或者所有权发生变化时使用,多用于读多写少的场景. pub enum Cow<'a ...
- JAVA中写时复制(Copy-On-Write)Map实现
1,什么是写时复制(Copy-On-Write)容器? 写时复制是指:在并发访问的情景下,当需要修改JAVA中Containers的元素时,不直接修改该容器,而是先复制一份副本,在副本上进行修改.修改 ...
- fork()和写时复制
写时复制技术最初产生于Unix系统,用于实现一种傻瓜式的进程创建:当发出fork( )系统调用时,内核原样复制父进程的整个地址空间并把复制的那一份分配给子进程.这种行为是非常耗时的,因为它需要: · ...
- Linux的fork()写时复制原则(转)
写时复制技术最初产生于Unix系统,用于实现一种傻瓜式的进程创建:当发出fork( )系统调用时,内核原样复制父进程的整个地址空间并把复制的那一份分配给子进程.这种行为是非常耗时的,因为它需要: · ...
- Linux进程管理——fork()和写时复制
写时复制技术最初产生于Unix系统,用于实现一种傻瓜式的进程创建:当发出fork( )系统调用时,内核原样复制父进程的整个地址空间并把复制的那一份分配给子进程.这种行为是非常耗时的,因为它需要: · ...
- 写时复制和fork,vfork,clone
写时复制 原理: 用了“引用计数”,会有一个变量用于保存引用的数量.当第一个类构造时,string的构造函数会根据传入的参数从堆上分配内存,当有其它类需要这块内存时,这个计数为自动累加,当有类析构时, ...
- 用户空间缺页异常pte_handle_fault()分析--(下)--写时复制【转】
转自:http://blog.csdn.net/vanbreaker/article/details/7955713 版权声明:本文为博主原创文章,未经博主允许不得转载. 在pte_handle_fa ...
- Redis持久化之父子进程与写时复制
之所以将Linux底层的写时复制技术放在Redis篇幅下,是因为Redis进行RDB持久化时,BGSAVE(后面称之为"后台保存")会开辟一个子进程,将数据从内存写进磁盘,这儿我产 ...
- phpCOW机制(写时复制)
写时复制(Copy-on-Write,也缩写为COW),顾名思义,就是在写入时才真正复制一份内存进行修改. COW最早应用在*nix系统中对线程与内存使用的优化,后面广泛的被使用在各种编程语言中,如C ...
随机推荐
- 【hadoop+spark】搭建spark过程
部分转载,已标红源地址,本博客为本菜搭建与爬坑记录,整理版请看: https://blog.csdn.net/the_fool_/article/details/78211166 记录: ====== ...
- laravel扩展包-私有库
创建一个新的laravel项目 composer create-project --prefer-dist laravel/laravel laravel-package "5.5.*&qu ...
- MySQL字符集乱码详解
对于MySQL数据库中出现乱码经常是新手碰到的一个头痛的问题,不知道为什么经常出现中文乱码. 1.对于所谓的数据库中乱码,其实这中说法是错误的,只是我们不认识服务器给我们的字符.其实还是原来的字符?那 ...
- JavaScript的数据类型及其检测
一.什么是数据类型 1.基本类型 值是不可改变的 var name = 'java'; name.toUpperCase(); // 输出 'JAVA' console.log(name); // 输 ...
- web交互方式---ajax
知识不怕旧,关键在于在旧知识的基础上不断创新与提高! 引入一个问题:打开一个浏览器,在地址栏输入一个网址,按下 enter 键到看到整个页面,中间都经历了哪些事情? 这是一个前端的面试题,相信很多朋友 ...
- [Vue 牛刀小试]:第十五章 - 传统开发模式下的 axios 使用入门
一.前言 在没有接触 React.Angular.Vue 这类 MVVM 的前端框架之前,无法抛弃 Jquery 的重要理由,除了优秀的前端 DOM 元素操作性以外,能够非常便捷的发起 http 请求 ...
- HDU 3183:A Magic Lamp(RMQ)
http://acm.hdu.edu.cn/showproblem.php?pid=3183 题意:给出一个数,可以删除掉其中m个字符,要使得最后的数字最小,输出最后的数字(忽略前导零). 思路:设数 ...
- c# bool类型和int类型的互转
项目过程中,会有model的一些属性字段为‘是’或‘否’ 数据库字段一半定义为int,值则是0或1 数据库model转实体类的时候,bool和int可以直接相互转换 false强转int 值就是0 t ...
- 教你用Python制作微信好友背景墙
目录: 0 引言 1 环境 2 代码实现 3 后记 0 引言 前段时间,微信朋友圈开始出现了一种晒照片新形式,微信好友墙,即在一张大图片中展示出自己的所有微信好友的头像. 效果如下图,出于隐私考虑,这 ...
- 番外:深浅copy
进击のpython 深浅copy copy是什么意思? 复制 (又学一个单词!开不开森) 那啥叫复制呢? 百度百科上给的解释是:仿原样品制造 我们曾经有过这样的印象 a = "zhangsa ...