提出的问题: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. [置顶] 遇到难题(bug)的解决方法心得

    今天早上花了2个小时解决一个问题...界面抖动.. 最近把淄博项目的界面用BT改了,后来发现4个界面之间切换会抖动.. 就是整个界面会左右抖动... 文章出处: PHP攻城师 www.phpgcs.c ...

  2. ubuntu 安装maven提示出错 The program &#39;mvn&#39; can be found in the following packages

    问题: I am trying to install apache maven 3 in Ubuntu 12.04 lts. What I did was open the terminal then ...

  3. Object-c @property的用法

    property是一种代码生成机制,可以生成不同类型的getter/setter函数,特别是假设你想要用点(.)操作符号来存取变量的话,你就能必须使用property. 怎样使用? 使用方法如:@pr ...

  4. 自拉ADSL网线搭建站点server,解决动态IP、无公网IP、80port被封、HTTP被屏蔽的方法

    自己的server搭建站点应用,提供站点服务,能够不用备案,但可能会面对网络限制问题,如动态公网IP.无公网IP.80port被封.HTTP被屏蔽,这些复杂网络情况. 依据本地网络环境,能够针对不同的 ...

  5. MySqlClient访问tinyint字段返回布尔值

    原文 MySqlClient访问tinyint字段返回布尔值 症状: 使用MySqlClient访问tinyint       unsign 字段返回布尔值 true 和        false,但 ...

  6. Linux教程:如何在Linux下进行C++开发?

    Linux是一类Unix计算机操作系统的统称,Linux操作系统的内核的名字也是“Linux”, 在Linux下进行C++开发,需要注意许多问题,比如:减少不必要的编辑动作,减少编辑的时间. Wind ...

  7. Codeforces 396B On Sum of Fractions 数论

    题目链接:Codeforces 396B On Sum of Fractions 题解来自:http://blog.csdn.net/keshuai19940722/article/details/2 ...

  8. jsp获得本地及serverIP的方法

    InetAddress addr = InetAddress.getLocalHost(); String ip = addr.getHostAddress().toString();//获得本机IP ...

  9. SAP屏幕框架的创建

    1.创建包括文本的基本框架 REPORT ztest_sum. TABLES:mara,syst. WITH FRAME TITLE mytitle. "mytitle是框架上的文本 ) A ...

  10. 与众不同 windows phone (4) - Launcher(启动器)

    原文:与众不同 windows phone (4) - Launcher(启动器) [索引页][源码下载] 与众不同 windows phone (4) - Launcher(启动器) 作者:weba ...