Loader (loader v0.3.0)

Loader is a load-generating library that allows you to define arbitrary distributions of arbitrary work via mathematical functions and small structs.

These distributions, called LoadProfiles, can be paired up with a WorkSpec and executed to generate load, and gather statistics from a client's perspective.

usage

Usage

In order to use Loader you must start it and provide a :name, typically in a supervision tree:

children = [
  {Loader, name: MyLoader}
]

However you may want to use Loader in an iex session, or as part of a mix script via Mix.install/2, in which case you can also start Loader dynamically:

Loader.start_link(name: MyLoader)

example

Example

Let's assume there is some service at http://website.io/public/api, and we want to generate some simple, uniform load against that service.


alias Loader.{LoadProfile, WorkResponse, WorkSpec}

uniform_one_minute_profile =
  LoadProfile.new(%{
    target_running_time: 60,
    function: &LoadProfile.Curves.uniform(&1, 10) # y = 10
  })

service_call_spec = %WorkSpec{
  task: fn ->
    Finch.build(:get, "http://website.io/public/api", [])
    |> Finch.request(MyApp.Finch)
  end,
  is_success?: fn %WorkResponse{data: res} ->
    case res do
      {:ok, _any} -> true
      _any -> false
    end
  end
}

Loader.start_link(name: MyLoader)

Loader.execute({uniform_one_minute_profile, service_call_spec}, MyLoader)

The above example will generate a uniform 10 requests/ second against our imaginary service. We could also write additional load profiles, and run them concurrently to generate constructive interference!

linear_one_minute_profile =
  LoadProfile.new(%{
    target_running_time: 60,
    function: &LoadProfile.Curves.linear(&1, 1.5, 5) # y = 1.5x + 5
  })

sine_wave_one_minute_profile =
  LoadProfile.new(%{
    target_running_time: 60,
    function: fn x -> 5 * (:math.sin(x) + 1) end # y = 5 * (sin(x) + 1)
  })

[
  {uniform_one_minute_profile, service_call_spec},
  {linear_one_minute_profile, service_call_spec},
  {sine_wave_one_minute_profile, service_call_spec},
]
|> Loader.execute(MyLoader)

Visualized, this second example would produce load on the service as shown, where x is in seconds and y is requests/ second:

constructive interference load graph

telemetry

Telemetry

Loader emits the following telemetry events:

  • [:loader, :load_profile_execution, :start] - emitted when Loader.execute/2 is called.
  • [:loader, :load_profile_execution, :stop] - emitted when a LoadProfile has been fully emitted, regardless of the number of successes or failures of individual tasks
  • [:loader, :task, :start] - emitted when the :task callback from a Loader.WorkSpec is invoked
  • [:loader, :task, :stop] - emitted when the :task callback from a Loader.WorkSpec is invoked
  • [:loader, :task, :exception] - emitted if there is an uncaught exception while invoking the :task callback from a Loader.WorkSpec

See the documentation for the Loader.Telemetry module for more information.

ets

ETS

Note that Loader uses one ETS table per instance.

installation

Installation

The package can be installed by adding loader to your list of dependencies in mix.exs:

def deps do
  [
    {:loader, "~> 0.3.0"}
  ]
end

The docs can be found at https://hexdocs.pm/loader.

Link to this section Summary

Functions

Returns a specification to start this module under a supervisor.

Execute tasks defined by the work_spec, scheduled based on the load_profile. When provided with a list, all profiles will be executed concurrently.

Start an instance of Loader

Link to this section Functions

Link to this function

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

Link to this function

execute(profile_spec_pairs, instance_name)

Execute tasks defined by the work_spec, scheduled based on the load_profile. When provided with a list, all profiles will be executed concurrently.

See Loader.LoadProfile for more information on how to define a profile.

Link to this function

start_link(opts)

Start an instance of Loader

options

Options

  • :name - The name of your Loader instance. This field is required.