Erlang服务器内存吃紧的优化解决方法
问题提出:服务器100万人在线,16G内存快被吃光。玩家进程占用内存偏高
解决方法:
第一步:
erlang:system_info(process_count). 查看进程数目是否正常,是否超过了erlang虚拟机的最大进程数。
第二步:
查看节点的内存瓶颈所在地方
> erlang:memory().
[{total,2099813400},
{processes,1985444264},
{processes_used,1985276128},
{system,114369136},
{atom,4479545},
{atom_used,4477777},
{binary,22756952},
{code,10486554},
{ets,47948808}]
显示内存大部分消耗在进程上,由此确定是进程占用了大量内存
第三步:
查看占用内存最高的进程
>spawn(fun()-> etop:start([{output, text}, {interval, 1}, {lines, 20}, {sort, memory}]) end).
(以输出text方式启动etop,其间隔为1秒,输出行数为20行,按照内存排序. 这里spawn一个新进程,目的是输出etop数据时不影响erlang shell 输入.)
第四步:查看占用内存最高的进程状态
>erlang:process_info(pid(0,12571,0)).
[{current_function,{mod_player,send_msg,2}},
{initial_call,{erlang,apply,2}},
{status,waiting},
{message_queue_len,0},
{messages,[]},
{links,[<0.12570.0>]},
{dictionary,[]},
{trap_exit,false},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.46.0>},
{total_heap_size,12538050},
{heap_size,12538050},
{stack_size,10122096},
{reductions,3795950},
{garbage_collection,[{min_bin_vheap_size,46368},
{min_heap_size,233},
{fullsweep_after,65535},
{minor_gcs,0}]},
{suspending,[]}]
其中” {total_heap_size,12538050},”表示占用内存为 12358050 words(32位系统word size为4,64位系统word size为8, 可以通过erlang:system_info(wordsize) 查看),在64位系统下将近100M, 太夸张了!
第五步:
手动gc回收,希望问题可以解决
> erlang:garbage_collect(pid(0,12571,0)).
true
再次查看进程内存,发现没有任何变化!gc没有回收到任何资源,因此消耗的内存还在发挥作用,没有回收!
第六步:
不要怀疑系统,首先要怀疑自己的代码
认真观察代码,其大致结构如下:
send_msg(Socket, Pid) ->
try
receive
{send, Bin} ->
...
{inet_reply, _Sock, Result} ->
...
catch
_:_->
send_msg(Sock,Pid)
end.
其目的是循环等待数据,然后进行发送,其使用了try...catch捕获异常.
这段代码不是尾递归! try...catch会在stack中保存相应的信息,异常捕获需要放置在函数内部,所以send_msg最后调用的是try...catch,而不是自身,所以不是尾递归!
可以通过代码得到验证:
cat test.erl
-module(test).
-compile([export_all]).
t1() ->
Pid = spawn(fun()-> do_t1() end),
send_msg(Pid, 100000).
t2() ->
Pid = spawn(fun()-> do_t2() end),
send_msg(Pid, 100000).
send_msg(_Pid, 0) ->
ok;
send_msg(Pid, N) ->
Pid !<<2:(N)>>,
timer:sleep(200),
send_msg(Pid, N-1).
do_t1() ->
erlang:garbage_collect(self()),
Result =erlang:process_info(self(), [memory, garbage_collection]),
io:format("~w~n", [Result]),
io:format("backtrace:~w~n~n",[erlang:process_display(self(), backtrace)]),
try
receive
_->
do_t1()
end
catch
_:_ ->
do_t1()
end.
do_t2() ->
erlang:garbage_collect(self()),
Result =erlang:process_info(self(), [memory, garbage_collection]),
io:format("~w~n", [Result]),
io:format("backtrace:~w~n~n",[erlang:process_display(self(), backtrace)]),
receive
_ ->
do_t2()
end.
版本1:erlctest.erl && erl -eval "test:t1()"
版本2:erlctest.erl && erl -eval "test:t2()"
你会看到版本1代码的调用堆栈在不断增长,内存也在增长, 而版本2函数调用地址保持不变,内存也没有发生变化!
总结:
1,服务器编程中,循环一定确保为尾递归;
2,尽量使用OTP,如果使用gen_server替换手写loop,就会避免出现该问题。
转自:http://www.2cto.com/os/201405/299927.html
Erlang服务器内存吃紧的优化解决方法的更多相关文章
- Linux系统内存占用90%以上——解决方法
Linux系统内存占用90%以上--解决方法 首先要明确一个问题:Linux系统内存占用90%以上,是否属于正常范围?网上有详细的解释,这属于正常现象~~~ www.2cto.com L ...
- JCIFS读取远程服务器文件过慢的解决方法
JCIFS读取远程服务器文件过慢的解决方法 发表于3年前(2013-07-12 11:23) 阅读(1174) | 评论(0) // 我要收藏"; var favor_del = &qu ...
- IIS6.0服务器搭建网站无法访问解决方法
IIS6.0服务器搭建网站无法访问解决方法 IIS6.0服务器搭建网站无法访问解决方法很多朋友在用IIS6架网站的时候遇到不少问题,而这些问题有些在过去的IIS5里面就遇到过,有些是新出来的, ...
- Java虚拟机系列(三)---内存溢出情况及解决方法
因为Java虚拟机内存有堆内存.方法区.虚拟机栈.本地方法栈和程序计数器五部分组成,其中程序计数器是唯一一块不会发生内存溢出异常的内存区,所以只有四类内存区可能发生内存溢出异常,其中虚拟机栈和本地方法 ...
- Block产生的内存泄露,以及解决方法
前言: 在ARC(自动引用技术)前,Objective-c都是手动来分配释放 释放 计数内存,其过程非常复杂. ARC技术推出后,貌似世界和平了很多,但是其实ARC并不等同于Java或者C#中的垃圾回 ...
- Tomcat常见的内存溢出,以及解决方法
一.常见的三种内存溢出错误: 1.java.lang.OutOfMemoryError:java heap space ====JVM Heap(堆)溢出 JVM再启动的时候回自动设置JVM H ...
- Unity3D占用内存太大的解决方法
原地址:http://www.cnblogs.com/88999660/archive/2013/03/15/2961663.html 最近网友通过网站搜索Unity3D在手机及其他平台下占用内存太大 ...
- 上Mysql com.mysql.jdbc.StatementImpl$CancelTask内存泄漏问题和解决方法
近来在负责公司短信网关的维护及建设,随着公司业务发展对短信依赖越来越严重了,短信每天发送量也比曾经每天40多w发送量暴增到每天达到200w发送量.由于是採用Java做发送底层,压力递增情况下不可避免的 ...
- Firefox内存占用过高解决方法
刚开始使用firefox火狐浏览器的时候,你会发现firefox占用内存大,CPU占用率高,打开网页停顿等问题,其实这些是因为firefox没有进行优化,默认设置是标准的设置的原因,解决方法如下: 一 ...
随机推荐
- js, lambada? 在chrome和node下可以使用
var a=function(a,c){if(a)c(a)} undefined a(true,(console.log)) VM177:2 Uncaught TypeError: Illegal i ...
- EOJ Monthly 2018.1 F 最小OR路径
题目链接 Description 给定一个有 \(n\) 个点和 \(m\) 条边的无向图,其中每一条边 \(e_i\) 都有一个权值记为 \(w_i\) . 对于给出的两个点 \(a\) 和 \(b ...
- Windows消息钩取
@author: dlive @date: 2016/12/19 0x01 SetWindowsHookEx() HHOOK SetWindowsHookEx( int idHook, //hook ...
- JQuery操作基本选择器
<body> <input type="button" id="btn1" value="选择为one的元素"/> ...
- hdu 5059(模拟)
Help him Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- 爬虫学习笔记(二)http请求详解
上篇博客里面写了,爬虫就是发http请求(浏览器里面打开发送的都是http请求),然后获取到response,咱们再从response里面找到想要的数据,存储到本地. 咱们本章就来说一下什么是http ...
- HDU 6225.Little Boxes-大数加法 (2017ACM/ICPC亚洲区沈阳站-重现赛(感谢东北大学))
整理代码... Little Boxes Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/O ...
- 一种极简的异步超时处理机制设计与实现(C#版)
1.引言 当执行某些动作之后,会期待反馈.最终要么是得到了结果,要么就是超时了.当超时发生时,可能是期望得到通知,或是希望能自动重试,等等.于是设计了一种通用的异步超时的处理机制,以期通过简洁易理解的 ...
- SQLite的Pragma语句
SQLite的Pragma语句 Pragma语句是SQLite提供的特有语句.该语句可以查询SQLite的非表数据,还可以修改SQLite的库.在iOS开发中,利用Pragma语句,可以实现很多非 ...
- centos7下使用wget命令安装mysql
1.首先安装wget命令: yum -y install wget 2.下载mysql wget http://repo.mysql.com/mysql-community-release-el7- ...