文档详情

std::string 的 Copy-on-Write:不如想象.pdf

发布:2017-05-23约4.99千字共4页下载文档
文本预览下载声明
std ::string 的 Copy-on-Write:不如想象中美好 Copy-on-w rite (以下简称COW )是一种很重要的优化手段。它的核心思想是懒 处理多个实 体的资源请求,在多个实体之间共享某些资源,直到有实体需要对资源进行修改时,才真正为该 实体分配私有的资源。 COW技术的一个经典应用在于Linux 内核在进程fork时对进程地址空间的处理。由于fork产生 的子进程需要一份和父进程内容相同但完全独立的地址空间,一种做法是将父进程的地址空间完 全复制一份,另一种做法是将父进程地址空间中的页面标记为”共享的“ (引用计数+1),使子进程 与父进程共享地址空间,但当有一方需要对内存中某个页面进行修改时,重新分配一个新的页 面 (拷贝原内容),并使修改进程的虚拟地址重定向到新的页面上。 COW技术有哪些优点呢? 1. 一方面减少了分配 (和复制)大量资源带来的瞬间延迟 (注意仅仅是latency ,但实际上该 延迟被分摊到后续的操作中,其累积耗时很可能比一次统一处理的延迟要高,造成throughput下降 是有可能的) 2. 另一方面减少不必要的资源分配。 (例如在fork的例子中,并不是所有的页面都需要复制, 比如父进程的代码段 .code)和只读数据 .rodata)段,由于不允许修改,根本就无需复制。而如 果fork后面紧跟exec 的话,之前的地址空间都会废弃,花大力气的分配和复制只是徒劳无功。) COW 的思想在资源管理上被广泛使用,甚至连STL中的std ::string 的实现也要沾一下边。陈硕 的这篇博客 《C++工程实践 (10 ):再探std ::string》充分探讨了各个STL实现中对std ::string 的实 现方式,其中g++ std ::string和Apache stdcxx就使用了COW技术。 (其他对std ::string 的实现包 括eager copy和small string optimization,建议参考原博客,图文并茂十分清楚) 很简单一段代码,就能查看当前std ::string实现是否使用了COW : 如果实现使用了COW,那么第一个比较会返回true,第二个比较会返回false 。经测 试libstdc++ gcc 4.5)确实使用了COW,而查看STL中string 的源码,也确实采用了引用计数的手段 。 但要注意,std ::string 的lazy-copy行为只发生在两个string对象之间的拷贝构造,赋值 和assign )操作上,如果一个string 由const)char*构造而来,则必然会分配内存和进行复制,因 为string对象并不知道也无权控制char*所指内存的生命周期。 实际上,std ::string c = a.data )确实是一种在字符串赋值时禁止COW行为的方法。 看起来使用COW管理string来减少不必要的拷贝似乎很有效,然而在多数C++ STL实现中, 只有寥寥两种使用了COW,而同样著名的Visual C++ 2010)和clang libc++却不约而同抛弃 了COW,选择了SSO (small string optimization,足够小的字符串直接放在对象本身的栈内存中 ,避免了向Heap动态请求内存的开销)。 SSO对小字符串的高效是原因之一 (程序中通常会有大量的短字符串),而COW本身的缺陷 更是原因之一。 更多精彩攻略访问 1 更是原因之一。 一、性能:for thread-safety ! 想要实现COW,必须要有引用计数 (reference count )。string初始化时rc=1,每当该string 赋值给了其他sring,rc++。当需要对string做修改时,如果rc1,则重新申请空间并复制一份原字 符串的拷贝,rc– 。当rc减为0时,释放原内存。 基于”共享“和”引用“计数的COW在多线程环境下必然面临线程安全的问题。那么: std ::string是线程安全的吗? 在stackoverflow上对这个问题的一个很好的回答:是又不是。 从在多线程环境下对共享的string对象进行并发操作的角度来看,std ::string不是线程安全的, 也不可能是线程安全
显示全部
相似文档