From 93d40c9cecc977c75ca5892c1f694ccbdb868a6e Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Sat, 9 May 2026 23:06:49 -0500 Subject: [PATCH] Simplify insert/2 common case MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simplifies insertion for the case where the buffer is full and an element is dropped. This is usually a common real world case for long running applications. A simple performance test showed a ~13% speed increase on an M4 MBP. The following is a Claude-assisted diff of the bytecodes which shows an eliminated stack frame and BIF call: ``` Before — ~20 instructions, 4-slot stack frame, BIF call: get_map_elements ... [b: x2] # extract :b is_ne_exact x2, nil # guard b != [] allocate 4, 3 # ⬅︎ stack frame init_yregs y0 move x2 → y1 move x1 → y2 move x0 → y3 # ⬅︎ spill all three live regs get_map_elements ... [a: y0] # extract :a (with deopt fallback) ... (deopt path through elixir_erl_pass.no_parens_remote/2) ... bif :tl # ⬅︎ tl(b) as a BIF call test_heap 2,2 put_list y2, x0, x0 # cons [item | a] put_map_exact ... [a, b] deallocate 4 return After — 7 instructions, no stack frame, decomposition opcode: get_map_elements ... [b: x3, a: x2] # ⬅︎ both fields in one shot is_nonempty_list x3 # ⬅︎ single tag check test_heap 2,4 get_tl x3 → x3 # ⬅︎ tail-of opcode, no BIF call put_list x1, x2, x1 # cons [item | a] put_map_exact ... [a, b] return ``` --- lib/circular_buffer.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/circular_buffer.ex b/lib/circular_buffer.ex index d0d045d..3a18692 100644 --- a/lib/circular_buffer.ex +++ b/lib/circular_buffer.ex @@ -52,8 +52,8 @@ defmodule CircularBuffer do Inserts a new item into the next location of the circular buffer """ @spec insert(t(), any()) :: t() - def insert(%CB{b: b} = cb, item) when b != [] do - %{cb | a: [item | cb.a], b: tl(b)} + def insert(%CB{a: a, b: [_ | tl_b]} = cb, item) do + %{cb | a: [item | a], b: tl_b} end def insert(%CB{count: count, max_size: max_size} = cb, item) when count < max_size do