<< Click to Display Table of Contents >> 内存管理 |
❖DataGrid 生命周期管理
产品中定义了 DataGrid 接口用来表达运算结果,一般来说 DataGrid 对象被认为是产品中大量存在,而且占用内存空间较大的一类对象。因此,DataGrid 对象的生命周期直接关系到产品对内存的使用是否合理,影响计算效率。
因此在产品中对 DataGrid 对象的生命周期管理方式进行了优化,避免 DataGrid 对象被过早或者过晚回收,能够及时清除不被使用的 DataGrid 对象,减少内存的无端占用,有效控制 serial 目录的增长。
•相关属性配置:
以下属性配置中的值都是系统默认值,可根据使用情况来决定是否进行调整,一般使用默认值即可。
属性 |
说明 |
---|---|
sys.lifecycle.managed=true |
定义是否开启DataGrid对象的生命周期管理 |
sys.lifecycle.debug=false |
定义是否打开调试信息,使用时建议关闭 |
lifecycle.check.period=7200000 |
定义查看系统中存在的DataGrid信息的时间间隔 |
❖执行结果缓存设计
产品运行时会合理的将运算结果进行缓存,不但可以节省计算资源,还能够改善产品体验。目前,产品已经支持对运算结果的缓存。缓存以 Query 的基础运算结果为基本单元,一些在基础运算结果上的后处理则不进行缓存,基于同一 Query 的不同运算没有在缓存层面进行考虑。在 7.0 版本中,对上述缓存机制进行了提升,进一步提高缓存结果重用率,从而提高计算的效率。
是否缓存最终运算结果需要满足如下规则:
•进行的运算是非详细查询的;
•查询对应的报表模式为非编辑状态;
•当最终运算结果和已经缓存的结果大小相同时(如无后续处理或仅包含表达式或者排序),不需要缓存;
•当已缓存的结果记录行数较少时 , 或后续处理执行时间较短时,不需要缓存。
对于集市数据运算结果的缓存,目前将结果保存在内存当中,默认的有效时间为15分钟,为增强数据查看的体验,达到秒级打开报表的效果,我们将报表执行的结果进行永久缓存,保存在磁盘上,第一时间将数据展现出来。
缓存的结果会被保存在与bihome文件夹同级的cache文件夹(Yonghong/cache)里面,缓存的结果有效期默认为一周,一周之后缓存的结果将会被从磁盘上删除。
对于将运算结果保存在磁盘上的功能,目前只支持缓存使用集市数据(同步查询数据,增量导入数据)的报表结果,可以通过参数来控制是个开启结果缓存的功能,默认是开启的。同时也可以通过参数来控制缓存的结果是否随着报表的更改而更新,为了减轻系统的负担,默认不打开自动更新的功能,按照具体的需求可以通过参数来更改。
当报表结果被缓存到磁盘后,报表中配置的参数_REFRESH_将不再生效,每次查看报表时都会直接读取缓存到内存或者磁盘上的结果,并不会重新进行集市运算。如果想每次都重新进行集市计算的话,需要通过配置参数result.serial=false来关闭这个缓存的功能。
属性 |
说明 |
---|---|
result.serial=false |
默认关闭缓存到磁盘的功能 |
result.serial.auto.refresh=false |
是否自动更新已缓存到磁盘的文件,默认不缓存 |
result.serial.auto.refresh.interval=1800000 |
自动更新已缓存到磁盘的文件的时间间隔 |
result.serial.max.length=20 |
单个缓存到磁盘文件大小的限制,默认为20M |
result.serial.max.size=1000 |
限制可以缓存到磁盘的文件个数,默认为1000个,可以理解为一个element对应一个缓存文件 |
result.serial.timeout=604800000 |
缓存到磁盘的文件的过期时间,默认为一周没有被使用就会过期 |
❖线程执行的内存调度
系统对线程执行的内存调度进行了优化,当通过多线程同时执行多个运算时,系统会根据系统负载情况来对内存进行控制,合理的分配系统资源,防止运算受限或者内存溢出,以提高 cpu 和内存的使用效率,从而提高运算速度。
在产品使用过程中,系统会监控计算内存(可通过参数 mem.calc.mem 配置)的使用,估算每个计算线程的内存占用,采用内存申请的机制来为每个线程分配合适的内存。
首先线程执行的时候该线程会向系统申请一个单位内存(可通过参数 calc.mem.units 配置), 系统会设置一个检查点,当线程执行一段时间到达检查点后会估算线程总占用的内存大小,此时:
•如果申请到的内存比预估的总占用内存大,则可以不申请内存,直至任务运行结束;
•如果占用的内存比申请到的内存大,或快用完,则继续申请内存,如果申请不到,则该 Runnable 会暂停执行;
•如果此时已无空闲内存,而所有线程都处于申请内存状态,则此时应该给予额外的内存,让其中的某个线程优先执行完,并释放出空闲内存,其中优先级高的线程可以更优先获得空闲内存。
•相关属性配置:
以下属性配置中的值都是系统默认值,可根据使用情况来决定是否进行调整,一般使用默认值即可。
属性 |
说明 |
---|---|
mem.apply.timeout=3600000 |
定义每个线程申请内存的超时时间 |
calc.mem.managed=true |
定义是否使用计算内存机制 |
calc.mem.debug=false |
定义是否打开计算内存的调试信息,使用时建议关闭 |
calc.mem.units=10 |
定义为每个线程分配的初始内存值,默认为10M |
mem.calc.mem= |
定义计算内存的大小,默认为最大JVM的3/10 |
❖计算过程中内存对象管理
针对不同类型的对象,建立合适的管理方案,通过管理计算全过程中可能使用大内存的对象,来增强系统的内存透明性和稳定性。
❖分组聚合计算的内存控制优化
对分组聚合计算的内存控制进行优化。计算分组过程中,当内存占用与分组数量同时超过阈值时,超出阈值的分组采用新的数据结构进行存储。避免分组数量过多导致的内存占用较高问题。
•相关属性配置:
以下属性配置中的值都是系统默认值,可根据使用情况来决定是否进行调整,一般使用默认值即可。
属性 |
说明 |
---|---|
dc.aggr.key.serial=true |
默认开启分组聚合计算内存控制功能 |
dc.aggregation.memory.ratio=0.8 |
定义内存占用阈值,默认值为80% |
aggr.groups.keys.limit=50000 |
定义分组数量阈值,默认值为5万 |