背景
在内存受限设备中,经常会遇到这样的问题:
如何在多个相互竞争的组件之间分配内存?
例如,在一部普通的手机中,有游戏、音乐播放、图形界面等组件,每个组件对内存的需求都是“贪婪”的,并且这种“贪婪”是有道理的,即一般情况下,组件得到越多的内存,则该组件的运行表现越良好。但是如果放任每一个组件都去试图尽量多地分配内存,那么系统的总内存将入不敷出。
让我们撇开数量众多的嵌入式设备不说。即便面对如今内存动辄上G的智能手机,我们依然应当谨慎地为各个组件分配内存。
模式
让我们考虑如下的模式:
为每个组件设置限额,超过限额的请求将不予响应。
我们将它称之为:内存限额。
内存限额的目标是防止某一个组件独霸内存。
更深入的探讨
现在,你也许会有这样的疑问,如何确定每个组件的内存限额?
首先需要明确的是,内存限额模式对于内存需求有变化的组件才有意义,如C++中的vector,java中的arraylist。
内存限额的分配应当遵循“小富即安”的原则,即限额应当确保该组件的正常运行即可。有一点原则必须明确:即便某一个组件运行性能特别出色,其他组件也可能成为整个系统性能的瓶颈。内存和CPU的故事,想必无需我再赘述。
适用的场景
警觉的朋友会对这个模式产生疑问。是的,这个模式是一个容易浪费系统内存的模式。即便系统中有空闲内存,某一个组件也可能因为自身的限额而失败。
这个模式适用于负荷稳定、几乎没有弹性负荷的场景,实现简单是它的最大优点。
实现
终于可以脱离纸上谈兵了(*^__^*)
有以下几种方法可供选择,以实现该模式。
- 重写内存管理函数。比如,你可以重写c++中的new和delete方法。
- 分离的heap。可以让每个组件各自使用分离的heap。windows系统的操作系统支持该操作,至少我知道的,windows CE是肯定支持的。
- 分离的进程。大部分的linux允许开发者为每一个进程指定一个内存限额。很方便,不是吗?
示例
下面的C++代码限制MemoryRestrictedClass及其子类所使用的内存总量。如果超额分配,会触发内存不足异常。
class MemoryRestrictedClass{
public:
enum { LIMIT_IN_BYTES = 10000 };
static size_t totalMemoryCount;
void* operator new(size_t aSize);
void* operator delete{void* anItem, size_t aSize};
};
size_t MemoryRestrictedClass::totalMemoryCount = 0;
// 实现new操作符
void* MemoryRestrictedClass::operator new(size_t aSize){
// 如果分配后内存大于限额,抛出内存不足异常
if ( totalMemoryCount + aSize > LIMIT_IN_BYTES )
throw (bad_alloc());
// 更新计数器,增加之
totalMemoryCount += aSize;
return malloc(aSize);
}
// 实现delete操作符
void* MemoryRestrictedClass::operator delete(void* anItem, size_t aSize){
// 更新计数器,减少之
totalMemoryCount -= aSize;
free((char*)anItem);
}
下面来看看相对不那么“强大”的java语言如何实现内存限额模式。
是的,java没有提供内存分配和销毁函数,然而限制某一个类的实例数量还是可以做到的,只需要提供一个static的计数器即可。
问题又来了,java如何获取占用内存已被归还?我们可以使用finalize()函数来拦截这一动作,然而,大多数java虚拟机finalize的效率不佳,因此,以下代码仅仅是一个示范,绝非推荐做法(具体请参看Gosling所著的《java语言规范》一书)。
Class RestrictedClass{
// 最大可分配10个实例
static final int maxNumberOfInstances = 10;
// 伟大的计数器又出现了
static int numberOfInstances = 0;
public RestrictedClass(){
numberOfInstances++;
if ( numberOfInstances > maxNumberOfInstances ){
// 出师未捷身先死,直接被回收掉...
System.gc();
throw new OutOfMemoryException("只能创建10个对象");
}
}
public void finalize(){
--numberOfInstances;
}
}
预告
下一篇,介绍小型接口。
分享到:
相关推荐
侯捷 内存受限系统之软件开发,不用怎么介绍了吧,经典书籍啊 侯捷 内存受限系统之软件开发,不用怎么介绍了吧,经典书籍啊
Thinking Small The Processes for Creating Small Memory Software This paper describes some process patterns for teams to follow when creating software to run in limited memory....It is a draft version ...
适用于有限存储系统(即手持式和专用微型计算设备)的一组连贯且易于使用的模式。 包括C ++和Java中的示例。
在内存受限的情况下,将数据流按时序进行分割,且用B -树进 行区间分块索引,之后利用RFID数据流统计分布特性进行复杂事件查找与匹配,避免了频繁搜索外存,极大地 降低了I/O开销并提高了吞吐量。此外,进行了相关的...
Oracle 12c受限模式 只读模式 静默模式 延迟模式
1 / 2 图书馆管理系统——课程设计 数据库课程设计 图书馆管理系统——课程设计全文共30页,当前为第1页。图书馆管理系统 图书馆管理系统——课程设计全文共30页,当前为第1页。 目录 一、系统背景与概述 2 二、系统...
本工具可以在64位windows操作系统上解除32位应用程序单进程内存1G的限制
11.3内存访问的模式 11.3.1 标记——清扫技术,使用标记位图和延迟清扫 11.3.2 节点复制垃圾收集 11.3.3 渐进式垃圾收集 11.3.4 避免读取 11.4 改进cache性能的标准方法 11.4.1 cache的容量 11.4.2 块大小 11.4.3 ...
UbuntuKylin14.04LTS系统初始配置——更新系统并安装版权受限程序.pdf
———————————————————————————————————————————————————— 第二步,修改客户端。 单机版中的连接字串符: 取消:CONN.OPEN "provider=Microsoft.jet.OLEDB.4.0;...
This paper describes some UI design patterns to use when creating software to run in limited memory. It is a draft version of a chapter to add to the authors’ book Small Memory Software, and ...
172-387-路网条件受限下过江通道两侧衔接规划研究-word资料.pdf
论文研究-停车受限条件下多模式交通网络动态拥挤收费.pdf, 在一个多起始单终点的交通网络上, 本文研究当终点处停车空间不足时, 如何通过在路段瓶颈处实施拥挤收费实现...
深入浅出密码学——常用加密技术原理与应用Christof Paar,Jan Pelzl 本书拥有的诸多特征...此外,本书还包含了许多非常新的主题,比如针对受限的应用而优化的轻量级加密( 例如RFID标签或智能卡) ,或新的操作模式。
受限环境下DNS服务发现的研究,易品,魏更宇,物联网的飞速发展将使得数以百亿计的受限设备连入当今的互联网,发现受限网络节点和其相关服务是未来网络必不可少的重要功能。互
由于DRAM的功耗、容量密度受限于工艺瓶颈,无法满足内存计算快速增长的内存需求,因此研发人员将目光逐渐移向了新型的非易失性内存(non-volatile memory,NVM).由DRAM和NVM共同构成的异质内存,具有低成本、低功耗、高...
11.3内存访问的模式 11.3.1 标记——清扫技术,使用标记位图和延迟清扫 11.3.2 节点复制垃圾收集 11.3.3 渐进式垃圾收集 11.3.4 避免读取 11.4 改进cache性能的标准方法 11.4.1 cache的容量 11.4.2 块大小 11.4.3 ...
联想工程师专用小工具 win8_10无线连接受限优化工具V2.45.1联想工程师专用小工具 win8_10无线连接受限优化工具V2.45.1联想工程师专用小工具 win8_10无线连接受限优化工具V2.45.1联想工程师专用小工具 win8_10无线...
提出一种获取潜在语义的受限非负矩阵分解方法.通过在非负矩阵分解方法的目标函数 上增加3个约束条件来定义受限非负矩阵分解方法的目标函数 ,给出求解受限非负矩阵分解方 法目标函数的迭代规则 ,并证明迭代规则的收敛...