Unexpected memory growth in Asterisk

Hi!

I am experiencing an issue with Asterisk’s memory usage. Initially, Asterisk consumes around 35MB, but after making some calls using sipp, the memory usage increases and gets stuck at around 105MB, without decreasing over time.

Environment:
- A custom Docker image that compiles asterisk 22 directly from the repository, using Debian 12-slim as the base image.
- A sipp launching 2000 calls, 100 simultaneous anonimous call.

pjsip.conf:

	[transport-udp]
	type=transport
	protocol=udp
	bind=0.0.0.0:5060

	[anonymous]
	type=endpoint
	context=from-internal
	disallow=all
	allow=ulaw

extensions.conf:

	[default]
	include => from-internal

	[from-internal]
	exten => 123,1,Answer()
	same => n,Hangup

modules.conf:

	[modules]
	    autoload = no
	    load = app_system.so
	    load = res_sorcery_astdb.so
	    load = res_sorcery_config.so
	    load = res_sorcery_memory.so
	    load = res_sorcery_realtime.so
	    load = chan_pjsip.so
	    load = res_musiconhold.so
	    load = res_pjproject.so
	    load = res_pjsip_sdp_rtp.so
	    load = res_pjsip_pubsub.so
	    load = res_pjsip_session.so
	    load = res_pjsip.so
	    load = res_rtp_asterisk.so
	    load = res_pjsip_endpoint_identifier_anonymous.so
	    load = pbx_config.so

(Note: I’ve tried removing unnecessary modules in case one of them is causing the issue, leaving only this minimal set. The memory problem also occurs with the default modules configuration.)

It looks like there are no stuck calls in the system:

CLI> core show calls
0 active calls
2000 calls processed

Are there any known issues related to this topic?
Could using Asterisk inside a Docker container be causing this problem?

Thanks in advance!

There are caches and other aspects internally. If you truly want to know where all of the memory usage is going, then you’d have to investigate deeper yourself.

Hi, sorry for the late response.

I’ve been running some tests with Valgrind. I changed the environment to a Debian 12 VM to avoid issues.

Latest Valgrind results:

Without any calls:

==3090== LEAK SUMMARY:
==3090==    definitely lost: 120 bytes in 2 blocks
==3090==    indirectly lost: 0 bytes in 0 blocks
==3090==      possibly lost: 2,752,883 bytes in 14,989 blocks
==3090==    still reachable: 42,738,163 bytes in 148,930 blocks
==3090==         suppressed: 0 bytes in 0 blocks

With 200 simultaneous calls (total of 1000 calls):

==5827== LEAK SUMMARY:
==5827==    definitely lost: 216 bytes in 3 blocks
==5827==    indirectly lost: 0 bytes in 0 blocks
==5827==      possibly lost: 3,232,594 bytes in 18,406 blocks
==5827==    still reachable: 58,885,007 bytes in 153,811 blocks
==5827==         suppressed: 0 bytes in 0 blocks

Additional observations:

==5827== 8,228,000 bytes in 121 blocks are still reachable in loss record 8,093 of 8,094
==5827==    at 0x48407B4: malloc (vg_replace_malloc.c:381)
==5827==    by 0x49ACC55: default_block_alloc (pool_policy_malloc.c:45)
==5827==    by 0x49B4EC4: pj_pool_create_block (pool.c:61)
==5827==    by 0x49B4EC4: pj_pool_allocate_find (pool.c:152)
==5827==    by 0x490CDAD: pjsip_tx_data_encode (sip_transport.c:611)
==5827==    by 0x4904F25: endpt_on_tx_msg (sip_endpoint.c:1120)
==5827==    by 0x490DB22: pjsip_transport_send (sip_transport.c:961)
==5827==    by 0x4906C24: stateless_send_transport_cb (sip_util.c:1304)
==5827==    by 0xC3AF5B2: sip_resolve (pjsip_resolver.c:525)
==5827==    by 0x490930A: pjsip_endpt_send_request_stateless (sip_util.c:1508)
==5827==    by 0x49202E4: tsx_send_msg (sip_transaction.c:2518)
==5827==    by 0x4920625: tsx_on_state_null (sip_transaction.c:2788)
==5827==    by 0x4924436: pjsip_tsx_send_msg (sip_transaction.c:2020)

Question:
Is it normal for Asterisk’s memory usage to never be freed? In this simple scenario, it is not a major issue, but we have observed memory growing to over 1GB in more complex environments or with more simultaneous calls.
Would there be any way to free this memory without restarting Asterisk or its core?

If I could provide more info, please tell me.

There’s Asterisk memory usage which is generally freed, except glibc may keep on to it. There is PJSIP memory usage which operates based on memory pools and has caching built in, so it may or may not be freed depending on what exactly is being done and used.

The glibc aspect can be cleaned up using the “malloc trim” CLI command. The rest there are no commands to do so.