持久化内存编程及其思考

由于个人工作关系,接触到了持久化内存的概念,觉得这个概念特别有意思,对于未来的编程模型会有很大的影响,甚至,很多的软件(系统软件)优化和架构会有很大的不同,甚至重写。

  • 背景知识

长久以来,我们一直接受的观念是,数据从磁盘读取到内存中,然后CPU从内存对数据进行操作,最后再从内存回写到磁盘保存,完成整个数据的读取,处理和保存。这个观念中,内存容量很小,很贵,磁盘容量很大但是很便宜。从4k访问延时或者吞吐量上来看,内存是要比磁盘快上1000倍或者以上的,然而,随着Intel的黑科技技术傲腾(Optane)诞生,貌似这一假设有可能会被终结。

这玩意可以长得和我们普通内存一样,可以插到内存插槽上,但是容量可以做到单根甚至是512GB,至于价格就不好说了,毕竟官方还没有公布,肯定是会比内存便宜很多。但这玩意也叫PM(Persistent Memory,持久化内存),肯定访问方式和内存还是会有点不太一样,既然是持久化,那么它和磁盘有什么区别么?

通常我们访问磁盘,都需要走文件系统,内核,驱动程序,最后是磁盘本身的操作,当然,磁盘自身的操作时间(延时)会比较长,前面一些操作的时间基本可以被忽略。随着磁盘越来越快,从传统HDD到SSD到PCI-E SSD再到现在的傲腾技术,我们发现“磁”盘自身操作的延时越来越短,那么相比之下,操作系统内核,驱动,文件系统所带来的开销就不能被忽略了,甚至会成为瓶颈,于是就有了新的持久化内存编程模型出来了。

应用程序会有3种模式可以访问傲腾磁盘(插在内存插槽上的傲腾介质):

    • 仍然是传统的文件系统方式访问文件,把傲腾当成普通的SSD用;

      • 这个访问延迟可能会和访问PCI-E SSD不会有太大差别,毕竟延时都浪费再文件系统,内核,驱动上了,更不用谈现在的Java或者C++的文件API,通常都有“缓存”访问,天知道需要在内存里倒腾来倒腾去多少次最后才会写到真正的设备里;
      • 虽然看上去现有代码不需要怎么改动,但是性能优势和PCI-E SSD比,如果没有太大区别,除非其价格和PCI-E SSD可以拼一把,否则这种应用场景通常不会被考虑。
    • 用PM-Aware文件系统(可以持久化)
      • 会跳过文件系统本身的负载(比如文件缓存等),至于PM-Aware文件系统本身的负载有多大,就不得而知了,不知道Intel会不会公布他们的官方性能数据;相信应该是一个不错的数字;
      • 标准文件API这一块或许不是我们通常理解的标准C/C++/Java API,至少这些API底层需要重写或者有PM-Aware文件系统提供新型API;
    • 应用程序直接访问NVDIMM,操作系统内核把它当作内存用,并提供MMU的地址映射关系(可以不持久化)
      • 这块是我觉得让人很振奋的地方,理论上应该是应用程序可以获得一个更大的内存,和普通的内存使用没有什么太大区别,访问数据时,没有了系统调用,文件系统等多个拖累。

相信官方应该是推荐后面两种方案;(https://pmem.io)

  • 个人的一些想法(随想)

    • 单机版应用(包括系统程序)可能需要有对应的修改

      • 比如传统的数据库系统(MySQL/Oracle),大部分的优化是基于数据先写内存,积累到一定量一次性刷到底层存储系统,并保证一致性,但是现在有了PM-aware文件系统,数据存储足够快,数据是可以直接往底层设备上写,并保证其一致性的,内存“缓存”的概念可能会慢慢弱化;
      • 高级语言对应的API和数据结构优化,比如常见的文件操作(java中的StringBuffer,BufferedReader等等) ,或许对于性能而言,反而会导致性能下降,需要开发新的API以支持PM-aware文件系统或者是直接内存访问模式;
    • 分布式应用
      • 传统数据传输走的是以太网(TCP/IP),后面是不是可以用RDMA直接对接PM?也会减少很多内核和驱动的负载。
      • 比如Apache Spark,Kylin这类所谓的In-memory分布式计算引擎,如果有相应改动,会极大提升计算效率,当然会涉及到一些列的数据结构上的优化和修改,让它更适合访问“PM”类型的内存特性;
      • 分布式缓存框架,比如Alluxio,Apache Ignite等也有很多机会获得最好的性能或者延迟。
  • 参考文档

原文地址:https://www.cnblogs.com/cccchhhh/p/9947059.html

时间: 2024-09-30 23:54:04

持久化内存编程及其思考的相关文章

关于Qt半自动内存管理的思考及实验

一时兴起,对Qt感了兴趣,决心想要研究一下. 按网上资料配好环境,Windows 7 64bit + Qt 5.3.1 + VS2010. 根据<C++ GUI Qt4 编程>这本书,写出了第一个程序HelloQt,程序如下: #include <QApplication> #include <QLabel> #if _MSC_VER >= 1600 #pragma execution_character_set("utf-8") #endif

内存编程(所有的情况都有例子)

1. 内存分配方式 1.1 内存分配的几种方式 (1) 从静态存储区域分配. 内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. 初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域. (2) 在栈上创建. 在执行函数时,函数的参数值,内局部变量的存储单元都可以在栈上创建.函数执行结束时这些存储单元自动被释放.栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限. (3) 从堆上分配

【转】Linux共享内存编程实例

原文地址:http://blog.csdn.net/pcliuguangtao/article/details/6526119 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 6

内存管理的思考方式2(ARC下)

所有权修饰符 所有权修饰符共有四种 __strong __weak __unsafe_unretained __sutoreleasing __strong修饰符 是id类型和对象类型默认的所有权修饰符,通过__strong修饰符,不必再次键入retain或者release,完美的满足了'引用计数式内存管理的思考方式': 自己生成的对象自己持有 非自己生成的对象,自己也可以持有 不再需要自己持有的对象时释放 非自己持有的对象无法释放 前两项只需通过对带__strong修饰符的变量赋值即可达成.通

C++中关于new及内存地址的思考

OJ题刷多了,每次都是直接分配内存,那么,你还记得怎么动态分配内存吗? ———————————————————————————————————— 我们知道,使用malloc/calloc等分配内存的函数时,一定要检查其返回值是否为“空指针”(亦即是检查分配内存的操作是否成功),这是良好的编程习惯,也是编写可靠程序所必需的.但是,如果你简单的把这一招应用到new上,那就不一定正确了. C++里,如果new分配内存失败,默认是抛出异常的.如果你想检查new是否成功,应该捕捉异常. try{ int*

编程架构思考

架构,作为程序员是必须的,好的架构提供代码重用的可能性(因为模块化/对象化,而且模块/对象间松散耦合),提供灵活的扩展性(方便加入其他模块和功能),代码维护性和可读性好 . 人类的认识总是连续性上升的,不会飞跃,所以随着时间推移,架构技术也在更新,所以你需要关心一些新的架构技术.新的通信技术.新的框架.例如ROS机器人系统第一代使用master方式,ROS2使用新的DDS技术方式. 其实很多技术的相似的,思想是相似的,你需要自己提炼一下,理解好,实际操作实践一下,从而提高自己水平. <设计模式>

PLC编程再思考之二:SOA

随着AMAZON云服务的成功,许多人知道了BEZOS在AMAZON内部推广WEB SERVICE的故事,从而佩服他的技术眼光和执行力. 如果说AMAZON.COM的成功是因为长尾理论,是对万货商店的技术实现,那么从某个层面来说,AWS(AMAZON WEB SERVICE)是另一种形式的长尾,只不过它销售的是IT服务而不是物理产品. BEZOS基于SOA的思想,通过网络接口和服务打通了AMAZON内部的各种子系统,他把基础设施的接口进一步对外开放,从而形成了AWS的基础功能. 那么,SOA的思想

PLC编程再思考之4 - 面向对象

PLC编程有诸多限制,如: 传统的西门子PLC单个DB的存储容量为64KB. 每次DB结构变更时,都需要编译并重新下载覆盖原DB. 每次DB结构变更时,OPC变量需要重新映射地址. 但有时候我们希望把DB设计得灵活一些,当给PLC增加一些小的元素时,我们不希望覆盖大量的DB. 有时我们希望PLC程序设计得模块化.产品化.基于配置. 在这些应用场景中,我们可以参考面向对象的方法进行PLC编程. 本文以质量安灯实例说明了面向对象的PLC编程方法. 业务需求为: 每个工位配置1条拉绳. 当拉绳拉下时,

由共享内存引发的思考

1.共享内存段被映射进进程空间之后,存在于进程空间的什么位置?共享内存段最大限制是多少? 存在于进程数据段,最大限制是0x2000000Byte 将一块内存映射到两个或者多个进程地址空间.通过指针访问该共享内存区.一般通过mmap将文件映射到进程地址共享区. Linux对共享内存的实现,在2.6采用了内存映射技术.对于内存共享,主要集中在三个内核函数,他们是do_shmat,sys_shmat和sys_shmdt.其中,sys_shmat调用了do_shmat最终实现了共享内存的attach.s