我迷迷糊糊关于这似乎是存在于所有数据的方法对象,如QList,QQueue,QHash...
我甚至调查到目前为止我可以看到它的源代码,这是
inline void setSharable(bool sharable) {
    if (!sharable) detach(); d->sharable = sharable;
}
在qlist.h中(第117行).
但是,它有什么样的影响上QList,QQueue,QHash...?它是否与线程有关(听起来合理)?
感谢您的回答,如果您有实际知识,请回答.
如何获取稀疏块大小并检查Linux中reiserfs/ext3中稀疏文件中给定偏移量处是否存在数据?
我想用它来实现使用FUSE的简单的copy-on-write块设备.
或者我最好将位图保存在单独的文件中?
var absences = [0, 2, 0, 4, 0, 3, 1, 0]
let midpoint = absences.count / 2
var firstHalf = absences.prefix(upTo: midpoint)
let secondHalf = absences.suffix(from: midpoint)
来自Apple的报价:
firstHalf和secondHalf slice都不会分配任何新的存储空间.相反,每个都提供了缺席数组存储的视图.
当我尝试变异firstHalf如下:
firstHalf[1] = 19
firstHalf更改的值但原始数组absences保持不变(firstHalf[1]等于19,而absences[1]等于2)那么在后台会发生什么.我是否通过改变数组切片来实例化一个新数组?提前致谢.
我正在尝试创建仍然使用Qt的隐式共享的多态类型的QList .
我的具体用例是将QList中保存的项传递给QtConcurrent :: mapped.这些项都来自一个基类,它定义了QtConcurrent :: mapped将调用的虚函数.大多数存储的数据将是特定于子类的.线程开始后可以编辑这些项目,留下两个主要选项,锁定或复制数据.我不想坚持使用锁,因为这会消除使用额外线程的大部分目的.同样制作我的数据的完整副本似乎也是不可取的.相反,我想使用Qt的隐式共享来制作我更改的数据项的副本,但是我似乎无法制作仍然使用隐式共享的多态类型的QList.
QList默认使用隐式共享,所以乍一看似乎我们已经完成了.
QList<Base> list;
Derived derived_obj;
list.append(derived_obj); // this fails
但是,将子类附加到父类的QList将不起作用,标准答案是使用QSharedPointers的QList到基类,它将接受附加指向子类的指针.
QList<QSharedPointer<Base> > pointer_list;
QSharedPointer<Derived> derived_pointer;
pointer_list.append(derived_pointer); // this works but there is no copy-on-write
如果我使用QSharedPointers的QList,那么将复制QSharedPointer而不是我的多态类,这意味着我已经失去了我想要的写时复制功能.
我还研究了使用QSharedDataPointers的QList .
QList<QSharedDataPointer<Base> > data_pointer_list;
QSharedDataPointer<Derived> derived_data_pointer;
list.append(derived_data_pointer); // this fails
但是像QList本身一样,QSharedDataPointers似乎不接受多态类型.
我在这里阅读了关于Swift中Array的copy-on-write实现.
与标准库中的所有可变大小集合一样,数组使用copy-on-write优化.在您修改其中一个副本之前,阵列的多个副本共享相同的存储.当发生这种情况时,被修改的数组将使用其自身的唯一拥有副本替换其存储,然后对其进行修改.有时应用优化可以减少复制量.
我想知道你是否有任何关于哪种结构支持写时复制的信息.
所以,我想知道 - 我将如何在内核中实现复制内存页面(struct page)并利用写时复制机制而不是立即传输数据.
现在,我通过将用户地址转换为页面来allocate_pages复制页面,使用内核分配所需的页面数量,使用它们进行复制copy_pages,然后最终使用它们将它们映射到所需的区域install_special_mapping.这有效,但我觉得这可以使用写时复制机制进行优化.
根据GCC 5发布更改页面(https://gcc.gnu.org/gcc-5/changes.html):
默认情况下,使用小字符串优化而不是写入时复制引用计数来启用std :: string的新实现
我决定检查它并写了一个简单的程序:
int main()
{
    std::string x{"blah"};
    std::string y = x;
    printf("0x%X\n", x.c_str());
    printf("0x%X\n", y.c_str());
    x[0] = 'c';
    printf("0x%X\n", x.c_str());
    printf("0x%X\n", y.c_str());
}
结果是:
0x162FC38
0x162FC38
0x162FC68
0x162FC38
请注意,x [0] ='c'后x.c_str()指针会发生变化.这意味着在写入时复制内部缓冲区.所以似乎COW仍然在工作.为什么?
我在Ubuntu上使用g ++ 5.1.0.
在Linux中,只要分支了一个进程,父进程的内存映射就会被克隆到子进程中。实际上,出于性能原因,这些页面被设置为写时复制 -最初它们是共享的,并且如果两个进程之一在其中之一上进行写操作,则将其克隆(MAP_PRIVATE)。
这是获取正在运行的程序状态的快照的一种非常常见的机制-您进行了分叉,这使您可以在该时间点(一致)查看进程的内存。
我做了一个简单的基准测试,其中包含两个部分:
在某些情况下(机器/体系结构/内存位置/线程数/ ...),我能够比线程写入数组早得多地完成复制。
但是,当子进程退出时,htop我仍然可以看到大部分CPU时间都花在了内核上,这与它在父进程写入页面时用于处理写时复制是一致的。
以我的理解,如果标记为写时复制的匿名页面是由单个进程映射的,则不应复制该页面,而应直接使用它。
我如何确定这确实是在复制内存上花费的时间?
如果我是对的,如何避免这种开销?
在现代 C ++ 中,基准测试的核心如下。
定义WITH_FORK以启用快照;保留undefined可禁用子进程。
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <numaif.h>
#include <numa.h>
#include <algorithm>
#include <cassert>
#include <condition_variable>
#include <mutex>
#include <iomanip>
#include <iostream>
#include <cmath>
#include <numeric>
#include <thread>
#include <vector>
#define ARRAY_SIZE 1073741824 // 1GB …我想SmallVec与 一起使用Cow。我试过这个:
use smallvec::SmallVec;
use std::borrow::Cow;
fn main() {
    let s = "hello world".to_owned();
    let mut s = Cow::Borrowed(s.as_bytes());
    clear_subslice(&mut s, 2, 6);
}
fn clear_subslice(text: &mut Cow<'_, [u8]>, start: usize, end: usize) {
    match text {
        Cow::Borrowed(v) => {
            if !v[start..end].iter().all(|&c| c == b' ') {
                let mut v = SmallVec::from_slice(v);
                v[start..end].iter_mut().for_each(|c| *c = b' ');
                *text = Cow::Owned(v);
            }
        }
        Cow::Owned(v) => {
            v[start..end].iter_mut().for_each(|c| *c = b' ');
        }
    }
}
error[E0271]: type mismatch …根据定义将数组或字典设为值类型,但只有当对其的引用尝试修改它时才实际复制它,这是一个不错的想法,但它让我在多队列/线程上下文中保持警惕。我需要知道:
Swift 的写时复制功能是线程安全的吗?例如:如果我在一个队列上创建一个数组并将其传递到另一个队列,那么任一队列修改它而另一个队列可能正在读取或修改它是否安全?由于根据定义,复制是在数组引用传递到第二个队列时进行的,因此我们是否可以假设 Swift 工程师做了正确的事情并以队列安全的方式实现了写入时复制?
我发现了这个古老的讨论,它看起来很权威,但是是双向的! https://developer.apple.com/forums/thread/53488
一些可靠的声音说它是线程安全的,其他人则说不是。我想这可能是因为在 Swift 的某些早期版本中不是这样,而在 Swift 5 中可能是这样。这里有人确切了解 Swift 5 吗?
下面是一些示例代码来说明该问题:
func func1()
{
    var strings1: [String] = ["A", "B", "C"]
    var strings2: [String] = strings1   // array not actually copied
    queue.async()
    {
        strings2.append("D")
    }
    print(strings1[0])    // is this reference thread-safe?
    strings1.append("E")  // is this modification thread-safe?
}
copy-on-write ×10
c++ ×4
swift ×3
linux ×2
memory ×2
qlist ×2
qt ×2
arrays ×1
c++11 ×1
collections ×1
filesystems ×1
gcc ×1
linux-kernel ×1
performance ×1
polymorphism ×1
rust ×1
string ×1
struct ×1
value-type ×1