diff options
Diffstat (limited to 'benchmarks/load_testing')
| -rw-r--r-- | benchmarks/load_testing/activities.ex | 384 | ||||
| -rw-r--r-- | benchmarks/load_testing/fetcher.ex | 236 | ||||
| -rw-r--r-- | benchmarks/load_testing/users.ex | 22 | 
3 files changed, 365 insertions, 277 deletions
| diff --git a/benchmarks/load_testing/activities.ex b/benchmarks/load_testing/activities.ex index 482e42fc1..074ded457 100644 --- a/benchmarks/load_testing/activities.ex +++ b/benchmarks/load_testing/activities.ex @@ -22,8 +22,21 @@ defmodule Pleroma.LoadTesting.Activities do    @max_concurrency 10    @visibility ~w(public private direct unlisted) -  @types ~w(simple emoji mentions hell_thread attachment tag like reblog simple_thread remote) -  @groups ~w(user friends non_friends) +  @types [ +    :simple, +    :emoji, +    :mentions, +    :hell_thread, +    :attachment, +    :tag, +    :like, +    :reblog, +    :simple_thread +  ] +  @groups [:friends_local, :friends_remote, :non_friends_local, :non_friends_local] +  @remote_groups [:friends_remote, :non_friends_remote] +  @friends_groups [:friends_local, :friends_remote] +  @non_friends_groups [:non_friends_local, :non_friends_remote]    @spec generate(User.t(), keyword()) :: :ok    def generate(user, opts \\ []) do @@ -34,33 +47,24 @@ defmodule Pleroma.LoadTesting.Activities do      opts = Keyword.merge(@defaults, opts) -    friends = -      user -      |> Users.get_users(limit: opts[:friends_used], local: :local, friends?: true) -      |> Enum.shuffle() +    users = Users.prepare_users(user, opts) -    non_friends = -      user -      |> Users.get_users(limit: opts[:non_friends_used], local: :local, friends?: false) -      |> Enum.shuffle() +    {:ok, _} = Agent.start_link(fn -> users[:non_friends_remote] end, name: :non_friends_remote)      task_data =        for visibility <- @visibility,            type <- @types, -          group <- @groups, +          group <- [:user | @groups],            do: {visibility, type, group}      IO.puts("Starting generating #{opts[:iterations]} iterations of activities...") -    friends_thread = Enum.take(friends, 5) -    non_friends_thread = Enum.take(friends, 5) -      public_long_thread = fn -> -      generate_long_thread("public", user, friends_thread, non_friends_thread, opts) +      generate_long_thread("public", users, opts)      end      private_long_thread = fn -> -      generate_long_thread("private", user, friends_thread, non_friends_thread, opts) +      generate_long_thread("private", users, opts)      end      iterations = opts[:iterations] @@ -73,10 +77,10 @@ defmodule Pleroma.LoadTesting.Activities do              i when i == iterations - 2 ->                spawn(public_long_thread)                spawn(private_long_thread) -              generate_activities(user, friends, non_friends, Enum.shuffle(task_data), opts) +              generate_activities(users, Enum.shuffle(task_data), opts)              _ -> -              generate_activities(user, friends, non_friends, Enum.shuffle(task_data), opts) +              generate_activities(users, Enum.shuffle(task_data), opts)            end          )        end) @@ -123,22 +127,22 @@ defmodule Pleroma.LoadTesting.Activities do      Enum.each(1..activity_count, fn _ ->        random = :rand.uniform()        i = Enum.find_index(intervals, fn {lower, upper} -> lower <= random && upper > random end) -      CommonAPI.post(Enum.random(users), %{"status" => "a post with the tag #tag_#{i}"}) +      CommonAPI.post(Enum.random(users), %{status: "a post with the tag #tag_#{i}"})      end)    end -  defp generate_long_thread(visibility, user, friends, non_friends, _opts) do +  defp generate_long_thread(visibility, users, _opts) do      group =        if visibility == "public", -        do: "friends", -        else: "user" +        do: :friends_local, +        else: :user      tasks = get_reply_tasks(visibility, group) |> Stream.cycle() |> Enum.take(50)      {:ok, activity} = -      CommonAPI.post(user, %{ -        "status" => "Start of #{visibility} long thread", -        "visibility" => visibility +      CommonAPI.post(users[:user], %{ +        status: "Start of #{visibility} long thread", +        visibility: visibility        })      Agent.update(:benchmark_state, fn state -> @@ -150,31 +154,28 @@ defmodule Pleroma.LoadTesting.Activities do        Map.put(state, key, activity)      end) -    acc = {activity.id, ["@" <> user.nickname, "reply to long thread"]} -    insert_replies_for_long_thread(tasks, visibility, user, friends, non_friends, acc) +    acc = {activity.id, ["@" <> users[:user].nickname, "reply to long thread"]} +    insert_replies_for_long_thread(tasks, visibility, users, acc)      IO.puts("Generating #{visibility} long thread ended\n")    end -  defp insert_replies_for_long_thread(tasks, visibility, user, friends, non_friends, acc) do +  defp insert_replies_for_long_thread(tasks, visibility, users, acc) do      Enum.reduce(tasks, acc, fn -      "friend", {id, data} -> -        friend = Enum.random(friends) -        insert_reply(friend, List.delete(data, "@" <> friend.nickname), id, visibility) - -      "non_friend", {id, data} -> -        non_friend = Enum.random(non_friends) -        insert_reply(non_friend, List.delete(data, "@" <> non_friend.nickname), id, visibility) - -      "user", {id, data} -> +      :user, {id, data} -> +        user = users[:user]          insert_reply(user, List.delete(data, "@" <> user.nickname), id, visibility) + +      group, {id, data} -> +        replier = Enum.random(users[group]) +        insert_reply(replier, List.delete(data, "@" <> replier.nickname), id, visibility)      end)    end -  defp generate_activities(user, friends, non_friends, task_data, opts) do +  defp generate_activities(users, task_data, opts) do      Task.async_stream(        task_data,        fn {visibility, type, group} -> -        insert_activity(type, visibility, group, user, friends, non_friends, opts) +        insert_activity(type, visibility, group, users, opts)        end,        max_concurrency: @max_concurrency,        timeout: 30_000 @@ -182,67 +183,104 @@ defmodule Pleroma.LoadTesting.Activities do      |> Stream.run()    end -  defp insert_activity("simple", visibility, group, user, friends, non_friends, _opts) do -    {:ok, _activity} = +  defp insert_local_activity(visibility, group, users, status) do +    {:ok, _} =        group -      |> get_actor(user, friends, non_friends) -      |> CommonAPI.post(%{"status" => "Simple status", "visibility" => visibility}) +      |> get_actor(users) +      |> CommonAPI.post(%{status: status, visibility: visibility})    end -  defp insert_activity("emoji", visibility, group, user, friends, non_friends, _opts) do -    {:ok, _activity} = -      group -      |> get_actor(user, friends, non_friends) -      |> CommonAPI.post(%{ -        "status" => "Simple status with emoji :firefox:", -        "visibility" => visibility -      }) +  defp insert_remote_activity(visibility, group, users, status) do +    actor = get_actor(group, users) +    {act_data, obj_data} = prepare_activity_data(actor, visibility, users[:user]) +    {activity_data, object_data} = other_data(actor, status) + +    activity_data +    |> Map.merge(act_data) +    |> Map.put("object", Map.merge(object_data, obj_data)) +    |> Pleroma.Web.ActivityPub.ActivityPub.insert(false)    end -  defp insert_activity("mentions", visibility, group, user, friends, non_friends, _opts) do +  defp user_mentions(users) do      user_mentions = -      get_random_mentions(friends, Enum.random(0..3)) ++ -        get_random_mentions(non_friends, Enum.random(0..3)) +      Enum.reduce( +        @groups, +        [], +        fn group, acc -> +          acc ++ get_random_mentions(users[group], Enum.random(0..2)) +        end +      ) -    user_mentions = -      if Enum.random([true, false]), -        do: ["@" <> user.nickname | user_mentions], -        else: user_mentions +    if Enum.random([true, false]), +      do: ["@" <> users[:user].nickname | user_mentions], +      else: user_mentions +  end -    {:ok, _activity} = -      group -      |> get_actor(user, friends, non_friends) -      |> CommonAPI.post(%{ -        "status" => Enum.join(user_mentions, ", ") <> " simple status with mentions", -        "visibility" => visibility -      }) +  defp hell_thread_mentions(users) do +    with {:ok, nil} <- Cachex.get(:user_cache, "hell_thread_mentions") do +      cached = +        @groups +        |> Enum.reduce([users[:user]], fn group, acc -> +          acc ++ Enum.take(users[group], 5) +        end) +        |> Enum.map(&"@#{&1.nickname}") +        |> Enum.join(", ") + +      Cachex.put(:user_cache, "hell_thread_mentions", cached) +      cached +    else +      {:ok, cached} -> cached +    end    end -  defp insert_activity("hell_thread", visibility, group, user, friends, non_friends, _opts) do -    mentions = -      with {:ok, nil} <- Cachex.get(:user_cache, "hell_thread_mentions") do -        cached = -          ([user | Enum.take(friends, 10)] ++ Enum.take(non_friends, 10)) -          |> Enum.map(&"@#{&1.nickname}") -          |> Enum.join(", ") +  defp insert_activity(:simple, visibility, group, users, _opts) +       when group in @remote_groups do +    insert_remote_activity(visibility, group, users, "Remote status") +  end -        Cachex.put(:user_cache, "hell_thread_mentions", cached) -        cached -      else -        {:ok, cached} -> cached -      end +  defp insert_activity(:simple, visibility, group, users, _opts) do +    insert_local_activity(visibility, group, users, "Simple status") +  end -    {:ok, _activity} = -      group -      |> get_actor(user, friends, non_friends) -      |> CommonAPI.post(%{ -        "status" => mentions <> " hell thread status", -        "visibility" => visibility -      }) +  defp insert_activity(:emoji, visibility, group, users, _opts) +       when group in @remote_groups do +    insert_remote_activity(visibility, group, users, "Remote status with emoji :firefox:") +  end + +  defp insert_activity(:emoji, visibility, group, users, _opts) do +    insert_local_activity(visibility, group, users, "Simple status with emoji :firefox:") +  end + +  defp insert_activity(:mentions, visibility, group, users, _opts) +       when group in @remote_groups do +    mentions = user_mentions(users) + +    status = Enum.join(mentions, ", ") <> " remote status with mentions" + +    insert_remote_activity(visibility, group, users, status) +  end + +  defp insert_activity(:mentions, visibility, group, users, _opts) do +    mentions = user_mentions(users) + +    status = Enum.join(mentions, ", ") <> " simple status with mentions" +    insert_remote_activity(visibility, group, users, status) +  end + +  defp insert_activity(:hell_thread, visibility, group, users, _) +       when group in @remote_groups do +    mentions = hell_thread_mentions(users) +    insert_remote_activity(visibility, group, users, mentions <> " remote hell thread status")    end -  defp insert_activity("attachment", visibility, group, user, friends, non_friends, _opts) do -    actor = get_actor(group, user, friends, non_friends) +  defp insert_activity(:hell_thread, visibility, group, users, _opts) do +    mentions = hell_thread_mentions(users) + +    insert_local_activity(visibility, group, users, mentions <> " hell thread status") +  end + +  defp insert_activity(:attachment, visibility, group, users, _opts) do +    actor = get_actor(group, users)      obj_data = %{        "actor" => actor.ap_id, @@ -262,118 +300,94 @@ defmodule Pleroma.LoadTesting.Activities do      {:ok, _activity} =        CommonAPI.post(actor, %{ -        "status" => "Post with attachment", -        "visibility" => visibility, -        "media_ids" => [object.id] +        status: "Post with attachment", +        visibility: visibility, +        media_ids: [object.id]        })    end -  defp insert_activity("tag", visibility, group, user, friends, non_friends, _opts) do -    {:ok, _activity} = -      group -      |> get_actor(user, friends, non_friends) -      |> CommonAPI.post(%{"status" => "Status with #tag", "visibility" => visibility}) +  defp insert_activity(:tag, visibility, group, users, _opts) do +    insert_local_activity(visibility, group, users, "Status with #tag")    end -  defp insert_activity("like", visibility, group, user, friends, non_friends, opts) do -    actor = get_actor(group, user, friends, non_friends) +  defp insert_activity(:like, visibility, group, users, opts) do +    actor = get_actor(group, users)      with activity_id when not is_nil(activity_id) <- get_random_create_activity_id(),           {:ok, _activity} <- CommonAPI.favorite(actor, activity_id) do        :ok      else        {:error, _} -> -        insert_activity("like", visibility, group, user, friends, non_friends, opts) +        insert_activity(:like, visibility, group, users, opts)        nil ->          Process.sleep(15) -        insert_activity("like", visibility, group, user, friends, non_friends, opts) +        insert_activity(:like, visibility, group, users, opts)      end    end -  defp insert_activity("reblog", visibility, group, user, friends, non_friends, opts) do -    actor = get_actor(group, user, friends, non_friends) +  defp insert_activity(:reblog, visibility, group, users, opts) do +    actor = get_actor(group, users)      with activity_id when not is_nil(activity_id) <- get_random_create_activity_id(), -         {:ok, _activity, _object} <- CommonAPI.repeat(activity_id, actor) do +         {:ok, _activity} <- CommonAPI.repeat(activity_id, actor) do        :ok      else        {:error, _} -> -        insert_activity("reblog", visibility, group, user, friends, non_friends, opts) +        insert_activity(:reblog, visibility, group, users, opts)        nil ->          Process.sleep(15) -        insert_activity("reblog", visibility, group, user, friends, non_friends, opts) +        insert_activity(:reblog, visibility, group, users, opts)      end    end -  defp insert_activity("simple_thread", visibility, group, user, friends, non_friends, _opts) -       when visibility in ["public", "unlisted", "private"] do -    actor = get_actor(group, user, friends, non_friends) -    tasks = get_reply_tasks(visibility, group) - -    {:ok, activity} = -      CommonAPI.post(user, %{"status" => "Simple status", "visibility" => visibility}) - -    acc = {activity.id, ["@" <> actor.nickname, "reply to status"]} -    insert_replies(tasks, visibility, user, friends, non_friends, acc) -  end - -  defp insert_activity("simple_thread", "direct", group, user, friends, non_friends, _opts) do -    actor = get_actor(group, user, friends, non_friends) +  defp insert_activity(:simple_thread, "direct", group, users, _opts) do +    actor = get_actor(group, users)      tasks = get_reply_tasks("direct", group)      list =        case group do -        "non_friends" -> -          Enum.take(non_friends, 3) +        :user -> +          group = Enum.random(@friends_groups) +          Enum.take(users[group], 3)          _ -> -          Enum.take(friends, 3) +          Enum.take(users[group], 3)        end      data = Enum.map(list, &("@" <> &1.nickname))      {:ok, activity} =        CommonAPI.post(actor, %{ -        "status" => Enum.join(data, ", ") <> "simple status", -        "visibility" => "direct" +        status: Enum.join(data, ", ") <> "simple status", +        visibility: "direct"        }) -    acc = {activity.id, ["@" <> user.nickname | data] ++ ["reply to status"]} -    insert_direct_replies(tasks, user, list, acc) +    acc = {activity.id, ["@" <> users[:user].nickname | data] ++ ["reply to status"]} +    insert_direct_replies(tasks, users[:user], list, acc)    end -  defp insert_activity("remote", _, "user", _, _, _, _), do: :ok - -  defp insert_activity("remote", visibility, group, user, _friends, _non_friends, opts) do -    remote_friends = -      Users.get_users(user, limit: opts[:friends_used], local: :external, friends?: true) - -    remote_non_friends = -      Users.get_users(user, limit: opts[:non_friends_used], local: :external, friends?: false) - -    actor = get_actor(group, user, remote_friends, remote_non_friends) +  defp insert_activity(:simple_thread, visibility, group, users, _opts) do +    actor = get_actor(group, users) +    tasks = get_reply_tasks(visibility, group) -    {act_data, obj_data} = prepare_activity_data(actor, visibility, user) -    {activity_data, object_data} = other_data(actor) +    {:ok, activity} = +      CommonAPI.post(users[:user], %{status: "Simple status", visibility: visibility}) -    activity_data -    |> Map.merge(act_data) -    |> Map.put("object", Map.merge(object_data, obj_data)) -    |> Pleroma.Web.ActivityPub.ActivityPub.insert(false) +    acc = {activity.id, ["@" <> actor.nickname, "reply to status"]} +    insert_replies(tasks, visibility, users, acc)    end -  defp get_actor("user", user, _friends, _non_friends), do: user -  defp get_actor("friends", _user, friends, _non_friends), do: Enum.random(friends) -  defp get_actor("non_friends", _user, _friends, non_friends), do: Enum.random(non_friends) +  defp get_actor(:user, %{user: user}), do: user +  defp get_actor(group, users), do: Enum.random(users[group]) -  defp other_data(actor) do +  defp other_data(actor, content) do      %{host: host} = URI.parse(actor.ap_id)      datetime = DateTime.utc_now() -    context_id = "http://#{host}:4000/contexts/#{UUID.generate()}" -    activity_id = "http://#{host}:4000/activities/#{UUID.generate()}" -    object_id = "http://#{host}:4000/objects/#{UUID.generate()}" +    context_id = "https://#{host}/contexts/#{UUID.generate()}" +    activity_id = "https://#{host}/activities/#{UUID.generate()}" +    object_id = "https://#{host}/objects/#{UUID.generate()}"      activity_data = %{        "actor" => actor.ap_id, @@ -390,7 +404,7 @@ defmodule Pleroma.LoadTesting.Activities do        "attributedTo" => actor.ap_id,        "bcc" => [],        "bto" => [], -      "content" => "Remote post", +      "content" => content,        "context" => context_id,        "conversation" => context_id,        "emoji" => %{}, @@ -476,60 +490,74 @@ defmodule Pleroma.LoadTesting.Activities do      {act_data, obj_data}    end -  defp get_reply_tasks("public", "user"), do: ~w(friend non_friend user) -  defp get_reply_tasks("public", "friends"), do: ~w(non_friend user friend) -  defp get_reply_tasks("public", "non_friends"), do: ~w(user friend non_friend) +  defp get_reply_tasks("public", :user) do +    [:friends_local, :friends_remote, :non_friends_local, :non_friends_remote, :user] +  end + +  defp get_reply_tasks("public", group) when group in @friends_groups do +    [:non_friends_local, :non_friends_remote, :user, :friends_local, :friends_remote] +  end -  defp get_reply_tasks(visibility, "user") when visibility in ["unlisted", "private"], -    do: ~w(friend user friend) +  defp get_reply_tasks("public", group) when group in @non_friends_groups do +    [:user, :friends_local, :friends_remote, :non_friends_local, :non_friends_remote] +  end -  defp get_reply_tasks(visibility, "friends") when visibility in ["unlisted", "private"], -    do: ~w(user friend user) +  defp get_reply_tasks(visibility, :user) when visibility in ["unlisted", "private"] do +    [:friends_local, :friends_remote, :user, :friends_local, :friends_remote] +  end -  defp get_reply_tasks(visibility, "non_friends") when visibility in ["unlisted", "private"], -    do: [] +  defp get_reply_tasks(visibility, group) +       when visibility in ["unlisted", "private"] and group in @friends_groups do +    [:user, :friends_remote, :friends_local, :user] +  end -  defp get_reply_tasks("direct", "user"), do: ~w(friend user friend) -  defp get_reply_tasks("direct", "friends"), do: ~w(user friend user) -  defp get_reply_tasks("direct", "non_friends"), do: ~w(user non_friend user) +  defp get_reply_tasks(visibility, group) +       when visibility in ["unlisted", "private"] and +              group in @non_friends_groups, +       do: [] -  defp insert_replies(tasks, visibility, user, friends, non_friends, acc) do -    Enum.reduce(tasks, acc, fn -      "friend", {id, data} -> -        friend = Enum.random(friends) -        insert_reply(friend, data, id, visibility) +  defp get_reply_tasks("direct", :user), do: [:friends_local, :user, :friends_remote] -      "non_friend", {id, data} -> -        non_friend = Enum.random(non_friends) -        insert_reply(non_friend, data, id, visibility) +  defp get_reply_tasks("direct", group) when group in @friends_groups, +    do: [:user, group, :user] -      "user", {id, data} -> -        insert_reply(user, data, id, visibility) +  defp get_reply_tasks("direct", group) when group in @non_friends_groups do +    [:user, :non_friends_remote, :user, :non_friends_local] +  end + +  defp insert_replies(tasks, visibility, users, acc) do +    Enum.reduce(tasks, acc, fn +      :user, {id, data} -> +        insert_reply(users[:user], data, id, visibility) + +      group, {id, data} -> +        replier = Enum.random(users[group]) +        insert_reply(replier, data, id, visibility)      end)    end    defp insert_direct_replies(tasks, user, list, acc) do      Enum.reduce(tasks, acc, fn -      group, {id, data} when group in ["friend", "non_friend"] -> +      :user, {id, data} -> +        {reply_id, _} = insert_reply(user, List.delete(data, "@" <> user.nickname), id, "direct") +        {reply_id, data} + +      _, {id, data} ->          actor = Enum.random(list)          {reply_id, _} =            insert_reply(actor, List.delete(data, "@" <> actor.nickname), id, "direct")          {reply_id, data} - -      "user", {id, data} -> -        {reply_id, _} = insert_reply(user, List.delete(data, "@" <> user.nickname), id, "direct") -        {reply_id, data}      end)    end    defp insert_reply(actor, data, activity_id, visibility) do      {:ok, reply} =        CommonAPI.post(actor, %{ -        "status" => Enum.join(data, ", "), -        "visibility" => visibility, -        "in_reply_to_status_id" => activity_id +        status: Enum.join(data, ", "), +        visibility: visibility, +        in_reply_to_status_id: activity_id        })      {reply.id, ["@" <> actor.nickname | data]} diff --git a/benchmarks/load_testing/fetcher.ex b/benchmarks/load_testing/fetcher.ex index 12c30f6f5..15fd06c3d 100644 --- a/benchmarks/load_testing/fetcher.ex +++ b/benchmarks/load_testing/fetcher.ex @@ -36,6 +36,7 @@ defmodule Pleroma.LoadTesting.Fetcher do      fetch_home_timeline(user)      fetch_direct_timeline(user)      fetch_public_timeline(user) +    fetch_public_timeline(user, :with_blocks)      fetch_public_timeline(user, :local)      fetch_public_timeline(user, :tag)      fetch_notifications(user) @@ -51,12 +52,12 @@ defmodule Pleroma.LoadTesting.Fetcher do    defp opts_for_home_timeline(user) do      %{ -      "blocking_user" => user, -      "count" => "20", -      "muting_user" => user, -      "type" => ["Create", "Announce"], -      "user" => user, -      "with_muted" => "true" +      blocking_user: user, +      count: "20", +      muting_user: user, +      type: ["Create", "Announce"], +      user: user, +      with_muted: true      }    end @@ -69,17 +70,17 @@ defmodule Pleroma.LoadTesting.Fetcher do        ActivityPub.fetch_activities(recipients, opts) |> Enum.reverse() |> List.last()      second_page_last = -      ActivityPub.fetch_activities(recipients, Map.put(opts, "max_id", first_page_last.id)) +      ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, first_page_last.id))        |> Enum.reverse()        |> List.last()      third_page_last = -      ActivityPub.fetch_activities(recipients, Map.put(opts, "max_id", second_page_last.id)) +      ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, second_page_last.id))        |> Enum.reverse()        |> List.last()      forth_page_last = -      ActivityPub.fetch_activities(recipients, Map.put(opts, "max_id", third_page_last.id)) +      ActivityPub.fetch_activities(recipients, Map.put(opts, :max_id, third_page_last.id))        |> Enum.reverse()        |> List.last() @@ -89,19 +90,19 @@ defmodule Pleroma.LoadTesting.Fetcher do        },        inputs: %{          "1 page" => opts, -        "2 page" => Map.put(opts, "max_id", first_page_last.id), -        "3 page" => Map.put(opts, "max_id", second_page_last.id), -        "4 page" => Map.put(opts, "max_id", third_page_last.id), -        "5 page" => Map.put(opts, "max_id", forth_page_last.id), -        "1 page only media" => Map.put(opts, "only_media", "true"), +        "2 page" => Map.put(opts, :max_id, first_page_last.id), +        "3 page" => Map.put(opts, :max_id, second_page_last.id), +        "4 page" => Map.put(opts, :max_id, third_page_last.id), +        "5 page" => Map.put(opts, :max_id, forth_page_last.id), +        "1 page only media" => Map.put(opts, :only_media, true),          "2 page only media" => -          Map.put(opts, "max_id", first_page_last.id) |> Map.put("only_media", "true"), +          Map.put(opts, :max_id, first_page_last.id) |> Map.put(:only_media, true),          "3 page only media" => -          Map.put(opts, "max_id", second_page_last.id) |> Map.put("only_media", "true"), +          Map.put(opts, :max_id, second_page_last.id) |> Map.put(:only_media, true),          "4 page only media" => -          Map.put(opts, "max_id", third_page_last.id) |> Map.put("only_media", "true"), +          Map.put(opts, :max_id, third_page_last.id) |> Map.put(:only_media, true),          "5 page only media" => -          Map.put(opts, "max_id", forth_page_last.id) |> Map.put("only_media", "true") +          Map.put(opts, :max_id, forth_page_last.id) |> Map.put(:only_media, true)        },        formatters: formatters()      ) @@ -109,12 +110,12 @@ defmodule Pleroma.LoadTesting.Fetcher do    defp opts_for_direct_timeline(user) do      %{ -      :visibility => "direct", -      "blocking_user" => user, -      "count" => "20", -      "type" => "Create", -      "user" => user, -      "with_muted" => "true" +      visibility: "direct", +      blocking_user: user, +      count: "20", +      type: "Create", +      user: user, +      with_muted: true      }    end @@ -129,7 +130,7 @@ defmodule Pleroma.LoadTesting.Fetcher do        |> Pagination.fetch_paginated(opts)        |> List.last() -    opts2 = Map.put(opts, "max_id", first_page_last.id) +    opts2 = Map.put(opts, :max_id, first_page_last.id)      second_page_last =        recipients @@ -137,7 +138,7 @@ defmodule Pleroma.LoadTesting.Fetcher do        |> Pagination.fetch_paginated(opts2)        |> List.last() -    opts3 = Map.put(opts, "max_id", second_page_last.id) +    opts3 = Map.put(opts, :max_id, second_page_last.id)      third_page_last =        recipients @@ -145,7 +146,7 @@ defmodule Pleroma.LoadTesting.Fetcher do        |> Pagination.fetch_paginated(opts3)        |> List.last() -    opts4 = Map.put(opts, "max_id", third_page_last.id) +    opts4 = Map.put(opts, :max_id, third_page_last.id)      forth_page_last =        recipients @@ -164,7 +165,7 @@ defmodule Pleroma.LoadTesting.Fetcher do          "2 page" => opts2,          "3 page" => opts3,          "4 page" => opts4, -        "5 page" => Map.put(opts4, "max_id", forth_page_last.id) +        "5 page" => Map.put(opts4, :max_id, forth_page_last.id)        },        formatters: formatters()      ) @@ -172,34 +173,34 @@ defmodule Pleroma.LoadTesting.Fetcher do    defp opts_for_public_timeline(user) do      %{ -      "type" => ["Create", "Announce"], -      "local_only" => false, -      "blocking_user" => user, -      "muting_user" => user +      type: ["Create", "Announce"], +      local_only: false, +      blocking_user: user, +      muting_user: user      }    end    defp opts_for_public_timeline(user, :local) do      %{ -      "type" => ["Create", "Announce"], -      "local_only" => true, -      "blocking_user" => user, -      "muting_user" => user +      type: ["Create", "Announce"], +      local_only: true, +      blocking_user: user, +      muting_user: user      }    end    defp opts_for_public_timeline(user, :tag) do      %{ -      "blocking_user" => user, -      "count" => "20", -      "local_only" => nil, -      "muting_user" => user, -      "tag" => ["tag"], -      "tag_all" => [], -      "tag_reject" => [], -      "type" => "Create", -      "user" => user, -      "with_muted" => "true" +      blocking_user: user, +      count: "20", +      local_only: nil, +      muting_user: user, +      tag: ["tag"], +      tag_all: [], +      tag_reject: [], +      type: "Create", +      user: user, +      with_muted: true      }    end @@ -222,24 +223,72 @@ defmodule Pleroma.LoadTesting.Fetcher do    end    defp fetch_public_timeline(user, :only_media) do -    opts = opts_for_public_timeline(user) |> Map.put("only_media", "true") +    opts = opts_for_public_timeline(user) |> Map.put(:only_media, true)      fetch_public_timeline(opts, "public timeline only media")    end +  defp fetch_public_timeline(user, :with_blocks) do +    opts = opts_for_public_timeline(user) + +    remote_non_friends = Agent.get(:non_friends_remote, & &1) + +    Benchee.run(%{ +      "public timeline without blocks" => fn -> +        ActivityPub.fetch_public_activities(opts) +      end +    }) + +    Enum.each(remote_non_friends, fn non_friend -> +      {:ok, _} = User.block(user, non_friend) +    end) + +    user = User.get_by_id(user.id) + +    opts = Map.put(opts, :blocking_user, user) + +    Benchee.run(%{ +      "public timeline with user block" => fn -> +        ActivityPub.fetch_public_activities(opts) +      end +    }) + +    domains = +      Enum.reduce(remote_non_friends, [], fn non_friend, domains -> +        {:ok, _user} = User.unblock(user, non_friend) +        %{host: host} = URI.parse(non_friend.ap_id) +        [host | domains] +      end) + +    domains = Enum.uniq(domains) + +    Enum.each(domains, fn domain -> +      {:ok, _} = User.block_domain(user, domain) +    end) + +    user = User.get_by_id(user.id) +    opts = Map.put(opts, :blocking_user, user) + +    Benchee.run(%{ +      "public timeline with domain block" => fn -> +        ActivityPub.fetch_public_activities(opts) +      end +    }) +  end +    defp fetch_public_timeline(opts, title) when is_binary(title) do      first_page_last = ActivityPub.fetch_public_activities(opts) |> List.last()      second_page_last = -      ActivityPub.fetch_public_activities(Map.put(opts, "max_id", first_page_last.id)) +      ActivityPub.fetch_public_activities(Map.put(opts, :max_id, first_page_last.id))        |> List.last()      third_page_last = -      ActivityPub.fetch_public_activities(Map.put(opts, "max_id", second_page_last.id)) +      ActivityPub.fetch_public_activities(Map.put(opts, :max_id, second_page_last.id))        |> List.last()      forth_page_last = -      ActivityPub.fetch_public_activities(Map.put(opts, "max_id", third_page_last.id)) +      ActivityPub.fetch_public_activities(Map.put(opts, :max_id, third_page_last.id))        |> List.last()      Benchee.run( @@ -250,17 +299,17 @@ defmodule Pleroma.LoadTesting.Fetcher do        },        inputs: %{          "1 page" => opts, -        "2 page" => Map.put(opts, "max_id", first_page_last.id), -        "3 page" => Map.put(opts, "max_id", second_page_last.id), -        "4 page" => Map.put(opts, "max_id", third_page_last.id), -        "5 page" => Map.put(opts, "max_id", forth_page_last.id) +        "2 page" => Map.put(opts, :max_id, first_page_last.id), +        "3 page" => Map.put(opts, :max_id, second_page_last.id), +        "4 page" => Map.put(opts, :max_id, third_page_last.id), +        "5 page" => Map.put(opts, :max_id, forth_page_last.id)        },        formatters: formatters()      )    end    defp opts_for_notifications do -    %{"count" => "20", "with_muted" => "true"} +    %{count: "20", with_muted: true}    end    defp fetch_notifications(user) do @@ -269,15 +318,15 @@ defmodule Pleroma.LoadTesting.Fetcher do      first_page_last = MastodonAPI.get_notifications(user, opts) |> List.last()      second_page_last = -      MastodonAPI.get_notifications(user, Map.put(opts, "max_id", first_page_last.id)) +      MastodonAPI.get_notifications(user, Map.put(opts, :max_id, first_page_last.id))        |> List.last()      third_page_last = -      MastodonAPI.get_notifications(user, Map.put(opts, "max_id", second_page_last.id)) +      MastodonAPI.get_notifications(user, Map.put(opts, :max_id, second_page_last.id))        |> List.last()      forth_page_last = -      MastodonAPI.get_notifications(user, Map.put(opts, "max_id", third_page_last.id)) +      MastodonAPI.get_notifications(user, Map.put(opts, :max_id, third_page_last.id))        |> List.last()      Benchee.run( @@ -288,10 +337,10 @@ defmodule Pleroma.LoadTesting.Fetcher do        },        inputs: %{          "1 page" => opts, -        "2 page" => Map.put(opts, "max_id", first_page_last.id), -        "3 page" => Map.put(opts, "max_id", second_page_last.id), -        "4 page" => Map.put(opts, "max_id", third_page_last.id), -        "5 page" => Map.put(opts, "max_id", forth_page_last.id) +        "2 page" => Map.put(opts, :max_id, first_page_last.id), +        "3 page" => Map.put(opts, :max_id, second_page_last.id), +        "4 page" => Map.put(opts, :max_id, third_page_last.id), +        "5 page" => Map.put(opts, :max_id, forth_page_last.id)        },        formatters: formatters()      ) @@ -301,13 +350,13 @@ defmodule Pleroma.LoadTesting.Fetcher do      first_page_last = ActivityPub.fetch_favourites(user) |> List.last()      second_page_last = -      ActivityPub.fetch_favourites(user, %{"max_id" => first_page_last.id}) |> List.last() +      ActivityPub.fetch_favourites(user, %{:max_id => first_page_last.id}) |> List.last()      third_page_last = -      ActivityPub.fetch_favourites(user, %{"max_id" => second_page_last.id}) |> List.last() +      ActivityPub.fetch_favourites(user, %{:max_id => second_page_last.id}) |> List.last()      forth_page_last = -      ActivityPub.fetch_favourites(user, %{"max_id" => third_page_last.id}) |> List.last() +      ActivityPub.fetch_favourites(user, %{:max_id => third_page_last.id}) |> List.last()      Benchee.run(        %{ @@ -317,10 +366,10 @@ defmodule Pleroma.LoadTesting.Fetcher do        },        inputs: %{          "1 page" => %{}, -        "2 page" => %{"max_id" => first_page_last.id}, -        "3 page" => %{"max_id" => second_page_last.id}, -        "4 page" => %{"max_id" => third_page_last.id}, -        "5 page" => %{"max_id" => forth_page_last.id} +        "2 page" => %{:max_id => first_page_last.id}, +        "3 page" => %{:max_id => second_page_last.id}, +        "4 page" => %{:max_id => third_page_last.id}, +        "5 page" => %{:max_id => forth_page_last.id}        },        formatters: formatters()      ) @@ -328,8 +377,8 @@ defmodule Pleroma.LoadTesting.Fetcher do    defp opts_for_long_thread(user) do      %{ -      "blocking_user" => user, -      "user" => user +      blocking_user: user, +      user: user      }    end @@ -339,9 +388,9 @@ defmodule Pleroma.LoadTesting.Fetcher do      opts = opts_for_long_thread(user) -    private_input = {private.data["context"], Map.put(opts, "exclude_id", private.id)} +    private_input = {private.data["context"], Map.put(opts, :exclude_id, private.id)} -    public_input = {public.data["context"], Map.put(opts, "exclude_id", public.id)} +    public_input = {public.data["context"], Map.put(opts, :exclude_id, public.id)}      Benchee.run(        %{ @@ -387,56 +436,47 @@ defmodule Pleroma.LoadTesting.Fetcher do      favourites = ActivityPub.fetch_favourites(user) -    output_relationships = -      !!Pleroma.Config.get([:extensions, :output_relationships_in_statuses_by_default]) -      Benchee.run(        %{          "Rendering home timeline" => fn ->            StatusView.render("index.json", %{              activities: home_activities,              for: user, -            as: :activity, -            skip_relationships: !output_relationships +            as: :activity            })          end,          "Rendering direct timeline" => fn ->            StatusView.render("index.json", %{              activities: direct_activities,              for: user, -            as: :activity, -            skip_relationships: !output_relationships +            as: :activity            })          end,          "Rendering public timeline" => fn ->            StatusView.render("index.json", %{              activities: public_activities,              for: user, -            as: :activity, -            skip_relationships: !output_relationships +            as: :activity            })          end,          "Rendering tag timeline" => fn ->            StatusView.render("index.json", %{              activities: tag_activities,              for: user, -            as: :activity, -            skip_relationships: !output_relationships +            as: :activity            })          end,          "Rendering notifications" => fn ->            Pleroma.Web.MastodonAPI.NotificationView.render("index.json", %{              notifications: notifications, -            for: user, -            skip_relationships: !output_relationships +            for: user            })          end,          "Rendering favourites timeline" => fn ->            StatusView.render("index.json", %{              activities: favourites,              for: user, -            as: :activity, -            skip_relationships: !output_relationships +            as: :activity            })          end        }, @@ -470,13 +510,13 @@ defmodule Pleroma.LoadTesting.Fetcher do      public_context =        ActivityPub.fetch_activities_for_context(          public.data["context"], -        Map.put(fetch_opts, "exclude_id", public.id) +        Map.put(fetch_opts, :exclude_id, public.id)        )      private_context =        ActivityPub.fetch_activities_for_context(          private.data["context"], -        Map.put(fetch_opts, "exclude_id", private.id) +        Map.put(fetch_opts, :exclude_id, private.id)        )      Benchee.run( @@ -507,14 +547,14 @@ defmodule Pleroma.LoadTesting.Fetcher do          end,          "Public timeline with reply filtering - following" => fn ->            public_params -          |> Map.put("reply_visibility", "following") -          |> Map.put("reply_filtering_user", user) +          |> Map.put(:reply_visibility, "following") +          |> Map.put(:reply_filtering_user, user)            |> ActivityPub.fetch_public_activities()          end,          "Public timeline with reply filtering - self" => fn ->            public_params -          |> Map.put("reply_visibility", "self") -          |> Map.put("reply_filtering_user", user) +          |> Map.put(:reply_visibility, "self") +          |> Map.put(:reply_filtering_user, user)            |> ActivityPub.fetch_public_activities()          end        }, @@ -533,16 +573,16 @@ defmodule Pleroma.LoadTesting.Fetcher do          "Home timeline with reply filtering - following" => fn ->            private_params =              private_params -            |> Map.put("reply_filtering_user", user) -            |> Map.put("reply_visibility", "following") +            |> Map.put(:reply_filtering_user, user) +            |> Map.put(:reply_visibility, "following")            ActivityPub.fetch_activities(recipients, private_params)          end,          "Home timeline with reply filtering - self" => fn ->            private_params =              private_params -            |> Map.put("reply_filtering_user", user) -            |> Map.put("reply_visibility", "self") +            |> Map.put(:reply_filtering_user, user) +            |> Map.put(:reply_visibility, "self")            ActivityPub.fetch_activities(recipients, private_params)          end diff --git a/benchmarks/load_testing/users.ex b/benchmarks/load_testing/users.ex index e4d0b22ff..6cf3958c1 100644 --- a/benchmarks/load_testing/users.ex +++ b/benchmarks/load_testing/users.ex @@ -27,7 +27,7 @@ defmodule Pleroma.LoadTesting.Users do      make_friends(main_user, opts[:friends]) -    Repo.get(User, main_user.id) +    User.get_by_id(main_user.id)    end    def generate_users(max) do @@ -166,4 +166,24 @@ defmodule Pleroma.LoadTesting.Users do      )      |> Stream.run()    end + +  @spec prepare_users(User.t(), keyword()) :: map() +  def prepare_users(user, opts) do +    friends_limit = opts[:friends_used] +    non_friends_limit = opts[:non_friends_used] + +    %{ +      user: user, +      friends_local: fetch_users(user, friends_limit, :local, true), +      friends_remote: fetch_users(user, friends_limit, :external, true), +      non_friends_local: fetch_users(user, non_friends_limit, :local, false), +      non_friends_remote: fetch_users(user, non_friends_limit, :external, false) +    } +  end + +  defp fetch_users(user, limit, local, friends?) do +    user +    |> get_users(limit: limit, local: local, friends?: friends?) +    |> Enum.shuffle() +  end  end | 
