skip to content

Tabular Inputs

The feeder half: which built-in reads your records, where those files have to sit, and which strategy hands a row to each user. Interviewers ask because the default one ends the run.

on this pageshow

explore

questions

12

In a Gatling simulation, which built-in feeders read a character-separated file, and where must the file sit for csv("credentials.csv") to resolve?

level: juniorimportance: must knowfreq 70%

answer

  1. data comes from outside the simulation
  2. four delimited builders, plus JSON and sitemap
  3. classpath root, not a project path
  4. csv, ssv, tsv, separatedValues(path, separator)
  5. optional argument is quoteChar, default double quote

basics

~10 s

Gatling ships csv, tsv, ssv and separatedValues for delimited files, plus jsonFile, jsonUrl and sitemap. The path is resolved from your classpath root: src/main/resources or src/test/resources on the JVM, resources in the JavaScript SDK.

solid answer

~40 s

Four built-ins read character-separated files: `csv` (comma), `ssv` (semicolon), `tsv` (tab) and `separatedValues(path, separator)` for anything else. Each takes an optional `quoteChar` argument, defaulting to a double quote — second for `csv`, `ssv` and `tsv`, third for `separatedValues`, whose second argument is the separator itself; there is no `quotes` method. `jsonFile` reads a JSON array of objects, `jsonUrl` fetches one over HTTP, and `sitemap` reads a sitemap XML file but lives in the HTTP DSL rather than core. The argument is a **classpath** path, not a filesystem path: put the file under `src/main/resources`, `src/test/resources`, or `src/gatling/resources` under Gradle, and pass the path relative to that root, so `csv("data/credentials.csv")`. The JavaScript and TypeScript SDK uses a `resources` folder instead. An absolute filesystem path also works when data files ship separately from the simulation.

code

java · 10 lines
java
import io.gatling.javaapi.core.*;

import static io.gatling.javaapi.core.CoreDsl.*;

public class CredentialFeeders {
  FeederBuilder.FileBased<String> commas = csv("data/credentials.csv");
  FeederBuilder.FileBased<String> pipes = separatedValues("data/credentials.txt", '|');
  FeederBuilder.FileBased<String> singleQuoted = csv("data/credentials.csv", '\'');
  FeederBuilder.FileBased<String> compressed = csv("data/credentials.csv.gz").unzip();
}

go deeper

for a junior

Be ready to name the four delimited-file builders and say where the file goes. Reciting csv, ssv, tsv and separatedValues plus the classpath root covers most of what is asked at this level.

for a middle

Explain that the argument is a classpath path resolved when the builder is created, that the optional extra argument is quoteChar rather than the separator, and that sitemap comes from the HTTP DSL.

for a senior

Be able to justify a builder choice for a supplied data file, including when unzip and transform earn their place and what an absolute path buys you when the data ships separately from the artifact.

for a principal

Own the convention across the suite: whether feeder data lives inside the built artifact or beside the load generator, and what that settles about reproducibility, artifact size and how the file reaches every generator.

## What a feeder actually is A **feeder** is a stock of records that virtual users draw on, so that a thousand simulated logins do not all send the same username. The SDK exposes a `feed` method that can be placed wherever `exec` is placed. Every time a virtual user reaches that step it collects one record, and Gatling merges that record's keys into the user's Session as attributes, ready for `#{username}` style interpolation. A record is just a map of names to values; the names come from the source itself — a CSV header line, a JSON object's keys, a sitemap element's tags. ## The character-separated family Four builders read delimited files. They are the same RFC 4180 parser with a different separator baked in: | builder | separator | optional quote-char argument | |---|---|---| | `csv(path)` | comma | `quoteChar`, default `"` | | `ssv(path)` | semicolon | `quoteChar`, default `"` | | `tsv(path)` | tab | `quoteChar`, default `"` | | `separatedValues(path, separator)` | whatever you pass | `quoteChar`, default `"` (third argument, after the separator) | Two things trip people up. `ssv` is **semicolon**-separated, not space-separated. And that optional extra parameter is the **quote character**, not the separator — there is no `quotes` method, so `csv("x.csv", ';')` makes `;` the quote character and leaves the separator a comma. Only `separatedValues` takes a separator argument at all, because it has none baked in: there the separator is the mandatory second argument and `quoteChar` moves to third. The one documented deviation from RFC 4180 is that header fields are trimmed of wrapping whitespace. ## The other file-backed sources * `jsonFile(path)` reads a JSON document whose **root node must be an array**. Each object in that array becomes one record, and its keys become the attribute names. * `jsonUrl(url)` reads the same shape over HTTP instead of off the classpath. * `sitemap(path)` reads a sitemap XML file, turning each `<url>` element into a record carrying `loc`, and `lastmod`, `changefreq` and `priority` where the element has them. It lives in the **HTTP** DSL, not core — `io.gatling.javaapi.http.HttpDsl` for Java and Kotlin, `io.gatling.http.Predef._` for Scala, `@gatling.io/http` for JavaScript and TypeScript — so a simulation that imports only the core DSL will not see it. ## Where the file has to sit The string you pass is a **classpath** path, not a filesystem path. 1. On the JVM SDKs, put the file under `src/main/resources` or `src/test/resources`, or under `src/gatling/resources` when you build with Gradle. 2. In the JavaScript and TypeScript SDK, put it under `resources`. 3. Pass the path **relative to that root**. A file at `src/test/resources/data/credentials.csv` is declared as `csv("data/credentials.csv")`. The documented alternative is an **absolute** filesystem path, which is how you deploy data files separately from the packaged simulation and let them sit on the load generator's own disk. What is not accepted is a path that names your source tree, such as `src/main/resources/data/credentials.csv`: Gatling recognises that prefix and refuses it with a message telling you to drop it. ## What you can chain onto the builder The builder is immutable — every call returns a new one, so keep the value: * `unzip()` for a gzip or zip source, decompressed on the fly. * `transform(...)` to convert a value before the user sees it, because a delimited file yields only `String`s. Java and Kotlin take a `BiFunction<String, T, Object>` over key and value; Scala takes a `PartialFunction[(String, T), Any]` defined only for the keys you want changed. * `recordsCount()` for the number of records, and `readRecords()` for the records themselves. * `shard()`, which slices the data across load generators on Gatling Enterprise and is a no-op anywhere else. In Scala these parameterless calls are written without parentheses — `csv("x.csv").unzip`, not `unzip()` — which is the usual cross-SDK spelling difference rather than a different feature. ## What the record turns into Whatever the source, a record is a map and its keys become Session attributes for that one virtual user. That has two consequences worth stating out loud: * The attribute names are decided by the **data**, not by the simulation. Rename a CSV column and every `#{...}` placeholder that referred to it silently stops resolving. * Values from a delimited file are always `String`. A JSON feeder preserves the document's own types, so a numeric field arrives as a number without any `transform` at all. ## The worked example A login scenario backed by a 200,000-row credentials file is the ordinary case. The file goes to `src/test/resources/data/credentials.csv` with a header line reading `username,password`, the simulation declares `csv("data/credentials.csv")`, and the scenario interpolates `#{username}` and `#{password}` into the login request. Nothing about the row count changes the declaration: size only affects how Gatling loads the file at run start, not how you name it.

  • In Gatling, how do you read a file whose columns are separated by a pipe character?
    Use `separatedValues("data/credentials.txt", '|')`. `csv`, `ssv` and `tsv` are fixed-separator shorthands over exactly the same parser — comma, semicolon and tab. All four accept a further optional argument, `quoteChar`, when the file quotes fields with something other than a double quote.
  • A Gatling CSV feeder hands every column over as a String. How do you turn one column into an Int?
    Chain `transform`. In Java and Kotlin it takes a `BiFunction<String, T, Object>` over the key and the value; in Scala it takes a `PartialFunction[(String, T), Any]` you define only for the keys you want changed, leaving the rest untouched. The JavaScript SDK takes a two-argument function.
  • What does Gatling do with the header line of a CSV feeder file?
    The first line supplies the Session attribute names for every record, and Gatling trims wrapping whitespace from each header field. A `jsonFile` feeder has no header: its root node must be a JSON array, and each object's own keys become the attribute names.

saying these in an interview costs you the question

  • Reading ssv as space-separated values; it is semicolon-separated.
  • Passing src/main/resources/data.csv as the feeder path instead of data.csv.
  • Calling a quotes method to set the quote character; only quoteChar exists.
  • Assuming sitemap comes from the core DSL rather than the HTTP DSL.
open as a page

In Gatling, which four record-consumption strategies can you set on a feeder, and which one applies if you set none?

level: juniorimportance: must knowfreq 68%

basics

~20 s

Gatling feeders take exactly four strategies: queue, random, shuffle and circular. Queue is the default. Queue and shuffle hand out each record once and stop the run when the stock empties; random and circular reuse records and never run out.

open as a page

A Gatling simulation declares csv("src/main/resources/credentials.csv") and dies before a single virtual user starts, although the file is exactly there. Why?

level: middleimportance: must knowfreq 55%

basics

~10 s

Gatling resolves a feeder path against the classpath, not the project tree, and specifically refuses paths starting src/main/resources/, src/test/resources/ or src/gatling/resources/. Use credentials.csv. The check runs while the Simulation constructor evaluates csv().

open as a page

In a Gatling simulation whose scenario feeds from `csv("credentials.csv")` with no strategy method called on it, what happens when more virtual users reach that feed step than the file has rows?

level: middleimportance: must knowfreq 58%

basics

~20 s

The default queue strategy hands out each row once, so the first virtual user to find the feeder empty stops the whole load generator. Gatling ends the run as a crash reading 'feeder is now empty', not a failed request.

open as a page

In Gatling 3.15, what happened to the `eager` and `batch` feeder loading modes, and what now decides how a file-backed feeder is loaded?

level: middleimportance: should knowfreq 20%

basics

~20 s

Gatling 3.15 dropped both methods outright, so calls to them no longer compile. Loading is now automatic for the line-based file sources such as CSV: the file's size is compared against a megabyte threshold setting, 100 by default, and larger files are streamed rather than held in memory. JSON feeder files are always loaded whole.

open as a page

A Gatling login simulation feeds from a 200,000-row credentials CSV. Does Gatling hold every row in heap, and what decides?

level: seniorimportance: should knowfreq 36%

basics

~20 s

It depends on file size. Gatling compares the uncompressed file length against gatling.core.feederAdaptiveLoadModeThreshold, 100 MB by default: below it the whole file is parsed into memory, above it records are read from disk as users consume them.

open as a page

A Gatling simulation calls csv("credentials.csv").readRecords() only to size its injection profile. What does that cost, and what should it call instead?

level: seniorimportance: should knowfreq 30%

basics

~20 s

readRecords builds the feeder and drains it into a list, so the file is parsed once for the sizing call and again when the run starts. recordsCount counts lines without constructing records, and is the call for sizing.

open as a page

A Gatling run stopped eight minutes into a planned thirty with 'Feeder csv(credentials.csv) crashed: feeder is now empty' — what outputs does that run leave you, and how do you size the file so the next one finishes?

level: seniorimportance: should knowfreq 40%

basics

~20 s

That run leaves its raw log but no HTML report and no assertion verdict, because a crash stops it first. Size the file from feed step executions - arrival rate times duration times feeds per user - and add headroom.

open as a page

A Gatling login simulation needs 200,000 distinct credentials per run. Would you ship them as a CSV, read them with jdbcFeeder, or serve them from Redis?

level: principalimportance: should knowfreq 32%

basics

~20 s

Default to the CSV. It is the only one of the three available in all five SDKs, it costs the running system nothing, and it ships with the artifact. Use the others only when the data cannot be a file.

open as a page

Across a Gatling suite, how would you decide which of the four feeder consumption strategies each data file gets, and what can those four not express?

level: principalimportance: should knowfreq 33%

basics

~20 s

Decide from the data, not the scenario: records carrying an identity get a consuming strategy and a stock sized to the run; everything else gets circular or random. The four cannot express reuse with uniqueness, or lending a record back.

open as a page

In Gatling's JavaScript and TypeScript SDK, which feeders and feeder methods from the JVM SDKs are missing?

level: middleimportance: nice to knowfreq 28%

basics

~20 s

jdbcFeeder, redisFeeder in all four command forms, readRecords and the custom-iterator feeder are documented as not supported in the JavaScript and TypeScript SDK. The file and in-memory feeders, unzip, shard, transform and recordsCount all are.

open as a page

In a Gatling simulation, what does `feed(feeder, 2)` put into the virtual user's Session, and what happens if only one record is left?

level: middleimportance: nice to knowfreq 24%

basics

~20 s

It takes two records in one step and merges them by key, so each source column becomes one Session attribute holding a two-element list that you read by index. If fewer than two records remain, Gatling stops the load generator.

open as a page