CN113515412B - 非易失性内存检查点生成方法、装置和电子设备 - Google Patents
非易失性内存检查点生成方法、装置和电子设备 Download PDFInfo
- Publication number
- CN113515412B CN113515412B CN202110712594.9A CN202110712594A CN113515412B CN 113515412 B CN113515412 B CN 113515412B CN 202110712594 A CN202110712594 A CN 202110712594A CN 113515412 B CN113515412 B CN 113515412B
- Authority
- CN
- China
- Prior art keywords
- memory
- check point
- application program
- stub routine
- stub
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Active
Links
- 230000015654 memory Effects 0.000 title claims abstract description 230
- 238000000034 method Methods 0.000 title claims abstract description 72
- 230000006870 function Effects 0.000 claims abstract description 50
- 230000008569 process Effects 0.000 claims description 25
- 238000005457 optimization Methods 0.000 claims description 24
- 238000013507 mapping Methods 0.000 claims description 19
- 238000004590 computer program Methods 0.000 claims description 11
- 238000003860 storage Methods 0.000 claims description 10
- 238000003780 insertion Methods 0.000 claims description 5
- 230000037431 insertion Effects 0.000 claims description 5
- 238000004891 communication Methods 0.000 claims 1
- 230000007246 mechanism Effects 0.000 abstract description 15
- 238000010586 diagram Methods 0.000 description 17
- 238000011084 recovery Methods 0.000 description 13
- 238000012545 processing Methods 0.000 description 9
- 230000002085 persistent effect Effects 0.000 description 8
- 238000012986 modification Methods 0.000 description 7
- 230000004048 modification Effects 0.000 description 7
- 238000004458 analytical method Methods 0.000 description 6
- 238000005516 engineering process Methods 0.000 description 4
- 239000002699 waste material Substances 0.000 description 4
- 230000002776 aggregation Effects 0.000 description 3
- 238000004220 aggregation Methods 0.000 description 3
- 238000013459 approach Methods 0.000 description 3
- 238000004364 calculation method Methods 0.000 description 3
- 238000013500 data storage Methods 0.000 description 3
- 230000008030 elimination Effects 0.000 description 3
- 238000003379 elimination reaction Methods 0.000 description 3
- 230000002688 persistence Effects 0.000 description 3
- 230000003068 static effect Effects 0.000 description 3
- 230000008901 benefit Effects 0.000 description 2
- 230000008859 change Effects 0.000 description 2
- 238000004883 computer application Methods 0.000 description 2
- 238000012546 transfer Methods 0.000 description 2
- 230000004075 alteration Effects 0.000 description 1
- 230000004888 barrier function Effects 0.000 description 1
- 230000015556 catabolic process Effects 0.000 description 1
- 238000006243 chemical reaction Methods 0.000 description 1
- 238000011161 development Methods 0.000 description 1
- 230000000694 effects Effects 0.000 description 1
- 238000002474 experimental method Methods 0.000 description 1
- 239000004744 fabric Substances 0.000 description 1
- 239000012530 fluid Substances 0.000 description 1
- 239000012634 fragment Substances 0.000 description 1
- 238000002372 labelling Methods 0.000 description 1
- 238000004519 manufacturing process Methods 0.000 description 1
- 230000003287 optical effect Effects 0.000 description 1
- 230000001052 transient effect Effects 0.000 description 1
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/07—Responding to the occurrence of a fault, e.g. fault tolerance
- G06F11/14—Error detection or correction of the data by redundancy in operation
- G06F11/1402—Saving, restoring, recovering or retrying
- G06F11/1415—Saving, restoring, recovering or retrying at system level
- G06F11/1438—Restarting or rejuvenating
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F12/00—Accessing, addressing or allocating within memory systems or architectures
- G06F12/02—Addressing or allocation; Relocation
- G06F12/0223—User address space allocation, e.g. contiguous or non contiguous base addressing
- G06F12/023—Free address space management
- G06F12/0238—Memory management in non-volatile memory, e.g. resistive RAM or ferroelectric memory
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/30—Creation or generation of source code
- G06F8/31—Programming languages or programming paradigms
- G06F8/315—Object-oriented languages
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/40—Transformation of program code
- G06F8/41—Compilation
- G06F8/44—Encoding
- G06F8/447—Target code generation
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F2201/00—Indexing scheme relating to error detection, to error correction, and to monitoring
- G06F2201/82—Solving problems relating to consistency
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F2212/00—Indexing scheme relating to accessing, addressing or allocation within memory systems or architectures
- G06F2212/10—Providing a specific technical effect
- G06F2212/1041—Resource optimization
- G06F2212/1044—Space efficiency improvement
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- General Engineering & Computer Science (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Software Systems (AREA)
- Quality & Reliability (AREA)
- Computing Systems (AREA)
- Retry When Errors Occur (AREA)
Abstract
本申请实施例中提供了一种非易失性内存检查点生成方法、装置和电子设备,所述方法包括:应用程序编译时,通过编译器插桩插件在应用程序中插入桩例程调用指令,并生成可执行应用程序;在运行可执行应用程序时,根据调用的桩例程获取当前纪元产生的脏内存块;在调用检查点函数时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在非易失性内存中生成检查点。本申请通过插入桩例程的机制能够对页面中被修改的内存区域进行定位,获得脏内存块,并将脏内存块写入到非易失性内存中,减少了写入非易失性内存的检查点的数据量,降低了检查点生成和运行时的开销,同时也能缩短检查点的生成时间。
Description
技术领域
本申请涉及软件技术领域,具体地,涉及一种非易失性内存检查点生成方法、装置和电子设备。
背景技术
长期以来,绝大多数的计算机应用程序都是通过内存进行高效处理,使用磁盘进行数据存储。非易失性内存的出现改变了固有的存储体系结构,越来越多的应用程序开始使用非易失性内存进行处理及数据存储。但是构建可恢复应用程序需要开发者合理使用缓存刷新指令(如CLWB)和内存栅栏指令(如SFENCE),正确实现故障一致性(Crash-consistency)机制,以保证非易失性内存中的数据始终处于一致状态。
因此,目前大部分应用程序都是通过检查点-恢复(Checkpoint-Recovery,CR)技术来实现应用程序的故障恢复,周期性地将计算得到的中间状态写入检查点(Checkpoint),并将检查点保存在非易失性内存中,在应用程序发生故障后,以非易失性内存中保存的最近的检查点为起点继续计算,从而实现应用程序的故障恢复。
在目前的检查点-恢复机制中,增量检查点的粒度是固定的(4KB或2MB),这个粒度远大于非易失内存所支持的读写粒度。也就是说,即使只有页面的一部分被修改,整体页面仍然会全部被写入非易失内存,导致检查点在生成和运行时开销过大,造成带宽浪费的现象。
发明内容
本申请实施例中提供了一种非易失性内存检查点生成方法、装置和电子设备,用于解决目前的检查点-恢复机制在检查点生成和运行时开销过大,造成带宽浪费的问题。
根据本申请实施例的第一个方面,提供了一种非易失性内存检查点生成方法,所述方法包括:
在应用程序编译过程中,通过编译器插桩插件在所述应用程序中插入桩例程调用指令,并生成可执行应用程序;
在所述可执行应用程序的运行过程中,根据所述桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块;
在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点。
根据本申请实施例的第二个方面,提供了一种非易失性内存检查点生成装置,所述装置包括:
插入桩例程模块,用于在应用程序编译过程中,通过编译器插桩插件在所述应用程序中插入桩例程调用指令,并生成可执行应用程序;
脏内存块获取模块,用于在所述可执行应用程序的运行过程中,根据所述桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块;
检查点生成模块,用于在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点。
根据本申请实施例的第三个方面,提供了一种电子设备,其特征在于,包括:处理器、存储器和总线,所述存储器存储有所述处理器可执行的机器可读指令,当所述电子设备运行时,所述处理器与所述存储器之间通过所述总线通信,所述机器可读指令被所述处理器执行时执行第一方面提供的非易失性内存检查点生成方法。
根据本申请实施例的第四个方面,提供了一种存储介质,所述存储介质上存储有计算机程序,所述计算机程序被处理器运行时执行第一方面提供的非易失性内存检查点生成方法。
本申请实施例提供了一种非易失性内存检查点生成方法、装置和电子设备,所述方法包括:在应用程序编译过程中,通过编译器插桩插件在应用程序中插入桩例程调用指令,并生成可执行应用程序;在可执行应用程序的运行过程中,根据桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块;在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在非易失性内存中生成检查点。本申请通过插入桩例程的机制能够对页面中被修改的内存区域进行定位,获得脏内存块,并将脏内存块写入到非易失性内存中,而不是将整个页面写入非易失性内存中,减少了写入非易失性内存的检查点的数据量,降低了检查点生成和运行时的开销,同时也能缩短检查点的生成时间。
附图说明
此处所说明的附图用来提供对本申请的进一步理解,构成本申请的一部分,本申请的示意性实施例及其说明用于解释本申请,并不构成对本申请的不当限定。在附图中:
图1为本申请实施例提供的非易失性内存检查点生成方法的流程图;
图2为本申请实施例提供的步骤S11的子步骤流程图;
图3为本申请实施例提供的自动优化的示例图;
图4为本申请实施例提供的生成二进制可执行文件的过程示意图;
图5为本申请实施例提供的运行时库的内存布局结构示意图;
图6为本申请实施例提供的应用程序的部分代码片段;
图7为问题规模为903时各版本除计算外产生的额外开销对比图;
图8为本申请实施例提供的非易失性内存检查点生成装置的功能模块图;
图9为本申请实施例提供的电子设备的示意图。
具体实施方式
在实现本申请的过程中,发明人发现,长期以来,绝大多数的计算机应用程序都是通过内存进行高效处理,使用磁盘进行数据存储。随着计算机系统的不断发展,传统的动态随机访问存储器(Dynamic RandomAccess Memory,DRAM)由于刷新功耗、工艺尺寸等限制,已经无法满足现在系统对于内存的需求。新型的非易失性内存(Non-Volatile Memory,NVM),例如相变存储器(Phase ChangeMemory,PCM)、自旋转移矩随机存储器(SpinTransfer Torque Random Access Memory,STT-RAM)、阻变式存储器(Resistive RandomAccess Memory,RRAM)等,由于其低功耗、非易失、可字节寻址等特性,而被视为DRAM的替代品之一。非易失性内存的出现改变了固有的存储体系结构,越来越多的应用程序开始使用非易失性内存进行处理及数据存储。但是构建可恢复应用程序需要开发者合理使用缓存刷新指令(如CLWB)和内存栅栏指令(如SFENCE),正确实现故障一致性(Crash-consistency)机制,以保证非易失性内存中的数据始终处于一致状态,既费力又容易出错。
因此,目前大部分应用程序都是通过检查点-恢复(Checkpoint-Recovery,CR)技术来实现应用程序的故障恢复,周期性地将计算得到的中间状态写入检查点(Checkpoint),并将检查点保存在非易失性内存中,在应用程序发生故障后,以非易失性内存中保存的最近的检查点为起点继续计算,从而实现应用程序的故障恢复。同时,应用程序可借助检查点-恢复机制保证应用程序数据的完整性和一致性。相比于事务等机制,检查点-恢复机制对应用程序的修改更少,且允许在容忍少量操作随故障而丢失的前提下,取得高可靠性和低性能开销之间的平衡。
但是,在目前的检查点-恢复机制中,通常都是借助处理器提供的内存保护(Memory Protection)机制实现检查点的增量生成,以减少检查点的大小。例如,在上一个检查点结束之后,持久化堆所处的地址空间经由mprotect()系统调用设置为只读,当应用程序访问某个页面时,处理器发出异常,由专门的信号处理函数将页面标记为脏(Dirty)并将该页面设置为可写状态,但在这种增量检查点生成方法中,增量快照的粒度是固定的(4KB或2MB),这个粒度远大于非易失内存所支持的读写粒度。也就是说,即使只有页面的一部分被修改,整体页面仍然会全部被写入非易失内存,导致检查点在生成和运行时开销过大,造成带宽浪费的现象。
为了通过非易失性内存实现检查点-恢复机制,还有一些方法试图在非易失性内存上保留足够的数据并提供故障后继续计算的能力。这种方法需要将部分应用程序数据存放于非易失性内存上,且要求程序员手动插入缓存刷新指令和内存栅栏指令,以确保应用程序数据的完整性。由于非易失性内存的带宽和读延迟与DRAM相比具有一定的差距,故应用程序的执行时间会被拉长。同时,手工插入缓存刷新指令繁琐、容易出错,程序员需要相当熟悉程序执行流程,因而该方法不适用于复杂的程序。
因此,如何在非易失性内存上生成增量检查点,且降低检查点生成和运行过程中的开销是目前需要解决的问题。
针对上述问题,本申请实施例中提供了一种非易失性内存检查点生成方法、装置和电子设备,所述方法包括:在应用程序编译过程中,通过编译器插桩插件在应用程序中插入桩例程调用指令,并生成可执行应用程序;在可执行应用程序的运行过程中,根据桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块;在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在非易失性内存中生成检查点。本申请能够在应用程序中插入桩例程调用指令,通过插入桩例程的机制能够对页面中被修改的内存区域进行定位,获得脏内存块,并将脏内存块写入到非易失性内存中,而不是直接写入整个页面,减少了写入非易失性内存的检查点的数据量,降低了检查点生成和运行时的开销,同时也能缩短检查点的生成时间。
为了使本申请实施例中的技术方案及优点更加清楚明白,以下结合附图对本申请的示例性实施例进行进一步详细的说明,显然,所描述的实施例仅是本申请的一部分实施例,而不是所有实施例的穷举。需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。
首先,先对编译过程进行一个简单的说明。在编译过程中,首先需要通过编译器将C/C++源文件分别转换成对象文件(Object File),然后通过链接器将一组对象文件组合成一个可执行文件(或链接库)。对于LLVM(Low Level Virtual Machine,底层虚拟机)等优化编译器来说,将C/C++源文件转换成对象文件的步骤又可以细分为三个阶段,第一个阶段是将C/C++源文件转换成中间代码表示(Intermediate Representation),中间代码可以理解为一种平台无关的伪代码,第二个阶段是通过对中间代码的分析和转换实现各种优化和功能扩展,第三个阶段是将中间代码转换为对象文件。
中间代码表示的最高层次是模块(Module),之后依次是函数(Function)、基本块(Basic Block)、指令(Instruction)等。控制流图则用于描述上述层次的包含(或被包含)以及先后关系,模块内还包括全局变量等。因此,每个中间文件有且只有一个模块,默认情况下分别对应一个C/C++源文件。中间文件可以合并,合并后的中间文件也只有一个模块,包含了原有的中间文件的所有函数、基本块、指令和全局变量。
下面结合附图对本申请实施例进行说明。
请参照图1,图1为本申请实施例提供的非易失性内存检查点生成方法的流程图。在本实施例中,所述方法包括:
步骤S11,在应用程序编译过程中,通过编译器插桩插件在应用程序中插入桩例程调用指令,并生成可执行应用程序。
步骤S12,在可执行应用程序的运行过程中,根据桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块。
步骤S13,在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在非易失性内存中生成检查点。
在上述步骤中,检查点函数用于生成检查点,在调用检查点函数时,将脏内存块写入非易失性内存中,即可视为已经在非易失性内存中生成了一个检查点。本实施例通过插入桩例程的机制能够对页面中被修改的内存区域进行定位,获得脏内存块,并将脏内存块写入到非易失性内存中,而不是将整个页面写入非易失性内存中,减少了写入非易失性内存的检查点的数据量,降低了检查点生成和运行时的开销,同时也能缩短检查点的生成时间。
另外,本实施例还能够根据纪元的序号将脏内存块写入非易失性内存的不同区域中,即使在生成检查点期间发生了电源中断或系统崩溃,这种双区域内存布局方式也能保证检查点的完整性。
可选地,在应用程序的编译阶段,编译器的插桩插件用于对中间代码进行静态分析,通过静态分析找到所有可能对非易失内存产生修改的操作,并修改中间代码,确保在执行这些操作时对应的内存块(默认为256字节)已被设置为“脏”,这是生成增量检查点的前提。
另外,若实际执行的桩例程调用指令过多,会对应用程序的性能产生影响。因此,需要通过静态分析技术判断无效或冗余的桩例程调用指令,并进行删除(即优化),从而可以在不影响检查点-恢复机制正确性的前提下保证了应用程序的高效率执行。
具体地,请参照图2,图2为本申请实施例提供的步骤S11的子步骤流程图。在本实施例中,步骤S11包括:
步骤S111,通过编译器将应用程序的每一个待编译的源文件转换为中间代码表示文件。
步骤S112,根据中间代码表示文件建立应用程序的控制流图。
步骤S113,通过编译器插桩插件根据控制流图查找需要插桩的目标指令。
步骤S114,针对每一个目标指令,根据目标指令生成对应的桩例程调用指令。
步骤S115,对桩例程调用指令进行优化,并将优化后的桩例程调用指令插入对应的目标指令之前。
在本实施例中,在应用程序的编译阶段,针对每一个编译模块(例如,源文件),编译器的插桩插件根据中间代码建立应用程序的模块级的控制流图(Control-Flow Graph,CFG)。在函数内部,控制流图能够反映基本块(Basic block)的执行顺序,据基本块的执行顺序可以找出分支、循环体和循环变量等参数,同时,控制流图还能够反映模块内所有函数调用关系。通过控制流图还可以查找到应用程序中所有调用了检查点函数的指令以及用于优化桩例程调用指令的优化标注,以便后续对桩例程调用指令进行优化。
随后,可以基于控制流图找到应用程序中所有的可能对非易失性内存产生修改的操作,即需要插入桩例程的目标指令,包括但不限于Store指令、Compare-and-swap(CAS)指令、Read-modify-write(RMW)指令;memset()、memcpy()和memmove()等标准库函数;read()等系统调用等。默认情况下,需要在这些目标指令之前插入一条桩例程调用指令,简写为call hook_routine(ptr,length)。桩例程调用指令的基本功能是维护当前纪元下持久化堆的写内存地址集合。
可选地,不同的目标指令对应的桩例程调用指令不同,因此,需要根据不同的目标指令生成与之对应的桩例程调用指令。具体地,在本实施例中,针对每一个目标指令,根据所述目标指令生成对应的桩例程调用指令,包括:
根据所述目标指令获取桩例程调用指令的指针和长度;根据所述指针和所述长度生成与所述目标指令对应的桩例程调用指令。
在上述步骤中,桩例程调用指令包括两个参数,分别是指针和长度,桩例程调用指令的指针和长度能够从目标指令中获得,因此,可以基于不同的目标指令生成对应的桩例程调用指令。
在生成桩例程调用指令后,还需要对桩例程调用指令分别进行分析优化。例如,当指针所处的内存块位于DRAM或已被设置为脏时,这部分桩例程调用指令可以被删除;另外,针对循环结构,在一定条件下还可将桩例程调用指令移出循环体。
可选地,在本实施例中,对所述桩例程调用指令进行优化,包括:
对所述桩例程调用指令进行自动优化,和/或根据优化标注对所述桩例程调用指令进行优化。
在上述步骤中,桩例程调用指令的优化可以根据是否需要人工干预分为自动优化和人工辅助优化两大类。
在自动优化中,请参照图3,图3为本申请实施例提供的自动优化的示例图。自动优化包括提升(Hoisting)、冗余写合并(Redundant Store Combination)、易失指针消除(Transient Pointer Elimination)、结构体合并(Struct Combination)及循环体聚合(Loop Aggregation)。
提升操作是指对于某个写入目标指令,该写入目标指令对应的桩例程调用指令可以往前移动,可以前移至计算获得的指针之后。另外,位于循环体内的桩例程调用指令可以被提升到循环体外部,从而避免重复执行桩例程调用指令。
冗余写合并操作是指对于某个桩例程调用指令I1,若存在桩例程调用指令I2使得:I1和I2作用于同一个变量、在CFG(控制流图)上,函数入口点到I1之间的所有路径均经过I2(记作I2dom I1)或不存在检查点函数调用发生在I2后且在I1前被执行,则可以将桩例程调用指令I1删除。
易失指针消除操作是指若通过控制流图分析发现某指针来自栈或者从DRAM处分配的堆,则删除该指针的桩例程调用指令。若指针来自函数参数(或函数返回值),只有该函数仅本模块可见,且所有实际参数(或实际返回值)都是常量或易失指针,才可以消去。
结构体合并操作是指若在同一函数中发现同一结构体具有多于一个元素指针的桩例程调用指令,可将其合并为该结构体整体的桩例程调用指令,并将该桩例程调用指令置于确定结构体指针之后。该操作要求在确定结构体指针之后,最后一个元素指针的桩例程调用指令之前,所有可能执行的指令都不是检查点函数调用指令。
循环体聚合操作是指若某个桩例程调用指令所处理的指针为数组形式,其基地址定义在循环体外部,下标等于循环体的归纳变量,则需要将其移出并改写为对整体数组的桩例程调用指令形式。该操作要求循环体内的所有可能执行的指令都不是检查点函数调用指令。
除了自动优化之外,用户还可以对代码段关键部位进行标注,通过优化标注对桩例程调用指令进行优化,进一步提高插入桩例程调用指令后应用程序的执行效率。
例如,若对结构体中不需持久化的成员标注“crpm2_discard”,则该模块中所有对此指针的桩例程调用指令都将被删除;若对不需持久化的函数标注“crpm2_discard”,则该函数的所有桩例程调用指令将被删除。
若用户在某函数中调用crpm2_annotate()接口(记其为I1),则对于该函数的桩例程调用指令I2,若I1dom I2(即函数入口点到I2之间的所有路径均经过I1)、二者的指针地址重叠或不存在检查点函数调用在I1后且在I2前被执行,则I2会被自动删除。
在本实施例中,桩例程调用指令的优化操作会被重复执行,直到无法继续优化后视为优化结束,在优化结束后,可以经优化后获得的桩例程调用指令插入至对应的目标指令之前,以生成二进制的可执行应用程序。
可选地,在本实施例中,在插入将优化后获得的桩例程调用指令之后,需要进行后续的编译和链接生成二进制文件,随后通过运行时库将经过编译器插桩插件处理后获得的二进制文件组成二进制可执行程序。具体地,请参照4,图4为本申请实施例提供的生成二进制可执行文件的过程示意图。在本实施例中,将源文件转换为二进制可执行程序需要通过编译器插桩插件和运行时库(即图4中的libcrpm.a)实现。
可选地,请参照图5,图5为本申请实施例提供的运行时库的内存布局结构示意图。在本实施例中,一个持久化堆至少具有主(main)区域和副(back)区域两个部分。逻辑上主区域和副区域的大小应当相等,实际中为了节省非易失性内存的空间,副区域部分的内存地址空间复用主区域。通过back_to_main数组维护主-副区域的对应关系。例如,在图5中,由于数组下标为1对应的条目是“3”,因此副区域内存段B1对应的主区域内存段为M3,×表示该副区域内存段没有对应的主区域内存段。
在应用程序运行期间,主区域和副区域的对应关系可能发生变化,但不影响系统的可恢复性。副区域实际大小应不小于工作集大小(即两次检查点之间内存修改的大小)。为了提供更高的带宽,持久化堆还占用了一部分动态随机存取存储器(Dynamic RandomAccess Memory,DRAM)的地址空间作为工作区域,应用程序在正确插入桩例程调用指令的前提下能够自由读写DRAM。内存在这些区域均被划分为若干2MB内存段(Segment),进一步细分为256B内存块(Block)。
持久化堆还保留了一定空间用于存储元数据。由于副区域内存段少于主区域,因此元数据包含一个数组,用于描述每个副区域内存段关联的主区域内存段。例如,图5中主区域的M3号内存段与副区域的B1号内存段相对应。元数据还包括一个映射表,描述组成最近检查点的内存段集合。具体地,它为每一个内存段保留了2Bit空间,分别有三个状态:(T1)Initial:该内存段从未被使用;(T2)Main:最近有效检查点位于主区域;(T3)Back:最近有效检查点位于副区域。为了便于原子化更新映射表,实际上元数据中包含两个映射表,使用映射表索引维护有效映射表。
在本实施例中,在形成二进制可执行程序之后,需要运行该二进制应用程序,定时调用检查点函数,以在非易失性内存中生成检查点。
在运行二进制可执行程序时,在执行到桩例程调用指令时,能够调用对应的桩例程,以修改当前纪元所属的脏页位图,从而将对应内存块标注为脏。
因此,可以通过插入的桩例程调用指令快速且准确地追踪到在一段时间内被修改的内存块,以将该内存块写入到非易失性内存中,无需将整个页面写入非易失性内存,避免出现带宽浪费的现象。
在对内存块进行标注之后,即可调用检查点函数。请参照图6,图6为本申请实施例提供的应用程序的部分代码片段。该代码片段能够通过应用程序编程接口(API)为LULESH(Livermore非结构化拉格朗日显式冲击流体力学)程序增加检查点。在应用程序执行过程中,需要通过crpm2_open()或crpm2_mpi_open()函数打开检查点文件(如图6中的第6-12行),并通过crpm2_get_root()函数从根指针数组检索持久化对象(如图6中的第13行)。当持久化对象不可用时,应用程序调用crpm2_malloc()函数取代默认的malloc()函数为持久化对象分配内存空间(如图6中的第15行),并使用crpm2_set_root()函数设置根指针数组(如图6中的第16行)。主循环(如图6中的第20-26行)定期调用crpm2_checkpoint()或crpm2_mpi_checkpoint()函数(即检查点函数)来创建检查点(如图6中的第24行)。
在调用检查点函数生成检查点时,所有写线程都会暂停工作并合力完成检查点更新。具体地,在本实施例中,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点,包括:
判断当前纪元的序号是否为奇数;若当前纪元的序号为奇数,则将上一个纪元和当前纪元产生的脏内存块从所述DRAM复制到非易失性内存的副区域中;若当前纪元的序号不为奇数,则将上一个纪元和当前纪元产生的脏内存块从所述DRAM复制到非易失性内存的主区域中。
例如,在图5的示例中,当前纪元的序号为2,因此,需要先将上一个纪元产生并写入到副区域的脏内存块(属于B0、B1和B3号内存段)从DRAM(或NVM上的副区域,二者内容相同)复制到非易失性内存的主区域上,并将当前纪元产生的脏内存块(如M1、M2、M4和M5号内存段)从DRAM复制到非易失性内存的主区域上。
根据当前纪元的序号的奇偶性即可将脏内存块交替写入非易失性内存的主区域或副区域中,保证在任何情况下,均有一个最近的一致(Consistent)检查点被保留下来。
值得说明的是,本实施例不是简单地将完整内存段作为一个整体进行传输,而是只写入脏内存块。因此,若某个内存段内只有少量的内存块被修改(即被标记为脏)时,生成检查点期间的数据传输量则仅为这些内存块大小的总和。脏内存块的大小可小于页面大小,这是非插桩方式无法达到的。此外,为了提高脏内存块的查找效率,在脏内存块位图之外还引入了脏内存块数组。当上次检查点至今产生的脏内存块数量小于一个阈值时,无需扫描整个脏内存块位图,而是从脏内存块数组直接获得脏内存块集合。
可选地,在本实施例中,位于DRAM的工作区域和位于非易失性内存的主区域、副区域都按照段粒度(例如2MB)进行了切分。副区域部分内存地址空间复用主区域,数组back_to_main[x]==y表示副区域内存段Bx对应的主区域内存段为My。映射表(如图5中的seg_state[2])用于描述检查点的组成,共有2份。
back_to_main数组和映射表均存储在非易失性内存上的保留空间,也就是都会被持久化。元数据中包含了已提交的检查点所属的纪元(epoch)的序号(如图5中的committed_epoch)。若为奇数(即epoch=1),则使用映射表1完成恢复过程,否则使用映射表0。初始化两个映射表的所有元素的值都为SS_Initial。任何时刻只有一个映射表是有效的;只要修改committed_epoch,就能更换有效的映射表。
在根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点之后,所述方法还包括:
根据生成的检查点对映射表及纪元的序号进行更新。
具体地,在上述步骤中,在将脏内存块复制到非易失性内存的主区域或者副区域之后,按照新检查点的布局向非活动映射表中填写新状态:若当前纪元(epoch)的序号(检查点尚未提交时)为奇数,则修改映射表0;否则为映射表1。对于上一个纪元和当前纪元产生的脏内存块所属的内存段,修改映射表中对应项的值为SS_Main(epoch编号为奇数)或SS_Back(epoch编号为偶数)。最后,通过修改committed_epoch,就能切换活动映射表,同时将当前纪元(epoch)的序号自增1。
为了验证本申请实施例提出的非易失性内存检查点生成方法的实际使用效果,在英特尔傲腾内存、两处理器累计96核心(超线程开启)的实验环境下,对检查点生成的原始版本(即非快照版本)、经本实施例处理的版本、基于Dirty-bit实现内存访问追踪的版本(产生检查点时采用重做日志Redo-logging替换原有检查点)和基于FTI(基于磁盘的MPI容错库,多级检查点被关闭)的版本进行了对比实验。
请参照表1,表1展示了本实施例与其他版本在运行LULESH程序时的总用时与求解问题规模的关系。
表1
结果显示,本申请实施例在多种数据规模下具有比FTI更优的性能,程序总执行时间较FTI减少最高达到8.40%。这是因为该工作避免了write()系统调用带来的开销,以及全量检查点导致的写带宽浪费。相对于基于Dirty-bit实现内存访问追踪的版本,本实施例生成检查点的时间仅为其一半左右。
请参照图7,图7为问题规模为903时各版本除计算外产生的额外开销对比图。结果显示,FTI检查点生成所需时间分别为本实施例和Dirty-bit方法的1.93和6.05倍,这是因为在每次生成检查点时,即使只有很小一部分被修改,FTI也必须将保护变量的值完整写入持久化设备。相对于Dirty-bit方法,在本方法中,检查点生成的开销降低了68%,这主要是因为在交替向主区域或副区域写入检查点数据时,无需按照重做日志的要求将一份数据写入两遍。另一方面由于采用了细粒度的增量复制技术,检查点生成过程中的带宽消耗也得以减少。本方法还避免了页表从内核态拷贝到用户态和扫描页表的开销,体现了借助插桩技术实现轻量内存追踪的优势。
请参照表2,表2示出了本申请实施例在编译时对桩例程调用指令优化后运行LULESH程序的总用时和插入桩例程调用指令的数量。
表2
结果显示,若不实施任何的桩例程调用指令优化,则总运行时间增加103.64%,通过自动优化和人工辅助的优化,插入桩例程调用指令时需要的开销被不断减少,最终优化了51%桩例程调用指令,同时总运行时间也只增加了5.16%。
综上所述,本申请实施例提供了一种非易失性内存检查点生成方法,所述方法包括:在应用程序编译过程中,通过编译器插桩插件在应用程序中插入桩例程调用指令,并生成可执行应用程序;在可执行应用程序的运行过程中,根据桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块;在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在非易失性内存中生成检查点。本申请能够在应用程序中插入桩例程调用指令,通过插入桩例程的机制能够对页面中被修改的内存区域进行定位,获得脏内存块,并将脏内存块写入到非易失性内存中,而不是将整个页面写入非易失性内存中,减少了写入非易失性内存的检查点的数据量,降低了检查点生成和运行时的开销,同时也能缩短检查点的生成时间。
另外,本申请实施例通过DRAM-NVM(Non-volatile Memory,非易失性内存)混合架构,避免了应用程序因直接访问NVM延长执行时间,通过共享部分地址空间的双区域内存布局,保证了检查点的完整性,同时也减少了NVM存储空间占用;支持多线程和多进程应用程序正确生成检查点;相对现有的增量检查点生成方法,本申请实施例不会为每个增量检查点生成独立的快照文件,且增量检查点的恢复效率与全量检查点相当。
本申请实施例还提供了一种非易失性内存检查点生成装置,如图8所示,图8为本申请实施例提供的非易失性内存检查点生成装置110的功能模块图。在本实施例中,所述装置包括:
插入桩例程模块1101,用于在应用程序编译过程中,通过编译器插桩插件在所述应用程序中插入桩例程调用指令,并生成可执行应用程序;
脏内存块获取模块1102,用于在所述可执行应用程序的运行过程中,根据所述桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块;
检查点生成模块1103,用于在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点。
本申请实施例还提供了一种电子设备,请参照图9,图9为本申请实施例提供的电子设备10的示意图。在本实施例中,电子设备10包括:处理器11、存储器12和总线13,存储器12存储有处理器11可执行的机器可读指令,当电子设备10运行时,11处理器与存储器12之间通过总线13通信,机器可读指令被处理器11执行时执行本申请实施例提供的非易失性内存检查点生成方法。
本申请实施例还提供了一种存储介质,所述存储介质上存储有计算机程序,所述计算机程序被处理器运行时执行上述实施例提供的非易失性内存检查点生成方法。
本领域内的技术人员应明白,本申请的实施例可提供为方法、系统、或计算机程序产品。因此,本申请可采用完全硬件实施例、完全软件实施例、或结合软件和硬件方面的实施例的形式。而且,本申请可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
本申请是参照根据本申请实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的装置。
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令装置的制造品,该指令装置实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
尽管已描述了本申请的优选实施例,但本领域内的技术人员一旦得知了基本创造性概念,则可对这些实施例作出另外的变更和修改。所以,所附权利要求意欲解释为包括优选实施例以及落入本申请范围的所有变更和修改。
显然,本领域的技术人员可以对本申请进行各种改动和变型而不脱离本申请的精神和范围。这样,倘若本申请的这些修改和变型属于本申请权利要求及其等同技术的范围之内,则本申请也意图包含这些改动和变型在内。
Claims (9)
1.一种非易失性内存检查点生成方法,其特征在于,所述方法包括:
在应用程序编译过程中,通过编译器插桩插件在所述应用程序中插入桩例程调用指令,并生成可执行应用程序;
在所述可执行应用程序的运行过程中,根据所述桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块;
在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点;
其中,在应用程序编译过程中,通过编译器插桩插件在所述应用程序中插入桩例程调用指令,包括:
通过编译器将所述应用程序的每一个待编译的源文件转换为中间代码表示文件;
根据所述中间代码表示文件建立所述应用程序的控制流图;
通过所述编译器插桩插件根据所述控制流图查找需要插桩的目标指令;
针对每一个目标指令,根据所述目标指令生成对应的桩例程调用指令;
对所述桩例程调用指令进行优化,并将优化后的桩例程调用指令插入对应的目标指令之前。
2.根据权利要求1所述的方法,其特征在于,针对每一个目标指令,根据所述目标指令生成对应的桩例程调用指令,包括:
根据所述目标指令获取桩例程调用指令的指针和长度;
根据所述指针和所述长度生成与所述目标指令对应的桩例程调用指令。
3.根据权利要求1所述的方法,其特征在于,对所述桩例程调用指令进行优化,包括:
对所述桩例程调用指令进行自动优化,和/或;
根据优化标注对所述桩例程调用指令进行优化。
4.根据权利要求1所述的方法,其特征在于,根据所述桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块,包括:
在调用所述桩例程时,对位于动态随机存取存储器DRAM上的当前纪元的脏页位图进行修改,以将当前纪元的内存块标注为脏内存块。
5.根据权利要求4所述的方法,其特征在于,在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点,包括:
判断当前纪元的序号是否为奇数;
若当前纪元的序号为奇数,则将上一个纪元和当前纪元产生的脏内存块从所述DRAM复制到非易失性内存的副区域中;
若当前纪元的序号不为奇数,则将上一个纪元和当前纪元产生的脏内存块从所述DRAM复制到非易失性内存的主区域中。
6.根据权利要求1所述的方法,其特征在于,在根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点之后,所述方法还包括:
根据生成的检查点对映射表及纪元的序号进行更新。
7.一种非易失性内存检查点生成装置,其特征在于,所述装置包括:
插入桩例程模块,用于在应用程序编译过程中,通过编译器插桩插件在所述应用程序中插入桩例程调用指令,并生成可执行应用程序;
脏内存块获取模块,用于在所述可执行应用程序的运行过程中,根据所述桩例程调用指令调用桩例程,并根据调用的桩例程获取当前纪元产生的脏内存块;
检查点生成模块,用于在调用检查点函数生成检查点时,根据当前纪元的序号,将上一个纪元及当前纪元产生的脏内存块写入非易失性内存的主区域或者副区域中,以在所述非易失性内存中生成检查点;
其中,插入桩例程模块具体用于:通过编译器将所述应用程序的每一个待编译的源文件转换为中间代码表示文件;根据所述中间代码表示文件建立所述应用程序的控制流图;通过所述编译器插桩插件根据所述控制流图查找需要插桩的目标指令;针对每一个目标指令,根据所述目标指令生成对应的桩例程调用指令;对所述桩例程调用指令进行优化,并将优化后的桩例程调用指令插入对应的目标指令之前。
8.一种电子设备,其特征在于,包括:处理器、存储器和总线,所述存储器存储有所述处理器可执行的机器可读指令,当所述电子设备运行时,所述处理器与所述存储器之间通过所述总线通信,所述机器可读指令被所述处理器执行时执行如权利要求1-6任一项所述的方法。
9.一种存储介质,其特征在于,所述存储介质上存储有计算机程序,所述计算机程序被处理器运行时执行如权利要求1-6任一项所述的方法。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202110712594.9A CN113515412B (zh) | 2021-06-25 | 2021-06-25 | 非易失性内存检查点生成方法、装置和电子设备 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN202110712594.9A CN113515412B (zh) | 2021-06-25 | 2021-06-25 | 非易失性内存检查点生成方法、装置和电子设备 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN113515412A CN113515412A (zh) | 2021-10-19 |
CN113515412B true CN113515412B (zh) | 2024-04-12 |
Family
ID=78066302
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN202110712594.9A Active CN113515412B (zh) | 2021-06-25 | 2021-06-25 | 非易失性内存检查点生成方法、装置和电子设备 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN113515412B (zh) |
Families Citing this family (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN115061858B (zh) * | 2022-08-19 | 2022-12-06 | 湖南视拓信息技术股份有限公司 | 数据持久化方法、装置、计算机设备及存储介质 |
CN116991428B (zh) * | 2023-09-28 | 2023-12-15 | 飞腾信息技术有限公司 | 一种编译方法、装置、编译器、计算设备及存储介质 |
Citations (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN105183642A (zh) * | 2015-08-18 | 2015-12-23 | 中国人民解放军信息工程大学 | 基于插桩的程序行为获取及结构分析方法 |
CN107704400A (zh) * | 2017-10-12 | 2018-02-16 | 郑州云海信息技术有限公司 | 一种面向非易失存储的页缓存方法 |
US10846222B1 (en) * | 2019-07-01 | 2020-11-24 | Vmware, Inc. | Dirty data tracking in persistent memory systems |
WO2020253112A1 (zh) * | 2019-06-19 | 2020-12-24 | 深圳壹账通智能科技有限公司 | 测试策略的获取方法、装置、终端及可读存储介质 |
CN112631893A (zh) * | 2019-09-24 | 2021-04-09 | 无锡江南计算技术研究所 | 面向异构平台的多层次存储结构内存检测方法 |
Family Cites Families (1)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US10949326B2 (en) * | 2016-10-05 | 2021-03-16 | B.G. Negev Technologies And Applications Ltd. | Method and system for testing and checking the correctness of a computer program during runtime |
-
2021
- 2021-06-25 CN CN202110712594.9A patent/CN113515412B/zh active Active
Patent Citations (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN105183642A (zh) * | 2015-08-18 | 2015-12-23 | 中国人民解放军信息工程大学 | 基于插桩的程序行为获取及结构分析方法 |
CN107704400A (zh) * | 2017-10-12 | 2018-02-16 | 郑州云海信息技术有限公司 | 一种面向非易失存储的页缓存方法 |
WO2020253112A1 (zh) * | 2019-06-19 | 2020-12-24 | 深圳壹账通智能科技有限公司 | 测试策略的获取方法、装置、终端及可读存储介质 |
US10846222B1 (en) * | 2019-07-01 | 2020-11-24 | Vmware, Inc. | Dirty data tracking in persistent memory systems |
CN112631893A (zh) * | 2019-09-24 | 2021-04-09 | 无锡江南计算技术研究所 | 面向异构平台的多层次存储结构内存检测方法 |
Also Published As
Publication number | Publication date |
---|---|
CN113515412A (zh) | 2021-10-19 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
Scargall | Programming persistent memory: A comprehensive guide for developers | |
Hsu et al. | NVthreads: Practical persistence for multi-threaded applications | |
Haria et al. | MOD: Minimally ordered durable datastructures for persistent memory | |
US10691559B2 (en) | Persistent memory transactions with undo logging | |
Shull et al. | AutoPersist: An easy-to-use Java NVM framework based on reachability | |
US9940229B2 (en) | Technologies for persistent memory programming | |
Bruening et al. | Practical memory checking with Dr. Memory | |
US7542977B2 (en) | Transactional memory with automatic object versioning | |
Bond et al. | Tolerating memory leaks | |
US20100223429A1 (en) | Hybrid Caching Techniques and Garbage Collection Using Hybrid Caching Techniques | |
CN113515412B (zh) | 非易失性内存检查点生成方法、装置和电子设备 | |
US20150261463A1 (en) | Asynchronous consistent snapshots in persistent memory stores | |
Cohen et al. | Object-oriented recovery for non-volatile memory | |
Blelloch et al. | The parallel persistent memory model | |
Denny et al. | NVL-C: Static analysis techniques for efficient, correct programming of non-volatile main memory systems | |
US10019331B2 (en) | Memory allocation and recovery strategies for byte-addressable non-volatile RAM (NVRAM) | |
US9195593B1 (en) | Hardware assisted object memory migration | |
Cho et al. | Revamping hardware persistency models: view-based and axiomatic persistency models for Intel-x86 and Armv8 | |
Memaripour et al. | Breeze: User-level access to non-volatile main memories for legacy software | |
CN112131032B (zh) | 一种基于混合内存系统的故障快速恢复方法 | |
Lefort et al. | J-NVM: off-heap persistent objects in java | |
Shull et al. | QuickCheck: Using speculation to reduce the overhead of checks in nvm frameworks | |
Li et al. | UniHeap: Managing persistent objects across managed runtimes for non-volatile memory | |
Krauter et al. | Persistent software transactional memory in Haskell | |
Grossman et al. | Efficient checkpointing of multi-threaded applications as a tool for debugging, performance tuning, and resiliency |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |