Skip to content
Charlie edited this page Sep 9, 2021 · 19 revisions

iex

  • Access results of previous commands: v
  • Abort multi-line command without exiting: #iex:break
  • :observer.start()

Remote Connect

  • iex --name app@127.0.0.1 -S mix phx.server
  • iex --name inspector@127.0.0.1 --remsh wds@127.0.0.1

Both nodes need to be using name or sname.

In Anger

Process Measurements

  • heap_size - size in words of the youngest heap generation of the process, also includes the stack.
  • total_heap_size - words of all heap fragments of the process, also includes the stack and unreceived messages.
  • memory - Size in bytes of the process. Includes call stack, heap, and internal structures.

Important: 1 Word is 8 bytes on a 64-bit architecture (4 bytes for 32-bit).

http://erlang.org/doc/man/erlang.html#process_info-2 https://hexdocs.pm/observer_cli/

  • Make Erlang crash with a dump: :erlang.halt('oops')

Garbage Collector

  • Each process has a separate stack and heap that grow towards each other.

  • When they meet GC is triggered.

  • If not enough garbage is collected, the heap grows.

  • There is also a global "large object" space (RefC binaries).

  • A fullsweep is triggered when there is no more room on the old heap.

  • fullsweep_after - Maximum number of generational collections before forcing a fullsweep.

Applications, Processes, etc.

Start single application

iex> Application.start(:kv)
:ok

Start an application and its dependencies

iex> Application.ensure_all_started(:kv)
{:ok, [:logger, :kv]}

Sleep a process (mainly for testing)

# https://hexdocs.pm/elixir/Process.html#sleep/1
Process.sleep(2000)

Syntax

Anonymous Functions

iex(13)> Enum.map([1,2,3], fn x -> x*x*x end) 
[1, 8, 27]
iex(14)> Enum.map([1,2,3], &(&1*&1*&1))      
[1, 8, 27]
iex(15)> Enum.map([1,2,3], &(:math.pow(&1,3) |> round))
[1, 8, 27]

Interesting Snippets

:timer.tc(fn ->
  for a <- 1..100, b <- 1..100, c <- 1..100, a*a + b*b == c*c, do: [a, b, c]
end) |> IO.inspect

# {30319,
#  [
#    [3, 4, 5],
#    [4, 3, 5],
#    [5, 12, 13],

:timer.tc(fn ->
  for a <- 1..100, b <- (a+1)..100, c <- (b+1)..100, a*a + b*b == c*c, do: [a, b, c]
end) |> IO.inspect

{5131,
#  [
#    [3, 4, 5],
#    [5, 12, 13],

Unix Time

iex(4)> System.os_time(:second)
1601687572

Processes

iex(12)> spawn Procs, :greeter, []
#PID<0.142.0>
iex(13)> pid = v(-1)
#PID<0.142.0>
iex(14)> send pid, "Hello"
Hello "Hello"
"Hello"
iex(15)> send pid, "World"
"World"
  • Messages sent to nonexistent processes are quietly thrown away.
iex(1)> pid = spawn_link Procs, :counter, [3]
#PID<0.273.0>
iex(2)> send pid, {:boom, :bad}
** (EXIT from #PID<0.271.0>) shell process exited with reason: :bad

Interactive Elixir (1.10.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> pid = spawn_link Procs, :counter, [3]
#PID<0.277.0>
iex(2)> send pid, {:boom, :normal}
{:boom, :normal}
iex(3)>
  • By default, processes fail independently of each other
  • spawn_link to link the fate of the current process to the spawned process
  • Non-normal process exit causes iex to restart

flush() can be used to flush and print all messages in the mailbox

iex> send self(), :hello
:hello
iex> flush()
:hello
:ok

BEAM VM

  • Processes do not share memory, independently GC'd

  • Built for concurrency

  • Communication between Processes (Actors) happens via message passing

  • JVM maps threads to OS threads and lets OS schedule them

  • BEAM scheduler starts a thread per CPU core and manages the work

  • Maintains a "run queue" for processes, allows each process to run a certain number of statements, until complete, or until blocked by IO

Hackney

:hackney_trace.enable(:max, :io)

Docs

Clone this wiki locally