Skip to content

Instantly share code, notes, and snippets.

View cr0t's full-sized avatar
🏠
Working from home

Sergey Kuznetsov cr0t

🏠
Working from home
View GitHub Profile
@cr0t
cr0t / luhn_bench.exs
Last active April 5, 2024 17:40
Elixir benchmark of two solution approaches for Luhn task from Exercism.org
Mix.install([:benchee])
defmodule LuhnChecksum do
defguard is_even(x) when rem(x, 2) == 0
def with_reverse(digits) do
digits
|> Enum.reverse()
|> Enum.with_index(1)
|> Enum.map(fn
@cr0t
cr0t / elixir_string_benchmarks.exs
Created February 9, 2024 20:26
Just a few benchmarks to compare concatenation (<>), interpolation, joining, and IO lists performances in Elixir
Mix.install([:benchee])
defmodule StringPerf do
def concat([]), do: ""
def concat([head | tail]), do: head <> concat(tail)
def interpol([]), do: ""
def interpol([head | tail]), do: "#{head}#{interpol(tail)}"
def joiner(input), do: Enum.join(input, "")
@cr0t
cr0t / README.md
Created August 24, 2023 19:56
GenServer.reply/2

GenServer.reply/2

Check the other two files in this gist.

In the common.exs we show a standard approach (by the book) to handle incoming requests via handle_call/3 and {:reply, ...} return values. It blocks processing of all the coming requests until the one that is handled finished.

In contrast, in the reply.exs we leverage power of Task.async/1, GenServer.reply/2, and {:noreply, ...} return values. It allows our GenServer process incoming requests in parallel. Then the processing finished, we send results back to the original client (from pid).

Warning

Be careful, as this approach can lead to uncontrollable load to our GenServer.

@cr0t
cr0t / application.ex
Last active July 22, 2023 20:35
Clusty: Auto-clustering Elixir micro-application (a demo of `libcluster` and `:pg`)
defmodule Clusty.Application do
use Application
@topologies local_epmd: [strategy: Cluster.Strategy.LocalEpmd]
@impl true
def start(_type, _args) do
children = [
{Cluster.Supervisor, [@topologies, [name: ClusterSupervisor]]},
Pidgy
@cr0t
cr0t / take_while_vs_exception.exs
Created June 19, 2023 16:50
An Elixir benchmark idea of which born during discussion with one of my mentees on Exercism.io
Mix.install([:benchee])
defmodule Proteins do
@stop "STOP"
@err_msg "invalid codon"
@codons %{
"UGU" => "Cysteine",
"UGG" => "Tryptophan",
"UUU" => "Phenylalanine",
@cr0t
cr0t / elixir.yml
Created November 29, 2022 09:42
GitHub Actions Elixir Workflow Example
name: Elixir CI
on:
push:
branches: ["master"]
pull_request:
branches: ["master"]
env:
MIX_ENV: test
@cr0t
cr0t / bench_async_vs_map.exs
Last active November 21, 2022 13:55
Performance comparison between simple `Enum.map` and `Task.async_stream` in Elixir (oversimplified case)
Mix.install([
{:benchee, "~> 1.0"}
])
defmodule Cruncher do
def async(n) do
1..n
|> Task.async_stream(&(&1 ** 2))
|> Enum.reduce(0, fn {:ok, s}, acc -> s + acc end)
end
@cr0t
cr0t / cond_vs_pattern.exs
Created November 15, 2022 22:30
Performance comparison between `cond` and multiple-clauses functions in Elixir
Mix.install([
{:benchee, "~> 1.0"}
])
defmodule BirdCond do
def busy_days(list) do
cond do
list == [] -> 0
hd(list) < 5 -> busy_days(tl(list))
true -> 1 + busy_days(tl(list))
# Origin: https://blog.sequin.io/how-we-used-elixirs-observer-to-hunt-down-bottlenecks/
defmodule Overload do
# Define a CPU-intenstive work function, which can call itself
# recursively (forever)
def recursive do
:public_key.generate_key({:rsa, 4096, 65537})
recursive()
end
end
@cr0t
cr0t / uni.erl
Created July 27, 2022 16:10
Universal Server ("My favorite Erlang Program")
% Read more:
% - https://joearms.github.io/published/2013-11-21-My-favorite-erlang-program.html
% - https://ferd.ca/my-favorite-erlang-container.html
%
% How to run:
% $ erl
% > c(uni).
% {ok,uni}
% > uni:test().
% 30414093201713378043612608166064768844377641568960512000000000000