gen_server2 与gen_server的对比
在erlang杀手级应用rabbitmq中,不难发现,有一个gen_server2.erl模块。而在rabbitmq中,gen_server2.erl是对gen_server.erl模块的重写。
RabbitMQ重新实现了gen_server -> gen_server2。 很多Module都是用了这个behavior。
我们首先来看下OTP里gen_server 的实现:
gen_server的启动入口是gen_server:start_link,一个以gen_server为behavior的Module,例如frontend call gen_server:start_link( node_manager)来启动node_manager这个gen_server.
gen_server:start_link启动一个进程,执行gen_server:init_it。
gen_server:init_it做了三件事:
1. 调用node_manager:init
2. send ack to frontend
3. start loop
loop
先比较gen_server和gen_server2的loop
gen_server loop是receive一个message,处理这个message,再去receive下一个message,没有message时就block在那里。
message一般是三种来源:
1. frontend 的gen_server:call 由 node_manager: handle_call来处理, 会有reply send to frontend
2. frontend 的gen_server:cast 有 node_manager : handle_cast来处理
3. 其他由 node_manager : handle_info来处理
而gen_server2的loop与其不同:
1. receive所有message, 加到Queue里。
2. 如果Queue不空,从Queue里取出一个处理,再step1
3. 如果Queue为空:
3.1 如果没有hibernate, 直接去receive,然后加到Queue。如果timeout, 就由handle_info来处理
3.2 如果有hibernate,没有backoff, 将timeout设成 infinity, 在那一直去receive(边睡边等)
3.3 如果有hibernate,也有backoff, 直接去receive,然后加到Queue,如果timeout,去call pre_hibernate, hibernate,wake 以后重新调整timeout。
gen_server的message box可能非常大,而gen_server2使用了一个额外的Queue来解决这个问题,注释显示这样避免了selective receives in callbacks 去scan一个巨大的MessageBox, selective receives in callbacks例如multi_call,mcall
hibernate
node_manager的init和所有callback function 都可以返回一个hibernate,使loop进入休眠,直到有下个message进来。进入休眠会比较省cpu资源,一般对于下一个message需要很久后才come in的scenario
gen_server2提供了两个新的callback function: pre_hibernate and post_hibernate。
这里看下gen_server和gen_server2的 hibernate实现:
gen_server的每轮loop一旦收到一个hibernate, 就立刻调用proc_lib:hibernate, 当醒来时直接receive,然后处理message。
gen_server2的每轮loop一旦收到一个hibernate,先调用pre_hibernate ,再调用proc_lib:hibernate,醒来时receive所有message, 加到Queue里,再调用post_hibernate,然后处理Queue里的message
timeout
gen_server和gen_server2里的timeout不太一样
gen_server里,timeout是针对一个request处理,node_manager的init, handle_call, handle_cast, handle_info都可以返回一个timeout, 这样当下一次 receive timeout了以后,由handle_info(timeout)来处理。如果不设timeout, 默认是infinity,就是receive会block在那里。gen_server的timeout和hibernate没有什么关系,当有hibernate时就没有timeout,因为直到有request来才会wake, 这样就直接receive即可。
gen_server2里,timeout是在Queue空的时候使用,Queue空的时候需要receive messages,此时有三种情况:
1. 没有hibernate,就和gen_server一样,如果timeout由handle_info处理
2. 有hibernate没有backoff, timeout就没用了,跟gen_server一样,直接进入hibernate。
3. 当有hibernate又有backoff时,receive会等待timeout的时间再进入hibernate,而timeout时间是不断调整的。
backoff
gen_server2 的backoff 有这个几个参数:InitialTimeout, MinimumTimeout, DesiredHibernatePeriod。当一次hibernate的时间很长,超过DesiredHibernatePeriod,就会将下次timeout设置的时间短一点,这样可以尽快hibernate;如果当一次hibernate的时间很短,就会将下次timeout设置的时间长一点,这样在request来的很频繁的时候避免去hibernate。
mcall
gen_server2 增加了一个mcall接口,可以一次并行call gen_server2
gen_server2 与gen_server的对比的更多相关文章
- gen_server port 调用receive_match 问题
问题由来 前些天对系统做了一个优化,将原来从queue 轮询刷出数据后每条消息一个 spawn 进程单独处理,修改为批量刷出.一条一条刷轮询刷 queue 存在问题:刷queue 进程太多时,占用CP ...
- Erlang generic standard behaviours -- gen_server hibernate
hibernate 主要用于在内存空闲时,通过整理进程的stack,回收进程的heap 来达到回收内存节省资源的效果. hibernate 可用于OTP 进程以及普通进程, hibernate 的官方 ...
- Ignite性能测试以及对redis的对比
测试方法 为了对Ignite做一个基本了解,做了一个性能测试,测试方法也比较简单主要是针对client模式,因为这种方法和使用redis的方式特别像.测试方法很简单主要是下面几点: 不作参数优化,默认 ...
- IIC驱动移植在linux3.14.78上的实现和在linux2.6.29上实现对比(deep dive)
首先说明下为什么写这篇文章,网上有许多博客也是介绍I2C驱动在linux上移植的实现,但是笔者认为他们相当一部分没有分清所写的驱动时的驱动模型,是基于device tree, 还是基于传统的Platf ...
- [原] KVM 环境下MySQL性能对比
KVM 环境下MySQL性能对比 标签(空格分隔): Cloud2.0 [TOC] 测试目的 对比MySQL在物理机和KVM环境下性能情况 压测标准 压测遵循单一变量原则,所有的对比都是只改变一个变量 ...
- arcgis api for js入门开发系列六地图分屏对比(含源代码)
上一篇实现了demo的地图标绘模块,本篇新增地图地图分屏对比模块,截图如下(源代码见文章底部): 对效果图的简单介绍一下,在demo只采用了两分屏对比,感兴趣的话,可以在两分屏的基础上拓展,修改css ...
- 嵌入式&iOS:回调函数(C)与block(OC)回调对比
学了OC的block,再写C的回调函数有点别扭,对比下区别,回忆记录下. C的回调函数: callBack.h 1).定义一个回调函数的参数数量.类型. typedef void (*CallBack ...
- C#跨平台手机应用开发工具Xamarin尝试 与Eclipse简单对比
Xamarin 支持使用C#开发基于Android.IOS.WindowsPhone应用开发,最大特点C#+跨平台,详细说明问度娘. 安装 研究 想体验研究的点击查看页面 Xamarin For Vi ...
- 几款主流 NoSql 数据库的对比
最近小组准备启动一个 node 开源项目,从前端亲和力.大数据下的IO性能.可扩展性几点入手挑选了 NoSql 数据库,但具体使用哪一款产品还需要做一次选型. 我们最终把选项范围缩窄在 HBase.R ...
随机推荐
- mysql增加和删除字段
时间字段: `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `last_update_time` t ...
- 八. 输入输出(IO)操作6.文件与目录管理
目录是管理文件的特殊机制,同类文件保存在同一个目录下不仅可以简化文件管理,而且还可以提高工作效率.Java 语言在 java.io 包中定义了一个 File 类专门用来管理磁盘文件和目录. 每个 Fi ...
- 代理模式(Proxy)--动态代理(CGLIB)
上一篇:代理模式(Proxy)--动态代理(jdk) (1)CGLIB技术是第三方代理技术,可以对任何类生成代理,代理的原则是对目标对象进行继承代理 (2)如果目标对象被final修饰,则无法被CGL ...
- 每天一个linux命令8之grep高级篇
1语法 grep -[acinv] '搜索内容串' filename -a 以文本文件方式搜索-c 计算找到的符合行的次数-i 忽略大小写-n 顺便输出行号-v 反向选择,即找 没有搜索字 ...
- js常用函数和常用技巧
学习和工作的过程中总结的干货,包括常用函数.常用js技巧.常用正则表达式.git笔记等.为刚接触前端的童鞋们提供一个简单的查询的途径,也以此来缅怀我的前端学习之路. PS:此文档,我会持续更新. Aj ...
- 【IntellJ IDEA】idea的Terminal窗口中文乱码 解决方法
在操作git命令在windows上的idea中的terminal窗口时,总是出现中文乱码的问题 本开始以为是git乱码的问题,如果是GIt中文乱码,解决方案:https://www.cnblogs.c ...
- C# this.Invoke()的作用与用法
Invoke()的作用是:在应用程序的主线程上执行指定的委托.一般应用:在辅助线程中修改UI线程( 主线程 )中对象的属性时,调用this.Invoke(); 在多线程编程中,我们经常要在工作线程 ...
- Mac安装pstree
brew install pstree pstree(选项) -a:显示每个程序的完整指令,包含路径,参数或是常驻服务的标示: -c:不使用精简标示法: -G:使用VT100终端机的列绘图字符: -h ...
- 解决no declaration can be found for element 'context:component-scan'
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- NetBean 远程开发的好文1 --> NetBeans的远程Linux C开发实践
from: http://blog.csdn.net/jacktan/article/details/9268535 一直以来总觉得NetBeans生活在Eclipse的阴影下,同样做为一款不错的基 ...