- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用多个小型临时对象的并发数据结构。这些对象很多都是相同大小的。因此,为了减少对内存分配器的负担,我一直在使用线程本地映射将对象存储为<size, list>
元组。
当线程需要对象时,它将在进入分配器之前检查映射中是否有合适的对象。这可以很好地工作并显着提高了性能,但是很容易出现这样的问题:超时一个线程将其整个池丢失给其他线程,从而迫使它分配新对象。如果应用程序运行时间很长,我会发现一些线程具有大的内存池。
为了解决这个问题,我想在线程本地池和分配器之间添加一个共享内存池。由于结构的数量和结构的大小在编译时是恒定的,因此我认为应该以某种方式使用宏将每个大小映射到数组位置。允许更轻松的内存管理。
这是我目前的解决方案
#define RC_OBJECT_COUNT 0
#define ADD_RC_OBJECT(object) \
#ifndef RC_MAP_``sizeof(object)''
#define RC_OBJECT_TEMP RC_OBJECT_COUNT \
#undefine RC_OBJECT_COUNT \
#define RC_OBJECT_COUNT RC_OBJECT_TEMP+1 \
#define RC_MAP_``sizeof(object)'' RC_OBJECT_TEMP
#endif
最佳答案
我编写的代码的工作方式类似于您在讨论的内容,但是我并未尝试使用预处理器宏。
我的代码只有一个“对象管理器”和一个小的API。我程序中要获取对象的任何部分都调用一个API函数,即“注册函数”,即“我想请求具有以下特征的对象”。 register函数返回一个句柄。然后,有一个函数GetObject()
,它将句柄作为参数,并返回一个指向对象的指针。使用对象完成代码后,将使用ReleaseObject()
函数获取指向该对象的指针。
对于每个不同的对象,都有一个链接列表,我称之为“就绪列表”。代码总是从列表的开头插入和删除(因为一个未初始化的对象和另一个未初始化的对象一样好;它们的大小都相同)。我的代码是单线程的,所以我没有任何锁定问题,但是对于多线程,我需要在每个就绪列表上加一个锁。 (但是,插入或删除链表的开头非常快,因此没有线程需要很长的锁。)
出于我的目的,程序的不同部分可以共享对象,因此我对每个对象都有一个引用计数。 ReleaseObject()
将减少引用计数,当它变为零时,会将对象放在适当的就绪列表中。GetObject()
返回的句柄实际上只是指向链表结构的指针。
在我的代码中,如果存在对GetObject()
的调用,并且就绪列表为空,则会自动调用malloc()
并创建并返回一个新对象。 register函数需要一个指向要使用malloc()
创建对象的函数的指针,一个指向要使用free()
释放对象的函数的指针以及一个指向“健全性检查”函数的指针(因为我喜欢我的程序可以在调用assert()
的运行时),以及任何类似对象大小的参数。
如果程序的多个部分注册了他们想要相同类型的对象,则对象管理器会注意到这一点,并只返回第一次调用注册已设置的就绪列表的句柄。现在,他们在一个就绪列表中共享对象。
这听起来可能很复杂,但是我花了很长时间才建立起来,并且效果很好。如果就绪列表上没有对象,则对象管理器知道只是调用存储在就绪列表结构中的函数指针,以获取新对象,然后将其返回。
我在程序中发现的最常见的错误:完成对象后无法调用ReleaseObject()
。然后,该程序发生内存泄漏,并频繁调用malloc()
,并且在嵌入式平台上内存不足并死亡。通常,很容易注意到这一点,并在ReleaseObject()
中添加适当的调用。
编辑:(针对评论中的问题)对象管理器保留了一系列不同的对象管理结构实例。每个结构存储三个函数指针:指向“new”函数的指针,指向“delete”函数的指针,指向“健全性检查”函数的指针;少数在调用"new"函数时传递给它们的值(例如,所需缓冲区的大小);以及对象链接列表的头部。当代码调用“register”函数时,对象管理器将检查该数组中的任何位置是否具有与“register”相同的值(3个函数指针和少数几个值)。如果找到相同的值,则对象管理器返回一个指向该对象管理器结构实例的指针。如果找不到相同的值,则对象管理器将这些值复制到数组中的下一个可用结构中,并返回指向该结构的指针。
这意味着我的“注册”函数在被管理的各种不同种类的对象中的数量为O(N),但是对于我的应用程序,只有大约4种不同种类的对象,因此我从未尝试对其进行优化。我的“get”函数是O(1),因为它具有指向正确的对象管理器结构的指针,并且从链接列表的开头删除是恒定时间操作。
对象管理器结构的数组由malloc()
分配,如果注册了其他对象类型,则代码可以调用realloc()
来增加内存。
在我的应用程序中,我不需要“取消注册”操作,但是如果有的话,它将涉及释放该就绪列表中的所有对象,并将该对象管理器阵列中的该位置标记为未使用。
我的应用程序是音频处理引擎,它在处理音频时从不希望调用malloc()
,因为malloc()
可能会决定重新组织空闲块列表或其他内容,并花一些时间,并且音频播放可能会出现故障。在开始播放之前,引擎具有“初始化”阶段,其中代码调用“寄存器”功能,并且所有音频缓冲区都已分配;然后在运行时,缓冲区会飞走并进入准备就绪列表。它确实运行良好,并且我已经在低功耗DSP芯片上运行了它,没有任何问题。
关于c - 实现各种大小的结构的基于数组的内存池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19665092/
我在具有 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
我是一名优秀的程序员,十分优秀!