提出的问题: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. html,JavaScript调用winfrom方法

    ---恢复内容开始--- 目的: 在动画上面添加点击事件,通过JavaScript调用winfrom方法 1.创建一个页面 using System; using System.Collections ...

  2. 基于visual Studio2013解决C语言竞赛题之1084完全平方数

        题目 解决代码及点评 /************************************************************************/ /* ...

  3. [置顶] 提高生产力:Web开发基础平台WebCommon的设计和实现

    Web开发中,存在着各种各样的重复性的工作.为了提高开发效率,不在当码农,我在思考和实践如何搭建一个Web开发的基础平台. Web开发基础平台的目标和功能 1.提供一套基础的开发环境,整合了常用的框架 ...

  4. Android 带你从源码的角度解析Scroller的滚动实现原理

    转帖请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17483273),请尊重他人的辛勤劳动成果,谢谢! 今天给大 ...

  5. shell oracle

    #!/bin/sh traffic= rm -rf test.txt data=`sqlplus -S anoscfg/anoscfg <<EOF spool test.txt set f ...

  6. 阻塞队列BlockingQueue用法(转)

    多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享. 假设我们有若干生产者线程,另外又有若干个消费者线程.如果生产者线程需 ...

  7. cocos2d-x游戏开发系列教程-前言

    cocos2d-x游戏开发前景: 最近企业对于Cocos2D-X开发人才的用人需求很大,而且所提供的薪资相当可观. 为满足广大向往游戏开发行业同学的需求,特推出适合新手的Cocos2D-X手游开发教程 ...

  8. JavaScript快速入门(一)——JavaScript概览

    JavaScript是什么? JavaScript的诞生 在1995年前后,当时世界上的主流带宽为28.8Kbps,现在世界平均下载带宽为21.9Mbps(数据来源于http://www.netind ...

  9. jquery mobile 对手势触控提供了如下几个事件监听:

    jquery mobile 对手势触控提供了如下几个事件监听: 复制代码代码如下: tap  当用户点屏幕时触发taphold 当用户点屏幕且保持触摸超过1秒时触发swipe 当页面被垂直或者水平拖动 ...

  10. 静态书架和js模拟翻书效果

    书籍图片随便找了个,有点难看,须要的自己替换个好看点的png格式图片 源代码下载:http://download.csdn.net/detail/sweetsuzyhyf/7604091