Skip to main content
This page follows the Scala Traffic Generator through a run: where it runs, how requests and replies flow, and what it records. Before the simulation starts, the platform places the clients and servers on the hosts and pairs them. In the simulation, each connection starts in the client start window, generates requests in On periods until the end of the recording window, and records the latency of every transaction completed in that window. Configuration lists the attributes this page refers to, and the overview summarizes the model.

Overview

Placement and pairing

Before the simulation starts, the platform decides how many hosts run the client and how many run the server, assigns the hosts, and pairs them. A host is a server node of the configuration’s topology. On these pages, “server” on its own means the Traffic Generator’s server component, not a host.

Host counts

Each component has a distribution ratio: prScalaTrafficGenerator for the client and prScalaTrafficServer for the server (Distribution ratios). The number of hosts that run each is:
If these counts add up to fewer than the hosts, each component whose share is still below its ratio gets one more host, in turn and starting with the client, until every host runs one component. A host therefore runs the client or the server, never both. The ratios of all the applications in a configuration share one budget, and they must add up to 1. A ratio of 0 makes the configuration invalid. When you add an application, the platform splits 1.0 evenly over every client and server entry of every application in the configuration, so the Scala Traffic Generator on its own gets 0.5 for the client and 0.5 for the server.

Pairing

Each client is paired with a server on another host:
  1. Each client in turn takes a server that no other client has yet, picked at random.
  2. Once every server has a client, each further client picks any server at random, so a server can serve several clients.
  3. If servers are left over because there are more servers than clients, each of them gets a client picked at random, so a client can have several servers.
Pairing is random and set by the global simulation parameter RandomSeed (default 18760): the same configuration with the same seed gives the same pairs. Each pair has its own connections (Connections).

Worked example: 16 hosts

Connections

The client’s NumConnections (default 8, from 1 to 8) sets the number of connections each pair has. Each of the N connections has its own client instance on the client’s host and its own server instance, listening on its own port, on the server’s host, and is one TCP connection between them. The connections are independent: each has its own start time, its own requests at the full RequestRate, its own burst cycle, and its own rows in the records. A client paired with several servers has NumConnections connections to each.

Run timeline

Six global simulation parameters set the run’s timeline. They are not attributes of this model: they sit in the configuration’s SimulationParameters and are changed with PATCH /api/v1/configurations/{config_id}/parameters (Change the global simulation parameters). Times are in seconds of simulation time.
The servers start listening at StartTime. Each connection starts at a time in the client start window that StartType sets (Start types), and generates requests until the end of the recording window. Only transactions whose replies complete in the recording window are recorded (How a run ends).

Start types

The client’s StartType sets when each connection starts, that is, when its client opens the TCP connection and generates its first request:

Worked example: the default timeline

The defaults are StartTime 0.001, ClientStartOffset 0.001, ClientStartInterval 0.001, WarmUp 0.002, RunTime 0.5, and CoolDown 0.001.
With the default StartType, uniform, each connection starts at its own random time between 0.002 s and 0.003 s. Transactions whose replies complete from 0.005 s to 0.505 s are recorded, no request is generated after 0.505 s, and the connections close at 0.506 s.

Transactions

On each connection, the client generates requests as a Poisson process: the gap before each next request is drawn from an exponential distribution with mean 1 / RequestRate seconds, 2 ms at the default 500 requests per second. The first request is generated as soon as the connection starts, while TCP is still opening the connection. Requests are generated whether or not the replies to earlier ones have arrived (an open loop), and only during On periods (Burst cycle). Each transaction goes through these steps:
  1. Request. The client draws a request size and a reply size (Request and reply sizes) and hands the request to TCP as one write of the request size. TCP sends a connection’s requests in the order they were generated, so a request waits behind the ones before it.
  2. Reply. Once the whole request has arrived, the server replies at once, with no processing time, with a reply of the size the client drew. It answers a connection’s requests in the order they were sent, so a reply waits behind the replies to earlier requests.
  3. Completion. The transaction completes when the last byte of the reply reaches the client.
Requests and replies carry only their drawn sizes as payload: the reply size reaches the server with the request without adding bytes to it.

Latency

A transaction’s latency runs from the moment the client generates the request to the arrival of the last byte of the reply at the client. It includes the time the request waits in TCP behind earlier requests, the transfers in both directions, the time the reply waits behind replies to earlier requests, and, for a connection’s first request, the TCP handshake.

Request and reply sizes

Each transaction draws its request size from RequestSizeDistribution, RequestSizeMin, RequestSizeMax, and AverageRequestSize, and its reply size from ReplySizeDistribution, ReplySizeMin, ReplySizeMax, and AverageReplySize. The same rules apply to both, where Min, Max, and Average are the matching attributes:
With normal, the spread is broad: the standard deviation is wider than the Min-to-Max range. Sizes are whole bytes.

Worked example: the default sizes

Both distributions default to normal.

Burst cycle

On each connection, requests come in On periods separated by Off periods:
  1. An On period starts with a request.
  2. Further requests follow at the drawn gaps until the gaps drawn since the period began add up to BurstOnCycleTime or more. The time the last gap points to starts the Off period instead of a request.
  3. The Off period lasts BurstOffCycleTime, with no new requests. Then the next On period starts.
Each connection’s cycle starts at the connection’s own start time. Transactions in flight continue through an Off period: requests already sent are answered, and their replies arrive and are recorded. With BurstOffCycleTime at 0, the default, the next On period starts at once, so requests arrive as one continuous Poisson process at RequestRate. With BurstOnCycleTime and BurstOffCycleTime converted to seconds:

Worked example: requests per On period

TCP

Each connection is a TCP connection with the platform’s default TCP settings: The application’s packets carry DSCP 0, so switches put them in traffic class 0.

How a run ends

At the end of the recording window, the clients stop generating requests and the servers stop sending replies. A transaction whose reply completes after the end of the recording window is not recorded. The connections close at the stop time, when the simulation ends.

Records

Records a simulation writes

With the defaults, the Scala Traffic Generator writes these records. Each file is named after the record, in the form {simulation}-{record}-{shard-index}.csv, as Simulation output files describes. When a simulation runs as several simulator processes, each process writes its own shard, covering the instances that process ran. tcp-stats is written only when turned on (tcp-stats). BeaconReportInterval is a global simulation parameter, not an attribute of this model: a double in seconds (default 0.001) in the configuration’s SimulationParameters.

perf

perf has one row for each transaction whose reply completes in the recording window, both ends of the window included, written by the client when the last byte of the reply arrives. The server writes no rows. The columns are:

Beacon

The beacon record writes running totals every BeaconReportInterval. The application adds to six of its columns:
  • tx_client: requests the clients have handed to TCP since the start of the run.
  • rx_client: replies the clients have received in full, that is, transactions completed, since the start of the run.
  • tx_server: replies the servers have sent since the start of the run.
  • rx_server: requests the servers have received in full since the start of the run.
  • rx_bytes_writer: bytes of the requests the servers have received in full during the recording window.
  • goodput_writer_MB_per_sec: the request bytes the servers receive per second, divided by the number of hosts that run a server, averaged over the report intervals of the recording window so far, in MB/s (1,000,000 bytes per second).
The application counts requests and replies in tx_client, rx_client, tx_server, and rx_server, not packets. Each shard counts the instances its simulator process ran. Simulation output files lists the record’s columns.

tcp-stats

tcp-stats is written when the client’s EnableTcpStats is true, its default, and the global simulation parameter EnableTcpStackReporting is true; that parameter’s default is false, so the record is off until you set it (Change the global simulation parameters). It has one row for each client connection every TcpStackReportInterval of simulation time (a global simulation parameter, default 0.1 s), starting one interval after the first connection starts. Its columns, by group:

Getting the records

GET /api/v1/simulations/{sim_id}/results lists a simulation’s result files, among them every record on this page; its type query parameter filters by file type, for example csv. GET /api/v1/simulations/{sim_id}/results/download-url, with the fileName query parameter set to a file’s name, returns a link to download that file. The Simulations API reference lists their parameters. GET /api/v1/simulations/{sim_id}/results/data with metric=perf also summarizes the perf files on the platform (Simulation output files). Set SIM_ID to the simulation’s ID and FILE_NAME to a name from the list: