Solution to high memory usage of Erlang Server

Source: Internet
Author: User

Solution to high memory usage of Erlang Server

Question: The Erlang server has 1 million online users, and 16 GB of memory is quickly swallowed up. The memory occupied by player processes is high.

Solution:

Step 1:
Erlang: system_info (process_count). Check whether the number of processes is normal and whether it exceeds the maximum number of processes on the erlang virtual machine.
Step 2:
View the memory bottleneck of a node
> Erlang: memory ().
[{Total, 2099813400 },
{Processes, 1985444264 },
{Processes_used, 1985276128 },
{System, 114369136 },
{Atom, 4479545 },
{Atom_used, 4477777 },
{Binary, 22756952 },
{Code, 10486554 },
{Ets, 47948808}]
It is shown that most of the memory is consumed by the process, which determines that the process occupies a large amount of memory.

Step 3:
View processes with the highest memory usage

> Spawn (fun ()-> etop: start ([{output, text}, {interval, 1}, {lines, 20}, {sort, memory}]) end ).
(Start etop in output text mode. The interval is 1 second, and the number of output rows is 20 rows, sorted by memory. here, spawn is a new process to output etop data without affecting the erlang shell input .)

Step 4: view the process status with the highest memory usage
> Erlang: process_info (pid (, 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 },
{Functions, 3795950 },
{Garbage_collection, [{min_bin_vheap_size, 46368 },
{Min_heap_size, 233 },
{Fullsweep_after, 65535 },
{Minor_gcs, 0}]},
{Suspending, []}]

"{Total_heap_size, 12538050}," indicates that the occupied memory is 12358050 words (the 32-bit system word size is 4, and the 64-bit system word size is 8. You can use erlang: system_info (wordsize) view). The 64-bit system has nearly 100 MB, which is too exaggerated!

Step 5:
Manual gc collection, hope the problem can be solved
> Erlang: garbage_collect (pid (, 0 )).
True
Check the process memory again and find that there is no change! Gc has not recycled any resources, so the consumed memory is still playing a role, not recycled!

Step 6:
Do not doubt the system. First, doubt your code.
Observe the code carefully. Its structure is as follows:
Send_msg (Socket, Pid)->
Try
Receive
{Send, Bin}->
...
{Inet_reply, _ Sock, Result}->
...
Catch
_: _->
Send_msg (Sock, Pid)
End.
The purpose is to wait for the data cyclically and then send the data. It uses try... catch to catch exceptions.
This code is not tail recursion! Try... catch stores the corresponding information in the stack. Exception capture must be placed inside the function. Therefore, send_msg finally calls try... catch, not itself, so it is not tail recursion!
The code can be used for verification:
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 (1, 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.

Version 1: erlctest. erl & erl-eval "test: t1 ()"
Version 2: erlctest. erl & erl-eval "test: t2 ()"
You will see that the call stack of version 1 code is growing, the memory is also growing, and the call address of version 2 function remains unchanged, and the memory has not changed!

Summary:
1. In Server programming, the loop must be tail recursion;
2. Try to use OTP. If you use gen_server to replace the handwritten loop, this problem will be avoided.

Compile and install Erlang R15B on CentOS

Build an Erlang environment in Ubuntu 11.10

Install Erlang through YUM on CentOS 5.7

Erlang --- start parameter learning/Research

Source code compilation and installation of Erlang in CentOS 5.5

Install Erlang 5.8.3 in the source code of Ubuntu 10.10

Install Erlang on CentOS 6.4

Install Erlang R16B in Ubuntu

Erlang details: click here
Erlang: click here

This article permanently updates the link address:

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.