From 2c3dcdc5a04e12d40aedc571087e27db41dfa1b7 Mon Sep 17 00:00:00 2001 From: Jeff Kreeftmeijer Date: Fri, 5 Dec 2025 13:52:00 +0100 Subject: [PATCH] Don't use length() as it's expensive Replace expensive length/1 calls with more performant alternatives to fix Credo warnings flagged in CI[1]. - In scheduler.ex: Use pattern matching [_ | _] instead of length(events) > 0 in guard clause - In test files: Replace assert length(stack) > 0 with refute Enum.empty?(stack) for clearer intent and better performance In Elixir, length/1 is O(n) because lists are implemented as linked lists, requiring traversal of the entire list to count elements. For emptiness checks, pattern matching against [] or [_ | _] is O(1) and Enum.empty?/1 stops at the first element, making them much more efficient than counting all elements just to compare with zero. These changes maintain the same functionality while following Elixir best practices for checking list emptiness. [1]: https://github.com/appsignal/appsignal-elixir/actions/runs/19948488321/job/57203328408 [skip changeset] --- lib/appsignal/check_in/scheduler.ex | 2 +- test/appsignal/error_test.exs | 10 +++++----- test/appsignal/stacktrace_test.exs | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/appsignal/check_in/scheduler.ex b/lib/appsignal/check_in/scheduler.ex index fe8d5db5a..ae2b4245c 100644 --- a/lib/appsignal/check_in/scheduler.ex +++ b/lib/appsignal/check_in/scheduler.ex @@ -120,7 +120,7 @@ defmodule Appsignal.CheckIn.Scheduler do end @impl true - def terminate(_reason, %{events: events}) when length(events) > 0 do + def terminate(_reason, %{events: [_ | _] = events}) do # If any events are stored, attempt to transmit them before the # process is terminated. handle_continue({:transmit, events}, initial_state()) diff --git a/test/appsignal/error_test.exs b/test/appsignal/error_test.exs index b1c505578..8a4e3b59b 100644 --- a/test/appsignal/error_test.exs +++ b/test/appsignal/error_test.exs @@ -21,7 +21,7 @@ defmodule Appsignal.ErrorTest do test "format's the error's stack trace", %{metadata: metadata} do {_name, _message, stack} = metadata assert is_list(stack) - assert length(stack) > 0 + refute Enum.empty?(stack) assert Enum.all?(stack, &is_binary(&1)) end end @@ -46,7 +46,7 @@ defmodule Appsignal.ErrorTest do test "format's the error's stack trace", %{metadata: metadata} do {_name, _message, stack} = metadata assert is_list(stack) - assert length(stack) > 0 + refute Enum.empty?(stack) assert Enum.all?(stack, &is_binary(&1)) end end @@ -73,7 +73,7 @@ defmodule Appsignal.ErrorTest do test "format's the error's stack trace", %{metadata: metadata} do {_name, _message, stack} = metadata assert is_list(stack) - assert length(stack) > 0 + refute Enum.empty?(stack) assert Enum.all?(stack, &is_binary(&1)) end end @@ -101,7 +101,7 @@ defmodule Appsignal.ErrorTest do test "format's the error's stack trace", %{metadata: metadata} do {_name, _message, stack} = metadata assert is_list(stack) - assert length(stack) > 0 + refute Enum.empty?(stack) assert Enum.all?(stack, &is_binary(&1)) end end @@ -126,7 +126,7 @@ defmodule Appsignal.ErrorTest do test "format's the error's stack trace", %{metadata: metadata} do {_name, _message, stack} = metadata assert is_list(stack) - assert length(stack) > 0 + refute Enum.empty?(stack) assert Enum.all?(stack, &is_binary(&1)) end end diff --git a/test/appsignal/stacktrace_test.exs b/test/appsignal/stacktrace_test.exs index 7fa9507a9..a85286743 100644 --- a/test/appsignal/stacktrace_test.exs +++ b/test/appsignal/stacktrace_test.exs @@ -14,7 +14,7 @@ defmodule Appsignal.StacktraceTest do end test "does not return an empty list", %{stack: stack} do - assert length(stack) > 0 + refute Enum.empty?(stack) end test "returns a stacktrace containing the error", %{