LoginSignup
7
2

More than 1 year has passed since last update.

iPad Airであそぶ 〜Flowを使ったら速くなるか?〜

Last updated at Posted at 2023-02-01

やってみたこと
iPad M1はマルチコアなので、Flow使えば速度あがるのでは?という思いつきから
ElixirDesktopを使えばElixirのライブラリFLowが動けば希望が見えるかも
このコラムではmacでiosアプリのビルド方法等には触れない
実験がメインである

ベース↓

こちらに付属するElixirDesktopのTODOアプリを改造してなんちゃってiexを作る

ソースを改造する

elixir-app/mix.exs
defmodule Todo.MixProject do
  use Mix.Project

  @version "1.0.0"
  def project do
    [
      app: :todo_app,
      version: @version,
      elixir: "~> 1.10",
      elixirc_paths: elixirc_paths(Mix.env()),
      compilers: [:phoenix | Mix.compilers()],
      start_permanent: Mix.env() == :prod,
      deps: deps(),
      aliases: aliases()
    ]
  end

  # Specifies which paths to compile per environment.
  defp elixirc_paths(:test), do: ["lib", "test/support"]
  defp elixirc_paths(_), do: ["lib"]

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      mod: {TodoApp, []},
      extra_applications: [
        :logger,
        :ssl,
        :crypto,
        :sasl,
        :tools,
        :inets | extra_applications(Mix.target())
      ]
    ]
  end

  def extra_applications(:host) do
    [:observer]
  end

  def extra_applications(_mobile) do
    []
  end

  defp aliases do
    [
      "assets.deploy": [
        "phx.digest.clean --all",
        "esbuild default --minify",
        "sass default --no-source-map --style=compressed",
        "phx.digest"
      ],
      lint: [
        "compile --warnings-as-errors",
        "format --check-formatted",
        "credo --ignore design"
      ]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    deps_list = [
      {:ecto_sqlite3, "~> 0.8"},
      {:exqlite, github: "elixir-desktop/exqlite", override: true},
      # {:desktop, path: "../desktop"},
      {:desktop, "~> 1.4"},

      # Phoenix
      {:phoenix, "~> 1.6"},
      {:phoenix_live_view, "~> 0.17.11"},
      {:phoenix_html, "~> 3.0"},
      {:phoenix_live_reload, "~> 1.3", only: [:dev]},
      {:gettext, "~> 0.18"},
      {:plug_cowboy, "~> 2.5"},
      {:jason, "~> 1.2"},

      # Assets
      {:esbuild, "~> 0.2", runtime: Mix.env() == :dev},
      {:dart_sass, "~> 0.2", runtime: Mix.env() == :dev},

      # Credo
-     {:credo, "~> 1.5", only: [:dev, :test], runtime: false}
+     {:credo, "~> 1.5", only: [:dev, :test], runtime: false},
+     {:flow, "~> 1.2"}
    ]

    if Mix.target() in [:android, :ios] do
      deps_list ++ [{:wx, "~> 1.0", hex: :bridge, targets: [:android, :ios]}]
    else
      deps_list
    end
  end
end
elixir-app/lib/todo_web/live/todo_live.ex
defmodule TodoWeb.TodoLive do
  @moduledoc """
    Main live view of our TodoApp. Just allows adding, removing and checking off
    todo items
  """
  use TodoWeb, :live_view

  @impl true

  def mount(_args, _session, socket) do
    todos = TodoApp.Todo.all_todos()
    TodoApp.Todo.subscribe()
-   {:ok, assign(socket, todos: todos)}
+   {:ok, assign(socket, todos: todos) |> assign(exec: "") |> assign(text: "")}
  end

  @impl true
  def handle_info(:changed, socket) do
    todos = TodoApp.Todo.all_todos()
    {:noreply, assign(socket, todos: todos)}
  end

  @impl true
  def handle_event("add", %{"text" => ""}, socket) do
    {:noreply, socket}
  end+

  def handle_event("add", %{"text" => text}, socket) do
-   TodoApp.Todo.add_todo(text, "todo")
-
-   Desktop.Window.show_notification(TodoWindow, "Added todo: #{text}",
-     callback: &notification_event/1
-   )
-
-   {:noreply, socket}
+   exec =
+     Code.eval_string(text)
+     |> elem(0)
+     |> inspect()
+
+   IO.inspect(exec)
+   {:noreply, socket |> assign(exec: exec) |> assign(text: text)}
  end

  def handle_event("toggle", %{"id" => id}, socket) do
    id = String.to_integer(id)
    TodoApp.Todo.toggle_todo(id)
    {:noreply, socket}
  end

  def handle_event("drop", %{"id" => id}, socket) do
    id = String.to_integer(id)
    TodoApp.Todo.drop_todo(id)
    {:noreply, socket}
  end

  def notification_event(action) do
    Desktop.Window.show_notification(TodoWindow, "You did '#{inspect(action)}' me!",
      id: :click,
      type: :warning
    )
  end
end
elixir-app/lib/todo_web/live/todo_live.html.leex
 <div class="header">
-  <h2><%= gettext "My Todo List" %></h2>
+  <h2>ios iex</h2>
   <form phx-submit="add">
-    <input type="text" name="text" placeholder="<%= gettext "Add new todo item..." %>">
-    <button type="submit">&#8617;</button>
+    <textarea style="height: 300px; width:300px" name="text"><%= @text %></textarea>
+    <button type="submit">Run</button>
   </form>
+  <textarea style="height: 300px; width:300px" name="text"><%= @exec %></textarea>
 </div>

- <ul>
-  <%= for item <- @todos do %>
-  <li phx-click="toggle" phx-value-id="<%= item.id %>" class="<%= item.status %>"
-     ><%= item.text %>
-     <span class="close" phx-click="drop" phx-value-id="<%= item.id %>">&#215;</span>
-     </li>
-   <% end %>
- </ul>

実行してみた

実験用ソース
defmodule Hoge do
  def test_flow() do
    1..10_000_000
    |> Flow.from_enumerable() 
    |> Flow.map(fn x -> x * 2 end)
    |> Enum.sum()
  end

 def test_enum() do
    1..10_000_000 
    |> Enum.map(fn x -> x * 2 end)
    |> Enum.sum()
  end
end

flow = (:timer.tc(fn -> Hoge.test_flow() end) |> elem(0)) / 1_000_000
enum = (:timer.tc(fn -> Hoge.test_enum() end) |> elem(0)) / 1_000_000

[flow,enum, enum / flow]

実験結果

Flowを使うとこのケースの場合は1.3〜1.4倍動作が速い

IMG_0006.PNG

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2