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 / registry_ets.ex
Created September 6, 2024 13:26
Two (very simple) process registries written in Elixir, one with is fully based on GenServer, while the other stores its state in an ETS table
defmodule RegistryEts do
use GenServer
def register(key, pid \\ self()),
do: GenServer.call(__MODULE__, {:register, key, pid})
def whereis(key) do
case :ets.lookup(__MODULE__, key) do
[{^key, pid}] -> pid
_ -> nil
@cr0t
cr0t / map_vs_case_bench.exs
Created August 10, 2024 11:15
Compare performance of solutions that is based on `case` and uses a Map to get values
Mix.install([:benchee])
defmodule ResistorColor do
@color_map %{
black: 0,
brown: 1,
red: 2,
orange: 3,
yellow: 4,
green: 5,
@cr0t
cr0t / list_map_tuple_bench.exs
Created July 20, 2024 10:25
Compare access times to the elements in a Tuple, a Map, or a List containers
Mix.install([:benchee])
# Compare access times to the elements in a Tuple, a Map, or a List containers.
#
# At first, we generate some input that is being used in the access_* functions:
# they go over each element and check if it is what we put there. One by one.
defmodule Accessor do
@elements_n 10_000
@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