Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Elixir propaganda

Elixir propaganda

Sobolev Nikita

December 03, 2016
Tweet

More Decks by Sobolev Nikita

Other Decks in Programming

Transcript

  1. План доклада • Быстро пройдемся по базовым вещам • Посмотрим,

    чем Elixir отличается от других языков • А потом поговорим об инфраструктуре вокруг языка
  2. Elixir • Написан Jose Valim (Rails Core Dev) в 2012

    году • Основывается на BEAM
  3. Типы данных iex> 1 # integer iex> 1.0 # float

    iex> true # boolean iex> :atom # atom iex> "elixir" # string (unicode!) iex> [1, 2, 3] # list iex> {1, 2, 3} # tuple iex> %{a: 1} # map iex> [key: v] # keyword list
  4. Приятные фичи • Pattern matching [1 | tail] = [1,

    2, 3] #=> [1, 2, 3] tail #=> [2, 3] • Pipes "Elixir rocks" |> String.upcase |> String.split #=> ["ELIXIR", "ROCKS"] • Макросы
  5. parent = self() #=> PID<0.80.0> spawn fn -> send(parent, {:hello,

    self()}) end #=> PID<0.83.0> receive do {:hello, pid} -> "Got hello from #{inspect pid}" end #=> "Got hello from #PID<0.83.0>" Процессы - изолированные, параллельные, легковесные
  6. Уже готовые обертки • Agent - простая обертка над процессом

    с состоянием • GenServer - "generic process", инкапсулирует работу с состоянием, добавляют возможность использовать sync и async методы • GenEvent - позволяет работать с событиями • Task - позволяет запустить процесс, а потом получить его результат
  7. Обработка ошибок try do raise "Big Bad Error" rescue e

    -> IO.inspect(e) end #=> %RuntimeError{message: "Big Bad Error"} try do throw "Big Bad Throwable Error" catch e -> IO.inspect(e) end #=> "Big Bad Throwable Error" А еще все умрет, если умрет связанный (linked) процесс...
  8. defmodule Stack do use GenServer def start_link(state, opts \\ [])

    do GenServer.start_link(__MODULE__, state, opts) end def handle_call(:pop, _from, [h | t]) do {:reply, h, t} end def handle_cast({:push, h}, t) do {:noreply, [h | t]} end end Наше приложение
  9. Строим supervisor tree # Import helpers for defining supervisors import

    Supervisor.Spec # Supervise the Stack server which will be started with # a single argument [:hello] and the default registered # name of MyStack. children = [ worker(Stack, [[:hello], [name: MyStack]]) ] # Start the supervisor with our child {:ok, pid} = Supervisor.start_link(children, strategy: :one_for_one)
  10. Используем приложение GenServer.call(MyStack, :pop) #=> :hello GenServer.cast(MyStack, {:push, :world}) #=>

    :ok GenServer.call(MyStack, :pop) #=> :world GenServer.call(MyStack, :pop) #=> ??? #=> BOOM!!!
  11. source = File.read!("source.txt") #=> "roses are red\nviolets are blue\n\n" source

    |> String.split("\n") |> Enum.flat_map(&String.split/1) |> Enum.reduce(%{}, fn(word, map) -> Map.update(map, word, 1, &(&1 + 1)) end) Жадный подход
  12. Асинхронный подход File.stream!("source.txt", [], :line) |> Flow.from_enumerable() |> Flow.flat_map(&String.split/1) |>

    Flow.partition() # the magic happens here |> Flow.reduce(fn -> %{} end, fn(word, map) -> Map.update(map, word, 1, &(&1 + 1)) end) |> Enum.into(%{})
  13. Результаты • На маленьком объеме данных побеждает "жадный подход" (более

    чем в 19 раз) • На средних и больших побеждает Flow (от 3 раз) • https://github.com/sobolevn/fpconf_elixir
  14. mix • Встроенный build-tool, который выполняет все необходимые действия •

    Управляет зависимостями (как bundler) • Запускает задачи (как manage.py, rake) • Управляет конфигурацией
  15. 4.0GHZ Core i7 (quad core), 32GB RAM Framework Throughput (req/

    s) Latency (ms) Consistency (σ ms) Gin 59001.07 1.84 1.35 Phoenix 31417.81 3.52 3.50 Express Cluster 26244.35 3.92 3.25 Sinatra 8334.84 7.46 3.38 Express 9477.14 10.56 1.39 Rails 3452.58 17.96 7.73
  16. Ecto defmodule Weather do use Ecto.Schema import Ecto.Query schema "weather"

    do field :city, :string field :temp_lo, :integer field :temp_hi, :integer end def keyword_query do query = from w in Weather, where: w.city == "Moscow" and w.temp_lo > 0, select: w Repo.all(query) end end
  17. Когда использовать? • У вас высоконагруженное приложение • У вас

    есть задачи, которые нужно выполнять асинхронно / параллельно • Вам крайне важна отказоустойчивость
  18. Материалы • Keynote by Jose Valim: https://www.youtube.com/watch?v=srtMWzyqdp8 • The Road

    to 2 Million Websocket Connections in Phoenix: https:// www.youtube.com/watch?v=c6JcVwbOGXc • Processing 2.7 million images with Elixir: https://www.youtube.com/watch? v=xoNRtWl4fZU • Elixir on the Web: Raising Phoenix: https://www.youtube.com/watch? v=h4z7WnMLXKI • benchee: https://github.com/PragTob/benchee • Phoenix benchmarks: https://github.com/mroth/phoenix-showdown • Код из презентации: https://github.com/sobolevn/fpconf_elixir