提出的问题:server100万人在线,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,server编程中,循环一定确保为尾递归

2,尽量使用OTP,假设使用gen_server更换手写loop,将避免这个问题

版权声明:本文博客原创文章,博客,未经同意,不得转载。

Erlangserver紧内存优化解决方案的更多相关文章

  1. Android性能优化:手把手带你全面了解 内存泄露 & 解决方案

    . 简介 即 ML (Memory Leak)指 程序在申请内存后,当该内存不需再使用 但 却无法被释放 & 归还给 程序的现象2. 对应用程序的影响 容易使得应用程序发生内存溢出,即 OOM ...

  2. Android性能优化:手把手带你全面实现内存优化

      前言 在 Android开发中,性能优化策略十分重要 本文主要讲解性能优化中的内存优化,希望你们会喜欢 目录   1. 定义 优化处理 应用程序的内存使用.空间占用 2. 作用 避免因不正确使用内 ...

  3. [转]探索 Android 内存优化方法

    前言 这篇文章的内容是我回顾和再学习 Android 内存优化的过程中整理出来的,整理的目的是让我自己对 Android 内存优化相关知识的认识更全面一些,分享的目的是希望大家也能从这些知识中得到一些 ...

  4. JavaScript内存优化

    JavaScript内存优化 相对C/C++ 而言,我们所用的JavaScript 在内存这一方面的处理已经让我们在开发中更注重业务逻辑的编写.但是随着业务的不断复杂化,单页面应用.移动HTML5 应 ...

  5. Unity3D 游戏开发之内存优化

    项目的性能优化主要围绕CPU.GPU和内存三大方面进行. 无论是游戏还是VR应用,内存管理都是其研发阶段的重中之重. 然而,在我们测评过的大量项目中,90%以上的项目都存在不同程度的内存使用问题.就目 ...

  6. SQLServer2014内存优化表评测

    SQLServer2014内存优化表评测 分类: SQL内存表2014-06-20 11:49 1619人阅读 评论(11) 收藏 举报 目录(?)[-] SQLServer2014的使用基本要求 内 ...

  7. 【MDCC技术大咖秀】Android内存优化之OOM

    大神分析的很全面,所以就转过来保存一份,转自:http://www.csdn.net/article/2015-09-18/2825737/1 以下为正文: Android的内存优化是性能优化中很重要 ...

  8. Android内存优化之OOM

    内容大多都是和OOM有关的实践总结概要.理解错误或是偏差的地方,还请多包涵指正,谢谢!本人Q:1524447071 (一)Android的内存管理机制 Google在Android的官网上有这样一篇文 ...

  9. 【腾讯Bugly干货分享】Android内存优化总结&实践

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/2MsEAR9pQfMr1Sfs7cPdWQ 导语 智 ...

随机推荐

  1. HDU3572_Task Schedule(网络流最大流)

    解题报告 题意: 工厂有m台机器,须要做n个任务.对于一个任务i.你须要花费一个机器Pi天,并且,開始做这个任务的时间要>=Si,完毕这个任务的时间<=Ei. 对于一个任务,仅仅能由一个机 ...

  2. ASC(22)H(大数+推公式)

    High Speed Trains Time Limit: 4000/2000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) Su ...

  3. QT在构造函数中退出程序

    原地址:http://www.tuicool.com/articles/RZnYze 在QT的界面类的构造过程中,如果想退出整个程序,暴力的做法是调用exit(-1)进行,另外一种不是那么暴力的方式如 ...

  4. tmux centos 6.3

    tmux-1.6-1.el6.rf.i686.rpm CentOS 6 / RHEL 6 Download #21 tmux-1.6-1.el6.rf.i686.rpm

  5. 动静结合学内核:linux idle进程和init进程浅析

    刘柳 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 + titer1@qq.com 退休的贵族进程 ...

  6. Decoding BASE64 in ABAP

    Code Gallery Decoding BASE64 in ABAP Skip to end of metadata Created by Frank Klausner, last modifie ...

  7. CWnd中PreCreateWindow、PreSubclassWindow、SubclassWindow的区别

    http://blog.csdn.net/swimmer2000/archive/2007/10/30/1856213.aspx MFC(VC6.0)的CWnd及其子类中,有如下三个函数:     / ...

  8. delphi实现穿XP防火墙

    procedure TForm1.Button1Click(Sender: TObject);var   FwMgr,Profile,FwApp: variant;begin   FwMgr := C ...

  9. innerXml,outerXml,innerText的不同

    原文:innerXml,outerXml,innerText的不同 昨天看到咱们园子里有一个仁兄写的关于xml的有关操作,在读的过程中,由于是初学者有不明白的地方就查资料,发现自己多innerXml, ...

  10. C#中Base64之编码,解码方法

    原文:C#中Base64之编码,解码方法 1.base64  to  string string strPath =  "aHR0cDovLzIwMy44MS4yOS40Njo1NTU3L1 ...