Parallelize template rendering
authorrinpatch <rinpatch@sdf.org>
Thu, 15 Aug 2019 14:41:26 +0000 (17:41 +0300)
committerrinpatch <rinpatch@sdf.org>
Thu, 15 Aug 2019 15:05:50 +0000 (18:05 +0300)
lib/mix/tasks/pleroma/benchmark.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
lib/pleroma/web/web.ex

index a45940bf3edfae6cb114617efff2e0cb384e0405..4cc63472764a2f6dee54fb0dd7c2f80240c477fa 100644 (file)
@@ -37,17 +37,37 @@ defmodule Mix.Tasks.Pleroma.Benchmark do
       |> Map.put("blocking_user", user)
       |> Map.put("muting_user", user)
       |> Map.put("user", user)
+      |> Map.put("limit", 80)
       |> Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities()
       |> Enum.reverse()
 
-    Benchee.run(%{
-      "render_timeline" => fn ->
-        Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
-          activities: activities,
-          for: user,
-          as: :activity
-        })
-      end
-    })
+    inputs = %{
+      "One activity" => Enum.take_random(activities, 1),
+      "Ten activities" => Enum.take_random(activities, 10),
+      "Twenty activities" => Enum.take_random(activities, 20),
+      "Forty activities" => Enum.take_random(activities, 40),
+      "Eighty activities" => Enum.take_random(activities, 80)
+    }
+
+    Benchee.run(
+      %{
+        "Parallel rendering" => fn activities ->
+          Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
+            activities: activities,
+            for: user,
+            as: :activity
+          })
+        end,
+        "Standart rendering" => fn activities ->
+          Pleroma.Web.MastodonAPI.StatusView.render("index.json", %{
+            activities: activities,
+            for: user,
+            as: :activity,
+            parallel: false
+          })
+        end
+      },
+      inputs: inputs
+    )
   end
 end
index 492af170206bbdc3256901e3f397676b5bb95baf..7e4e992801a8508eea62a666877857fdfad9242a 100644 (file)
@@ -70,12 +70,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
 
   def render("index.json", opts) do
     replied_to_activities = get_replied_to_activities(opts.activities)
+    parallel = unless is_nil(opts[:parallel]), do: opts[:parallel], else: true
 
     opts.activities
     |> safe_render_many(
       StatusView,
       "status.json",
-      Map.put(opts, :replied_to_activities, replied_to_activities)
+      Map.put(opts, :replied_to_activities, replied_to_activities),
+      parallel
     )
   end
 
index 6873465544b19fab1c9d31f88689708a52cbf87f..bfb6c728784055ab925799f1ef7f84de7aa0ee76 100644 (file)
@@ -66,9 +66,23 @@ defmodule Pleroma.Web do
       end
 
       @doc """
-      Same as `render_many/4` but wrapped in rescue block.
+      Same as `render_many/4` but wrapped in rescue block and parallelized (unless disabled by passing false as a fifth argument).
       """
-      def safe_render_many(collection, view, template, assigns \\ %{}) do
+      def safe_render_many(collection, view, template, assigns \\ %{}, parallel \\ true)
+
+      def safe_render_many(collection, view, template, assigns, true) do
+        Enum.map(collection, fn resource ->
+          Task.async(fn ->
+            as = Map.get(assigns, :as) || view.__resource__
+            assigns = Map.put(assigns, as, resource)
+            safe_render(view, template, assigns)
+          end)
+        end)
+        |> Enum.map(&Task.await(&1, :infinity))
+        |> Enum.filter(& &1)
+      end
+
+      def safe_render_many(collection, view, template, assigns, false) do
         Enum.map(collection, fn resource ->
           as = Map.get(assigns, :as) || view.__resource__
           assigns = Map.put(assigns, as, resource)