Packages
Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.
Current section
Files
Jump to
Current section
Files
lib/raxol/memory/optimizer.ex
defmodule Raxol.Memory.Optimizer do
@moduledoc """
Memory optimization analysis and recommendations.
Analyzes configuration, processes, binaries, ETS tables, and GC
to produce actionable optimization suggestions.
"""
alias Raxol.Memory.Collector
@doc "Builds a full optimization analysis map."
def run_optimization_analysis(config) do
%{
timestamp: DateTime.utc_now(),
configuration_recommendations: analyze_configuration_optimizations(),
process_optimizations: analyze_process_optimizations(config),
binary_optimizations: analyze_binary_optimizations(),
ets_optimizations: analyze_ets_optimizations(config),
gc_optimizations: analyze_gc_optimizations(),
general_recommendations: get_general_recommendations()
}
end
# --- Private ---
defp analyze_configuration_optimizations do
vm_args = get_vm_args()
recommendations =
[]
|> maybe_add(
should_recommend_heap_tuning(vm_args),
"Consider tuning heap sizes for better memory efficiency"
)
|> maybe_add(
should_recommend_gc_tuning(),
"Consider adjusting garbage collection parameters"
)
%{current_config: vm_args, recommendations: recommendations}
end
defp get_vm_args do
%{
heap_size: :erlang.system_info(:heap_type),
schedulers: :erlang.system_info(:schedulers),
async_threads: :erlang.system_info(:thread_pool_size)
}
end
defp should_recommend_heap_tuning(_vm_args) do
memory = :erlang.memory()
memory[:processes] > memory[:total] * 0.6
end
defp should_recommend_gc_tuning do
{_gc_count, _words_reclaimed, _reductions} =
:erlang.statistics(:garbage_collection)
false
end
defp analyze_process_optimizations(_config) do
long_queues = find_processes_with_long_queues()
large_heaps = find_processes_with_large_heaps()
%{
long_message_queues: long_queues,
large_heap_processes: large_heaps,
recommendations:
generate_process_recommendations(long_queues, large_heaps)
}
end
defp find_processes_with_long_queues do
Process.list()
|> Enum.map(fn pid ->
case Process.info(pid, [:message_queue_len, :registered_name]) do
nil ->
nil
[message_queue_len: len, registered_name: name] when len > 1000 ->
%{pid: pid, name: name, queue_length: len}
_ ->
nil
end
end)
|> Enum.reject(&is_nil/1)
end
defp find_processes_with_large_heaps do
Process.list()
|> Enum.map(fn pid ->
case Process.info(pid, [:heap_size, :registered_name]) do
nil ->
nil
[heap_size: size, registered_name: name] when size > 100_000 ->
%{pid: pid, name: name, heap_size: size}
_ ->
nil
end
end)
|> Enum.reject(&is_nil/1)
end
defp generate_process_recommendations(long_queues, large_heaps) do
recommendations =
[]
|> maybe_add(
long_queues != [],
"Consider implementing backpressure for processes with long queues"
)
|> maybe_add(
large_heaps != [],
"Review processes with large heaps for memory optimization"
)
if Enum.empty?(recommendations),
do: ["Process memory usage appears optimal"],
else: recommendations
end
defp analyze_binary_optimizations do
%{
current_usage: :erlang.memory(:binary),
recommendations: [
"Use iodata instead of string concatenation",
"Consider binary streaming for large data",
"Use binary comprehensions where appropriate",
"Avoid unnecessary binary copying"
]
}
end
defp analyze_ets_optimizations(config) do
tables = Collector.analyze_ets_tables(config)
%{
table_count: tables.total_count,
total_memory: tables.total_memory,
recommendations: [
"Consider using ordered_set for sorted data",
"Use read_concurrency for read-heavy tables",
"Use write_concurrency for write-heavy tables",
"Consider table partitioning for very large tables"
]
}
end
defp analyze_gc_optimizations do
{gc_count, words_reclaimed, _} = :erlang.statistics(:garbage_collection)
%{
collections: gc_count,
words_reclaimed: words_reclaimed,
recommendations: [
"Monitor GC frequency and tune if needed",
"Consider fullsweep_after tuning for long-lived processes",
"Use hibernation for idle processes",
"Avoid creating many short-lived large terms"
]
}
end
defp get_general_recommendations do
[
"Regular memory profiling helps identify issues early",
"Use memory monitoring in production",
"Implement proper resource cleanup",
"Consider using supervision trees for fault tolerance",
"Monitor memory trends over time",
"Use appropriate data structures for your use case",
"Profile before optimizing",
"Test memory usage under load"
]
end
defp maybe_add(list, true, item), do: [item | list]
defp maybe_add(list, false, _item), do: list
end