设置是我在多个项目中通用的,不过根据应用场景的不同,还会有其它细调,就不在这一一说明了。 - Sunface
一、 erl启动时参数:
+K true
开启epoll调度,在linux中开启epoll,会大大增加调度的效率
+A 100
异步线程池,为某些port调用服务
+P 1024000
最大进程数
+Q 65535
最大port数
+sbt db
绑定调度器,绑定后调度器的任务队列不会在各个CPU线程之间跃迁,结合sub使用,可以让CPU负载均衡的同时也避免了大量的跃迁发生。
注意:一个linux系统中,最好只有一个evm开启此选项,若同时有多个erlang虚拟机在系统中运行,还是关闭为好
+sub true
开启CPU负载均衡,false的时候是采用的CPU密集调度策略,优先在某个CPU线程上运行任务,直到该CPU负载较高为止。
+swct eager 此选项设置为eager后,CPU将更频繁的被唤醒,可以增加CPU利用率 +spp true 开启并行port并行调度队列,当开启后会大大增加系统吞吐量,如果关闭,则会牺牲吞吐量换取更低的延迟。+zdbbl 65536
分布式erlang的端口buffer大小,当buffer满的时候,向分布式的远程端口发送消息会阻塞
二、erlang内部进程启动参数
示例:创建一个新进程并进行注册,该进程是全局唯一的自增ID生成进程,因此无法做多进程处理,这个时候单进程的性能就是至关重要的
首先,出于性能和功能考虑,这个进程不是gen_server;其次进行了部分参数调优能
register(num_generator, spawn_opt(?MODULE, init, [],[{priority,high},{scheduler,0},{min_heap_size, 65536 * 2},{min_bin_vheap_size,65536 * 2}])).
参数讲解:
1.priority
er lang是公平调度策略,因此默认情况下每个进程得到的运行时间片是相同的:2000reductions,但是对于我们的应用场景来说,这个进程应该是优先级较高的,需要得到更多的调度,因此设置为high,还可以设置为max,但是max是系统进程的预留优先级,用high即可
2. scheduler
将该进程绑定到指定的scheduler上,防止进程的任务被scheduler分配来分配去,可以减少CPU调用,注意这个和+sbt db是不同的,+sbt db是防治调度器的任务队列在CPU线程间跃迁,scheduler是为了防止进程在时间片切换过程中被分配给其它的调度器
3.min_heap_size
进程初始堆大小,用内存换CPU的典型做法,增大初始大小,可以显著降低GC次数和内存再分配次数
4.min_bin_vheap_size
进程初始二进制堆大小,当该进程对于binary数据的处理交换很多时,可以获得和增大min_heap_size一样的效果
三、port(socket)调优
示例:服务器监听端口,接受客户端请求。典型应用场景web服务器,需要实现高吞吐,低延迟的目标
Res = gen_tcp:listen(Port, [binary,
{reuseaddr, true},
{nodelay, true},
{delay_send,true},
{high_watermark,64 * 1024},
{send_timeout, 30000},
{send_timeout_close, true},
{keepalive, true}])
参数详解:
binary:
接收到客户端的消息后,作为binary来处理,binary在erlang中是很高效的数据结构,超过64字节,就是全局保存的,因此在很多操作下是不需要复制的,仅仅复制binary的指针即可,详细请搜索refc binary,注意:binary大量使用需要有丰富的经验,不然可能会内存泄漏
reuseaddr:
允许系统复用port,对于高吞吐的系统,这个参数很重要,请搜索:linux port 复用
nodelay:
开启linux中的TCP_NODELAY参数,请搜索:TCP_NODELAY 40毫秒延迟
delay_send:
默认的erlang port消息发送,是直接发送,若失败则排队处理,然后由调度器进行队列poll操作,如果设置为true,那么就不尝试直接发送,而且扔进队列,等待poll,开启选项会增加一点点消息延迟,换来吞吐量的大量提升
high_watermark:
port的发送缓存,缓存满了后,下次发送会直接阻塞,直到缓存低于某个阈值low_watermark。如果是密集网络IO系统,请增大该buffer,避免发送阻塞
send_timeout:
在high_watermark中提到了发送阻塞,如果阻塞超过这个时间,那么就会超时,发送直接返回,停止发送
send_timeout_close:
如果发生了send_timeout同时设置了send_timeout_close选项,那么超时后,会直接关闭socket.如果发送进程不是很重要,例如web用户进程,强烈建议开启这个选项,当发送30秒超时的时候,就说明该用户出现了很大的麻烦,断开连接是最理想的做法,否则可能出现很多奇怪的bug.
keepalive:
遵循HTTP/1.1协议的keepalive规定,这个根据业务需求选择是否开启,如果同一个客户端会连续发起http请求,那么建议设置为true,避免多次TCP握手
示例:服务器发起大量的http请求,在优化了参数后,同样的吞吐量所耗费的时间是未优化前的1/3 - 1/2(经过严苛的测试得出的数据)
inets:start(),
httpc:set_options([{max_keep_alive_length,500},{max_sessions,100},{nodelay,true},{reuseaddr,true}]),
参数详解:
max_keep_alive_length:
在同一条http连接上允许发送的最大包数,默认为5,超过5个包,就会重连
max_sessions:
跟目标服务器之间最大的并行http连接数目,大大的增加了数据上行吞吐量
nodelay_true:
见上文
reuseaddr:
见上文