@@ -37,17 +37,37 @@ defmodule Mix.Tasks.Pleroma.Benchmark do | |||||
|> Map.put("blocking_user", user) | |> Map.put("blocking_user", user) | ||||
|> Map.put("muting_user", user) | |> Map.put("muting_user", user) | ||||
|> Map.put("user", user) | |> Map.put("user", user) | ||||
|> Map.put("limit", 80) | |||||
|> Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities() | |> Pleroma.Web.ActivityPub.ActivityPub.fetch_public_activities() | ||||
|> Enum.reverse() | |> 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 | ||||
end | end |
@@ -70,12 +70,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do | |||||
def render("index.json", opts) do | def render("index.json", opts) do | ||||
replied_to_activities = get_replied_to_activities(opts.activities) | replied_to_activities = get_replied_to_activities(opts.activities) | ||||
parallel = unless is_nil(opts[:parallel]), do: opts[:parallel], else: true | |||||
opts.activities | opts.activities | ||||
|> safe_render_many( | |> safe_render_many( | ||||
StatusView, | StatusView, | ||||
"status.json", | "status.json", | ||||
Map.put(opts, :replied_to_activities, replied_to_activities) | |||||
Map.put(opts, :replied_to_activities, replied_to_activities), | |||||
parallel | |||||
) | ) | ||||
end | end | ||||
@@ -66,9 +66,23 @@ defmodule Pleroma.Web do | |||||
end | end | ||||
@doc """ | @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 -> | Enum.map(collection, fn resource -> | ||||
as = Map.get(assigns, :as) || view.__resource__ | as = Map.get(assigns, :as) || view.__resource__ | ||||
assigns = Map.put(assigns, as, resource) | assigns = Map.put(assigns, as, resource) | ||||