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
raxol lib raxol benchmark suites terminal_benchmarks.ex
Raw

lib/raxol/benchmark/suites/terminal_benchmarks.ex

defmodule Raxol.Benchmark.Suites.TerminalBenchmarks do
@moduledoc """
Performance benchmarks for terminal emulation operations.
"""
alias Raxol.Terminal.Emulator
def run(opts \\ []) do
Benchee.run(
%{
"ANSI sequence parsing" => fn input ->
emulator = setup_emulator()
Emulator.SafeEmulator.process_input(emulator, input)
end,
"Plain text writing" => fn input ->
emulator = setup_emulator()
write_plain_text(emulator, input)
end,
"Colored text rendering" => fn ->
emulator = setup_emulator()
write_colored_text(emulator)
end,
"Cursor movement operations" => fn ->
emulator = setup_emulator()
perform_cursor_movements(emulator)
end,
"Screen clearing" => fn ->
emulator = setup_emulator()
clear_operations(emulator)
end,
"Scrolling performance" => fn ->
emulator = setup_emulator_with_content()
scroll_operations(emulator)
end,
"Buffer resize" => fn ->
emulator = setup_emulator()
resize_operations(emulator)
end,
"Complex ANSI art" => fn ->
emulator = setup_emulator()
render_ansi_art(emulator)
end
},
Keyword.merge(default_options(), opts)
)
end
defp default_options do
[
warmup: 2,
time: 5,
memory_time: 2,
inputs: %{
"small (100 chars)" => generate_text(100),
"medium (1KB)" => generate_text(1_024),
"large (10KB)" => generate_text(10_240),
"huge (100KB)" => generate_text(102_400)
},
formatters: [
{Benchee.Formatters.Console, extended_statistics: true},
{Benchee.Formatters.HTML, file: "bench/output/terminal_benchmarks.html"}
]
]
end
defp setup_emulator do
{:ok, pid} = Emulator.SafeEmulator.start_link(width: 80, height: 24)
pid
end
defp setup_emulator_with_content do
emulator = setup_emulator()
# Fill buffer with content
Enum.each(1..100, fn i ->
Emulator.SafeEmulator.process_input(
emulator,
"Line #{i}: " <> String.duplicate("x", 70) <> "\n"
)
end)
emulator
end
defp write_plain_text(emulator, text) do
Emulator.SafeEmulator.process_input(emulator, text)
end
defp write_colored_text(emulator) do
colors = [31, 32, 33, 34, 35, 36, 37]
Enum.each(1..10, fn i ->
color = Enum.at(colors, rem(i, length(colors)))
Emulator.SafeEmulator.process_input(
emulator,
"\e[#{color}mColored line #{i}\e[0m\n"
)
end)
end
defp perform_cursor_movements(emulator) do
movements = [
# Home
"\e[H",
# Absolute position
"\e[10;20H",
# Up 5
"\e[5A",
# Down 3
"\e[3B",
# Right 15
"\e[15C",
# Left 8
"\e[8D",
# Save position
"\e[s",
# Restore position
"\e[u"
]
Enum.each(movements, fn seq ->
Emulator.SafeEmulator.process_input(emulator, seq)
end)
end
defp clear_operations(emulator) do
operations = [
# Clear screen
"\e[2J",
# Clear to end of line
"\e[K",
# Clear to beginning of line
"\e[1K",
# Clear entire line
"\e[2K"
]
Enum.each(operations, fn seq ->
Emulator.SafeEmulator.process_input(emulator, seq)
Emulator.SafeEmulator.process_input(emulator, "Some text")
end)
end
defp scroll_operations(emulator) do
# Scroll down
Enum.each(1..10, fn _ ->
Emulator.SafeEmulator.process_input(emulator, "\n")
end)
# Scroll regions
# Set scroll region
Emulator.SafeEmulator.process_input(emulator, "\e[10;20r")
# Reverse scroll
Enum.each(1..5, fn _ ->
Emulator.SafeEmulator.process_input(emulator, "\eM")
end)
end
defp resize_operations(emulator) do
sizes = [
{100, 30},
{120, 40},
{80, 50},
{160, 48},
# Back to original
{80, 24}
]
Enum.each(sizes, fn {width, height} ->
Emulator.SafeEmulator.resize(emulator, width, height)
end)
end
defp render_ansi_art(emulator) do
# Complex ANSI art with multiple colors and positioning
art = """
\e[H\e[2J\e[3J
\e[1;1H\e[48;5;17m \e[0m
\e[2;1H\e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[0m
\e[3;1H\e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[0m
\e[4;1H\e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[0m
\e[5;1H\e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[0m
\e[6;1H\e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[48;5;21m \e[48;5;17m \e[0m
\e[7;1H\e[48;5;17m \e[0m
"""
Emulator.SafeEmulator.process_input(emulator, art)
end
defp generate_text(size) do
# Generate realistic text with some ANSI sequences
base_text = "The quick brown fox jumps over the lazy dog. "
repetitions = div(size, byte_size(base_text))
text = String.duplicate(base_text, repetitions)
# Add some ANSI sequences
if size > 1000 do
text
|> String.split(" ")
|> Enum.map_every(10, fn word ->
color = Enum.random(31..37)
"\e[#{color}m#{word}\e[0m"
end)
|> Enum.join(" ")
else
text
end
end
end