Fix High CPU Usage & Performance Tuning

Identify and resolve Asterisk performance bottlenecks: transcoding, dialplan loops, connection limits, and monitoring

Why Asterisk Uses High CPU

Asterisk is inherently CPU-intensive because it processes real-time audio streams. Unlike a web server that handles bursty traffic, Asterisk must process audio packets every 20ms per call without interruption. The main CPU consumers are:

CPU ConsumerImpactTypical Load Per Call
Codec TranscodingVery High~20-30% of a single core per G.729 transcode
Recording (MixMonitor)MediumAdditional file I/O and mixing per recorded call
Conference BridgesHighScales with number of participants (mixing audio)
Dialplan ProcessingLow-MediumDepends on complexity; loops can spike CPU
AMI/ARI EventsLow-HighCan flood CPU if many subscribers or debug events
TLS/SRTP EncryptionLow-MediumInitial handshake is CPU-intensive; ongoing is minimal

#1 Problem: Codec Transcoding

Transcoding occurs when two endpoints use different codecs, forcing Asterisk to convert audio between formats in real-time. For example, if one side uses G.729 and the other uses G.711 (ulaw), Asterisk must decode G.729 and re-encode to G.711 for every single audio packet (50 packets/second per call).

Detect Transcoding:

# Show active channels with codec info
asterisk -rx "core show channels verbose"

# Look for lines like:
# SIP/100-00000001  (ulaw)    SIP/trunk-00000002  (g729)
#                    ^^^^                           ^^^^
# Different codecs = TRANSCODING happening!

# Check codec translation paths
asterisk -rx "core show translation"

# This shows a matrix of codec-to-codec conversion costs
# Lower numbers = less CPU; "n/a" = not possible

Fix: Match Codecs Everywhere

; In sip.conf - set the SAME codecs for all peers and trunks:
[general]
disallow=all
allow=alaw
allow=ulaw
; Only add g729 if ALL endpoints support it
; Avoid mixing g729 with ulaw/alaw

; For PJSIP endpoints:
[my-endpoint]
type=endpoint
disallow=all
allow=ulaw
allow=alaw
; Use the same codec list for ALL endpoints to avoid transcoding
Best Practice: Use ulaw (G.711u) or alaw (G.711a) for internal calls — they use zero CPU for transcoding and have excellent quality. Only use compressed codecs (G.729, Opus) for WAN trunks where bandwidth matters.

Hardware Codec Boards:

For deployments that must transcode (e.g., G.729 trunks to G.711 phones), consider hardware transcoding cards from Sangoma/Digium (TC400B) that offload codec conversion from the CPU. These can handle hundreds of simultaneous transcoding sessions.

#2 Problem: Dialplan Inefficiency

Complex or poorly written dialplans can cause excessive CPU usage, especially with loops, heavy database lookups, or AGI scripts that run on every call.

Common Dialplan Problems:

  • Infinite loops: GoTo/GotoIf that loops back without a proper exit condition
  • Excessive AGI calls: Spawning a new process for every call (use FastAGI instead)
  • Heavy ODBC/database lookups: Querying a slow database on every dialplan step
  • Regex pattern matching: Overly complex patterns like _X.! that match everything
  • Unnecessary logging: Verbose() and NoOp() with high verbosity in production

Optimize Dialplan:

; BAD: AGI script for every call (spawns new process each time)
exten => _X.,1,AGI(my-script.php)

; GOOD: Use FastAGI (persistent connection, no process spawn)
exten => _X.,1,AGI(agi://127.0.0.1:4573/my-script)

; BAD: Catch-all pattern with heavy processing
exten => _X.!,1,Set(RESULT=${ODBC_LOOKUP(${EXTEN})})

; GOOD: Specific patterns, cache results
exten => _1NXXNXXXXXX,1,Set(RESULT=${ODBC_LOOKUP(${EXTEN})})
exten => _NXXNXXXXXX,1,Goto(${CONTEXT},1${EXTEN},1)

; BAD: Verbose logging in production
exten => _X.,n,Verbose(5,Processing call to ${EXTEN} from ${CALLERID(all)})

; GOOD: Remove or reduce verbose level in production
; exten => _X.,n,NoOp()  ; Comment out in production

Monitoring & Diagnostics

# Current system overview
asterisk -rx "core show sysinfo"
asterisk -rx "core show uptime"

# Active calls and channels
asterisk -rx "core show calls"
asterisk -rx "core show channels count"
asterisk -rx "core show channels verbose"

# Check which codecs are in use (detect transcoding)
asterisk -rx "core show channels verbose" | grep -i "transcode"

# Check translation costs
asterisk -rx "core show translation recalc 10"

# Monitor from Linux side
top -p $(pidof asterisk)
htop -p $(pidof asterisk)

# Profile Asterisk CPU usage
asterisk -rx "core show profile"

# Check thread count (high thread count = potential issue)
ps -eLf | grep asterisk | wc -l

# Memory usage
asterisk -rx "core show sysinfo" | grep -i mem

# Check for process limits
cat /proc/$(pidof asterisk)/limits
ulimit -a

Performance Tuning Settings

asterisk.conf Optimizations:

[options]
; Increase max calls (default 0 = unlimited, but set a sane limit)
maxcalls=500

; Increase max file descriptors
maxfiles=16384

; Reduce debug/verbose in production
verbose=0
debug=0

; Enable core dumps for crash analysis
dumpcore=yes

; Set process priority (higher = more CPU time, range -20 to 19)
; highpriority=yes  ; Runs with nice -10

Linux System Tuning:

# Increase file descriptor limits for Asterisk
echo "asterisk soft nofile 65536" >> /etc/security/limits.conf
echo "asterisk hard nofile 65536" >> /etc/security/limits.conf

# Increase UDP buffer sizes for RTP
echo "net.core.rmem_max=16777216" >> /etc/sysctl.conf
echo "net.core.wmem_max=16777216" >> /etc/sysctl.conf
echo "net.core.rmem_default=1048576" >> /etc/sysctl.conf
sysctl -p

# Set Asterisk process to real-time priority
chrt -f 1 $(pidof asterisk)

# Pin Asterisk to specific CPU cores (NUMA aware)
taskset -cp 0-3 $(pidof asterisk)

Reduce AMI/ARI Event Flooding:

; In manager.conf - limit event types per AMI user:
[my-ami-user]
secret=mypassword
read=system,call
write=system,call
; Do NOT use: read=all,write=all (generates massive event traffic)
; Specifically exclude: cdr,dialplan,dtmf,reporting if not needed

; Limit AMI connections
[general]
; Only allow connections from specific IPs
bindaddr=127.0.0.1
; Or use ACLs:
; permit=127.0.0.1/255.255.255.255
; deny=0.0.0.0/0.0.0.0

Capacity Planning Guide

ScenarioCPU CoresRAMConcurrent Calls
Small office (no transcoding)1 core512 MB~50 calls
Medium business (no transcoding)2 cores2 GB~200 calls
Medium with G.729 transcoding4 cores4 GB~50-100 calls
Large (no transcoding, recording)4 cores8 GB~500 calls
Large conference bridge8 cores8 GB~100 conf participants
Carrier grade (no transcoding)8+ cores16 GB~2000+ calls
Key Takeaway: Eliminating transcoding is the single biggest performance improvement you can make. A single CPU core can handle ~50 transcoded calls but ~500+ non-transcoded calls.
← Back to All Asterisk Solutions|Asterisk Complete Guide →