- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我的应用程序目前对性能至关重要,每帧请求 3-5 百万个对象。最初,为了让一切顺利进行,我new'd
一切,让应用程序工作并测试我的算法。该应用程序是多线程的。
一旦我对性能感到满意,我就开始为我的对象创建一个内存管理器。显而易见的原因是内存碎片和浪费。由于内存碎片,应用程序在崩溃之前无法继续运行超过几帧。我检查了内存泄漏并且知道应用程序没有泄漏。
所以我开始使用 TBB 的 concurrent_queue
创建一个简单的内存管理器。队列存储允许应用程序使用的最大元素集。需要新元素的类从队列中弹出元素。根据英特尔的文档,try_pop
方法是无锁的。就内存消耗而言,这非常有效(尽管仍然存在内存碎片,但几乎没有以前那么多)。我现在面临的问题是,根据我自己的简单分析器,应用程序的性能已经降低了大约 4 倍(我无法访问商业分析器,也不知道任何可以在实时应用程序上工作的工具......任何建议将不胜感激)。
我的问题是,是否存在可扩展的线程安全内存池。池的一个 must-have
功能是快速回收元素并使其可用。如果没有,任何提示/技巧性能明智?
编辑:我想我会多解释一下这个问题。我可以轻松地初始化 n 个数组,其中 n 是线程数,并开始使用每个线程的数组中的对象。这在某些情况下非常有效。就我而言,我也在回收元素(可能是每一帧),它们可以在数组中的任何点被回收;即它可能来自数组的 elementArray[0]
或 elementArray[10]
或 elementArray[1000]
部分。现在,我将拥有一个由可以使用的元素和正在使用的元素组成的零散元素数组:(
最佳答案
正如评论中所说,不要获得线程安全的内存分配器,为每个线程分配内存。
正如您在更新中所暗示的那样,您需要有效地管理免费/使用中。这是一个非常简单的问题,给定一个常量类型并且没有并发。
例如(在我脑海中,未经测试):
template<typename T>
class ThreadStorage
{
std::vector<T> m_objs;
std::vector<size_t> m_avail;
public:
explicit ThreadStorage(size_t count) : m_objs(count, T()) {
m_avail.reserve(count);
for (size_t i = 0; i < count; ++i) m_avail.push_back(i);
}
T* alloc() {
T* retval = &m_objs[0] + m_avail.back();
m_avail.pop_back();
return retval;
}
void free(T* p) {
*p = T(); // Assuming this is enough destruction.
m_avail.push_back(p - &m_objs[0]);
}
};
然后,对于每个线程,都有一个 ThreadStorage 实例,并根据需要调用 alloc() 和 free()。
您可以添加智能指针来为您管理调用 free(),如果成本高,您可以优化构造函数/析构函数调用。
你也可以看看 boost::pool。
更新:
跟踪已使用的事物以便可以在第二遍中进行处理的新要求对我来说似乎有点不清楚。我认为您的意思是当对象的主要处理完成时,您不需要释放它,而是保留对它的引用以进行第二阶段处理。有些对象只会被释放回池中,不会用于第二阶段处理。
我假设您想在同一个线程中执行此操作。
作为第一步,您可以向 ThreadStorage 添加这样的方法,并在您想要对所有未发布的 T 实例进行处理时调用它。不需要额外的簿记。
void do_processing(boost::function<void (T* p)> const& f) {
std::sort(m_avail.begin(), m_avail.end());
size_t o = 0;
for (size_t i = 0; i != m_avail.size(); ++i) {
if (o < m_avail[i]) {
do {
f(&m_objs[o]);
} while (++o < m_avail[i]);
++o;
} else of (o == m_avail[i])
++o;
}
for (; o < m_objs.size(); ++o) f(&m_objs[o]);
}
假设没有其他线程正在使用 ThreadStorage 实例,这是合理的,因为它在设计上是线程本地的。再次,在我的脑海中,未经测试。
关于c++ - 线程安全内存池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5737344/
我在具有 2CPU 和 3.75GB 内存 (https://aws.amazon.com/ec2/instance-types/) 的 c3.large Amazon EC2 ubuntu 机器上运
我想通过用户空间中的mmap-ing并将地址发送到内核空间从用户空间写入VGA内存(视频内存,而不是缓冲区),我将使用pfn remap将这些mmap-ed地址映射到vga内存(我将通过 lspci
在 Mathematica 中,如果你想让一个函数记住它的值,它在语法上是很轻松的。例如,这是标准示例 - 斐波那契: fib[1] = 1 fib[2] = 1 fib[n_]:= fib[n] =
我读到动态内存是在运行时在堆上分配的,而静态内存是在编译时在堆栈上分配的,因为编译器知道在编译时必须分配多少内存。 考虑以下代码: int n; cin>>n; int a[n]; 如果仅在运行期间读
我是 Python 的新手,但我之前还不知道这一点。我在 for 循环中有一个基本程序,它从站点请求数据并将其保存到文本文件但是当我检查我的任务管理器时,我发现内存使用量只增加了?长时间运行时,这对我
我正在设计一组数学函数并在 CPU 和 GPU(使用 CUDA)版本中实现它们。 其中一些函数基于查找表。大多数表占用 4KB,其中一些占用更多。基于查找表的函数接受一个输入,选择查找表的一两个条目,
读入一个文件,内存被动态分配给一个字符串,文件内容将被放置在这里。这是在函数内部完成的,字符串作为 char **str 传递。 使用 gdb 我发现在行 **(str+i) = fgetc(aFil
我需要证实一个理论。我正在学习 JSP/Java。 在查看了一个现有的应用程序(我没有写)之后,我注意到一些我认为导致我们的性能问题的东西。或者至少是其中的一部分。 它是这样工作的: 1)用户打开搜索
n我想使用memoization缓存某些昂贵操作的结果,这样就不会一遍又一遍地计算它们。 两个memoise和 R.cache适合我的需要。但是,我发现缓存在调用之间并不可靠。 这是一个演示我看到的问
我目前正在分析一些 javascript shell 代码。这是该脚本中的一行: function having() { memory = memory; setTimeout("F0
我有一种情况,我想一次查询数据库,然后再将整个数据缓存在内存中。 我得到了内存中 Elasticsearch 的建议,我用谷歌搜索了它是什么,以及如何在自己的 spring boot 应用程序中实现它
我正在研究 Project Euler (http://projecteuler.net/problem=14) 的第 14 题。我正在尝试使用内存功能,以便将给定数字的序列长度保存为部分结果。我正在
所以,我一直在做 Java 内存/注意力游戏作业。我还没有达到我想要的程度,它只完成了一半,但我确实让 GUI 大部分工作了......直到我尝试向我的框架添加单选按钮。我认为问题可能是因为我将 JF
我一直在尝试使用 Flask-Cache 的 memoize 功能来仅返回 statusTS() 的缓存结果,除非在另一个请求中满足特定条件,然后删除缓存。 但它并没有被删除,并且 Jinja 模板仍
我对如何使用 & 运算符来减少内存感到非常困惑。 我可以回答下面的问题吗? clase C{ function B(&$a){ $this->a = &$a; $thi
在编写代码时,我遇到了一个有趣的问题。 我有一个 PersonPOJO,其 name 作为其 String 成员之一及其 getter 和 setter class PersonPOJO { priv
在此代码中 public class Base { int length, breadth, height; Base(int l, int b, int h) { l
Definition Structure padding is the process of aligning data members of the structure in accordance
在 JavaScript Ninja 的 secret 中,作者提出了以下方案,用于在没有闭包的情况下内存函数结果。他们通过利用函数是对象这一事实并在函数上定义一个属性来存储过去调用函数的结果来实现这
我正在尝试找出 map 消耗的 RAM 量。所以,我做了以下事情;- Map cr = crPair.collectAsMap(); // 200+ entries System.out.printl
我是一名优秀的程序员,十分优秀!