Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions gatling-simulations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,23 @@ There is preprocessed data available at https://nightlies.apache.org/solr/benchm

## Supported Simulations

Currently only a single simulation is supported, "IndexWikipediaBatchesSimulation", which provides a benchmark for indexing truncated wikipedia pages.
Currently, only two simulations are supported, "IndexWikipediaBatchesSimulation" and "SearchTermsSimulation".

### IndexWikipediaBatchesSimulation
`IndexWikipediaBatchesSimulation` provides a benchmark for indexing truncated wikipedia pages.
(This benchmark relies on having processed data available to index.
See [the data-prep README](../gatling-data-prep/README.md) for details on creating the necessary data.)
This benchmark can be can be configured using the environment-variable knobs below:
This benchmark can be configured using the environment-variable knobs below:

- `TESTS_WORK_DIR` - used to locate Wikipedia data (defaults to: `$REPOSITORY_ROOT/.gatling`)
- `BATCH_CONTENT_TYPE` - the format of the preprocessed Wikipedia data. Options are `application/json` or `application/xml` (defaults to: `application/json`)
- `CONCURRENT_USERS` - the number of threads used to index data to Solr (defaults to: 10)
- `endpoint` - a Solr URL to send documents to (defaults to: `"http://localhost:8983/solr"`)
- `NUM_BATCHES` - the number of batches of Wikipedia data to index. Options are `-1` for all or a number. (defaults to: `-1`)
- `endpoint` - a Solr URL to send documents to (defaults to: `"http://localhost:8983/"`)
- `COLLECTION_NAME` - the collection name to index data into, created by the simulation (defaults to: "wikipedia")
- `NUM_SHARDS` - the number of shards for the created collection (defaults to: 1)
- `NUM_REPLICAS` - the number of replicas for each shard of the created collection (defaults to: 1)

## Running Built-In Scenarios
- `TEAR_DOWN_COLLECTION` - if the collection should be deleted after running the simulation (defaults to: true)

Built-in indexing scenarios will create a collection and delete it after the test completes. You still need to load your own configset first.

Expand All @@ -39,4 +42,32 @@ Indexing benchmarks may be run using the command below from the repository root
NUM_SHARDS=2 ./gradlew gatlingRun --simulation index.IndexWikipediaBatchesSimulation
```

### SearchTermsSimulation
`SearchTermsSimulation` provides a benchmark for querying indexed wikipedia pages.
(This benchmark relies on having an already populated index available)
This benchmark can be configured using the environment-variable knobs below:

- `TESTS_WORK_DIR` - used to locate Wikipedia data (defaults to: `$REPOSITORY_ROOT/.gatling`)
- `SEARCH_TERMS_FILE` - used to source queries from. (defaults to: `wikipedia-queries.txt`)
- `CONCURRENT_USERS` - the number of threads used to index data to Solr (defaults to: 10)
- `endpoint` - a Solr URL to send documents to (defaults to: `"http://localhost:8983/"`)
- `COLLECTION_NAME` - the collection name to index data into, created by the simulation (defaults to: "wikipedia")

The search scenario requries a populated index.

Indexing benchmarks may be run using the command below from the repository root. One way is to reuse the a indexing scenario:

```
TEAR_DOWN_COLLECTION=false NUM_SHARDS=2 ./gradlew gatlingRun --simulation index.IndexWikipediaBatchesSimulation
```

Then run the searching test.
```
./gradlew gatlingRun --simulation search.SearchTermsSimulation
```

## Running Built-In Scenarios



Gatling will print basic statistics on `stdout`, but a more comprehensive (and human-friendly) HTML report is also available in `gatling-simulations/build/reports`
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
package index;

import io.gatling.javaapi.core.*;
import io.gatling.javaapi.http.*;
import util.GatlingUtils;
import util.SolrUtil;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.DirectoryStream;
Expand All @@ -16,15 +11,28 @@
import java.util.Map;
import java.util.stream.StreamSupport;

import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;
import io.gatling.javaapi.core.ChainBuilder;
import static io.gatling.javaapi.core.CoreDsl.RawFileBody;
import static io.gatling.javaapi.core.CoreDsl.atOnceUsers;
import static io.gatling.javaapi.core.CoreDsl.exec;
import static io.gatling.javaapi.core.CoreDsl.feed;
import static io.gatling.javaapi.core.CoreDsl.scenario;
import io.gatling.javaapi.core.ScenarioBuilder;
import io.gatling.javaapi.core.Simulation;
import static io.gatling.javaapi.http.HttpDsl.http;
import io.gatling.javaapi.http.HttpProtocolBuilder;
import io.gatling.javaapi.http.HttpRequestActionBuilder;
import util.GatlingUtils;
import util.SolrUtil;

public class IndexWikipediaBatchesSimulation extends Simulation {

private final String testWorkDir;
private final Path batchesDir;
private final int numFiles;
private final int numBatches;
private final int atOnceUsersCount;
private final boolean tearDownCollection;
private final HttpProtocolBuilder httpProtocol;
private final ChainBuilder updates;
private final ScenarioBuilder scn;
Expand All @@ -33,8 +41,10 @@ public IndexWikipediaBatchesSimulation() {
atOnceUsersCount = getConfigInt("CONCURRENT_USERS", 10);

testWorkDir = getConfig("TESTS_WORK_DIR", ".gatling");
tearDownCollection = getConfigBool("TEAR_DOWN_COLLECTION", true);
numBatches = getConfigInt("NUM_BATCHES", -1);
batchesDir = Paths.get(testWorkDir, "batches");
numFiles = batchesDir.toFile().list().length;
numFiles = numBatches > -1 ? numBatches : batchesDir.toFile().list().length;
httpProtocol = http.baseUrl(GatlingUtils.getEndpoint());
updates = index(testWorkDir);
scn = scenario(this.getClass().getSimpleName())
Expand All @@ -55,14 +65,20 @@ public static int getConfigInt(String key, int defaultValue) {
return Integer.parseInt(getConfig(key, String.valueOf(defaultValue)));
}

public static boolean getConfigBool(String key, boolean defaultValue) {
return Boolean.parseBoolean(getConfig(key, String.valueOf(defaultValue)));
}

@Override
public void before() {
setupCollection();
}

@Override
public void after() {
tearDownCollection();
if (tearDownCollection) {
tearDownCollection();
}
}


Expand Down
120 changes: 120 additions & 0 deletions gatling-simulations/src/gatling/java/search/SearchTermsSimulation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package search;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import io.gatling.javaapi.core.ChainBuilder;
import static io.gatling.javaapi.core.CoreDsl.atOnceUsers;
import static io.gatling.javaapi.core.CoreDsl.exec;
import static io.gatling.javaapi.core.CoreDsl.feed;
import static io.gatling.javaapi.core.CoreDsl.scenario;
import io.gatling.javaapi.core.ScenarioBuilder;
import io.gatling.javaapi.core.Simulation;
import static io.gatling.javaapi.http.HttpDsl.http;
import io.gatling.javaapi.http.HttpProtocolBuilder;
import io.gatling.javaapi.http.HttpRequestActionBuilder;
import util.GatlingUtils;

public class SearchTermsSimulation extends Simulation {

private final String testWorkDir;
private final String collectionName;
private final Path termsFile;
private final int atOnceUsersCount;
private final HttpProtocolBuilder httpProtocol;
private final ChainBuilder searchChain;
private final ScenarioBuilder scn;
private final String queryParams;

public SearchTermsSimulation() {
atOnceUsersCount = getConfigInt("CONCURRENT_USERS", 10);
collectionName = getConfig("COLLECTION_NAME", "wikipedia");
testWorkDir = getConfig("TESTS_WORK_DIR", ".gatling");
String termsFileName = getConfig("SEARCH_TERMS_FILE", "wikipedia-queries.txt");
queryParams = getConfig("QUERY_PARAMS","");
termsFile = Paths.get(testWorkDir, termsFileName);

httpProtocol = http.baseUrl(GatlingUtils.getEndpoint());

List<String> terms = readTerms(termsFile);
if (terms.isEmpty()) {
System.out.printf("No search terms found in %s; exiting simulation setup.%n", termsFile);
}
else{
System.out.printf("Found %s terms.%n", terms.size());
}

searchChain = search(terms);

int iterations = Math.max(1, terms.size() / Math.max(1, atOnceUsersCount));

scn = scenario(this.getClass().getSimpleName())
.repeat(iterations)
.on(exec(searchChain));

this.setUp(scn.injectOpen(atOnceUsers(atOnceUsersCount))).protocols(httpProtocol);
}

public static String getConfig(String key, String defaultValue) {
return System.getenv().getOrDefault(key, System.getProperty(key, defaultValue));
}

public static int getConfigInt(String key, int defaultValue) {
return Integer.parseInt(getConfig(key, String.valueOf(defaultValue)));
}

private static List<String> readTerms(Path file) {
if (!Files.exists(file)) return Collections.emptyList();
List<String> terms = new ArrayList<>();
try (BufferedReader r = Files.newBufferedReader(file)) {
String line;
while ((line = r.readLine()) != null) {
line = line.trim();
if (!line.isEmpty()) terms.add(line);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
return terms;
}

private ChainBuilder search(List<String> terms) {


Iterator<Map<String, Object>> feeder = terms.stream()
.map(t -> Collections.singletonMap("term", (Object) t))
.iterator();

HttpRequestActionBuilder req = http("search")
.get("/solr/" + collectionName + "/select")
.queryParam("q", "#{term}")
.queryParam("wt", "json");

// Add any extra query parameters provided as a single string: key1=val1&flag=true
if (!queryParams.isBlank()) {
for (String pair : queryParams.split("&")) {
if (pair.isBlank()) continue;
int idx = pair.indexOf('=');
if (idx < 0) {
req = req.queryParam(pair.trim(), "");
} else {
String key = pair.substring(0, idx).trim();
String value = pair.substring(idx + 1).trim();
req = req.queryParam(key, value);
}
}
}

return feed(feeder).exec(req);
}

}
Loading