콘텐츠로 이동

Gatling Performance Testing Cheatsheet

Gatling Performance Testing Cheatsheet

Installation

PlatformCommand
Ubuntu/Debianwget https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/3.10.3/gatling-charts-highcharts-bundle-3.10.3-bundle.zip && unzip gatling-charts-highcharts-bundle-3.10.3-bundle.zip && sudo mv gatling-charts-highcharts-bundle-3.10.3 /opt/gatling
macOS (Homebrew)brew install gatling
Windows (Manual)Download from Maven Central, extract to C:\gatling, add bin directory to PATH
SDKMAN (Linux/Mac)sdk install gatling
Dockerdocker pull denvazh/gatling:latest
Maven PluginAdd io.gatling:gatling-maven-plugin:4.6.0 to pom.xml
Gradle PluginAdd id 'io.gatling.gradle' version '3.10.3' to build.gradle

Prerequisites

# Install Java 11+ (required)
sudo apt install openjdk-11-jdk -y  # Ubuntu/Debian
brew install openjdk@11              # macOS

# Verify Java installation
java -version

Basic Commands

CommandDescription
gatling.shLaunch interactive mode to select and run simulations
gatling.sh -s com.example.MySimulationRun a specific simulation class
gatling.bat -s com.example.MySimulationRun simulation on Windows
gatling.sh --helpDisplay help and available options
gatling.sh --versionShow Gatling version
recorder.shLaunch Gatling Recorder GUI for recording browser sessions
recorder.batLaunch Recorder on Windows
gatling.sh -ro simulation-folder-nameGenerate reports from existing simulation logs
gatling.sh -s MySimulation -nrRun simulation without generating reports
gatling.sh -s MySimulation -rd "Test description"Run with custom description for reports
mvn gatling:testRun all Gatling tests using Maven
mvn gatling:test -Dgatling.simulationClass=MySimulationRun specific simulation with Maven
gradle gatlingRunRun all Gatling tests using Gradle
gradle gatlingRun-com.example.MySimulationRun specific simulation with Gradle
ls user-files/simulations/List available simulation files

Advanced Usage

CommandDescription
gatling.sh -s MySimulation -rf /custom/resultsRun with custom results folder
gatling.sh -s MySimulation -bf /custom/binariesRun with custom binaries directory
gatling.sh -s MySimulation -rsf /custom/resourcesRun with custom resources directory
gatling.sh -s MySimulation -df /custom/dataRun with custom data directory
gatling.sh -s MySimulation -cf /path/to/gatling.confRun with custom configuration file
JAVA_OPTS="-Xms2G -Xmx4G" gatling.sh -s MySimulationRun with custom JVM memory settings
gatling.sh -s MySimulation -D baseUrl=https://api.example.comPass system properties to simulation
gatling.sh -s MySimulation -D users=100 -D duration=300Pass multiple system properties
mvn gatling:test -Dgatling.jvmArgs="-Xms2G -Xmx4G"Maven run with custom JVM arguments
docker run -v $(pwd)/user-files:/opt/gatling/user-files denvazh/gatlingRun Gatling in Docker container
gatling.sh -s Sim1 && gatling.sh -s Sim2Run multiple simulations sequentially
for sim in Sim1 Sim2; do gatling.sh -s $sim -nr; doneBatch run simulations without reports
mvn clean gatling:test -DbaseUrl=https://prod.example.comMaven run with environment-specific URL
gradle gatlingRun -Dusers=500 -Dduration=600Gradle run with dynamic parameters
`gatling.sh -s MySimulation 2>&1tee test.log`

Configuration

Main Configuration File (gatling.conf)

gatling {
  core {
    # Output directory for results
    outputDirectoryBaseName = "simulation"
    
    # Encoding for files
    encoding = "utf-8"
    
    # Timeout for requests
    timeOut = 60000
    
    # Directory for simulation classes
    simulationClass = ""
  }
  
  http {
    # Enable/disable SSL/TLS
    enableGA = false
    
    # Connection timeout
    connectTimeout = 10000
    
    # Request timeout
    requestTimeout = 60000
    
    # Max connections per host
    maxConnectionsPerHost = 6
  }
  
  data {
    # Directory for feeder files
    file {
      bufferSize = 256
    }
  }
  
  charting {
    # Indicators percentiles
    indicators {
      lowerBound = 800
      higherBound = 1200
      percentile1 = 50
      percentile2 = 75
      percentile3 = 95
      percentile4 = 99
    }
  }
}

System Properties Configuration

# Set via command line
gatling.sh -s MySimulation \
  -Dgatling.core.outputDirectoryBaseName=custom-output \
  -Dgatling.http.requestTimeout=30000 \
  -Dgatling.charting.indicators.percentile1=90

Maven Configuration (pom.xml)

<plugin>
    <groupId>io.gatling</groupId>
    <artifactId>gatling-maven-plugin</artifactId>
    <version>4.6.0</version>
    <configuration>
        <simulationClass>com.example.MySimulation</simulationClass>
        <jvmArgs>
            <jvmArg>-Xms2G</jvmArg>
            <jvmArg>-Xmx4G</jvmArg>
            <jvmArg>-XX:+UseG1GC</jvmArg>
        </jvmArgs>
        <systemProperties>
            <baseUrl>https://api.example.com</baseUrl>
            <users>100</users>
        </systemProperties>
    </configuration>
</plugin>

Gradle Configuration (build.gradle)

gatling {
    simulations = {
        include 'com/example/**/*Simulation.scala'
    }
    
    jvmArgs = ['-Xms2G', '-Xmx4G', '-XX:+UseG1GC']
    
    systemProperties = [
        'baseUrl': 'https://api.example.com',
        'users': '100'
    ]
}

Common Use Cases

Use Case 1: Basic API Load Test

# Create simulation file
cat > user-files/simulations/BasicApiTest.scala << 'EOF'
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class BasicApiTest extends Simulation {
  val httpProtocol = http
    .baseUrl("https://api.example.com")
    .acceptHeader("application/json")
    .contentTypeHeader("application/json")

  val scn = scenario("Basic API Test")
    .exec(http("Get Users")
      .get("/users")
      .check(status.is(200)))
    .pause(1)

  setUp(
    scn.inject(
      rampUsers(100) during (60 seconds)
    )
  ).protocols(httpProtocol)
}
EOF

# Run the test
gatling.sh -s BasicApiTest

# View results
open results/basicapitest-*/index.html  # macOS
xdg-open results/basicapitest-*/index.html  # Linux

Use Case 2: Stress Testing with Gradual Load

# Create stress test simulation
cat > user-files/simulations/StressTest.scala << 'EOF'
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import scala.concurrent.duration._

class StressTest extends Simulation {
  val httpProtocol = http.baseUrl("https://api.example.com")

  val scn = scenario("Stress Test")
    .exec(http("Heavy Endpoint")
      .post("/api/process")
      .body(StringBody("""{"data": "test"}"""))
      .check(status.is(200)))

  setUp(
    scn.inject(
      nothingFor(5 seconds),
      atOnceUsers(10),
      rampUsers(50) during (30 seconds),
      constantUsersPerSec(20) during (60 seconds),
      rampUsersPerSec(20) to 50 during (60 seconds)
    )
  ).protocols(httpProtocol)
    .maxDuration(5 minutes)
    .assertions(
      global.responseTime.max.lt(5000),
      global.successfulRequests.percent.gt(95)
    )
}
EOF

# Run with custom memory settings
JAVA_OPTS="-Xms4G -Xmx8G" gatling.sh -s StressTest

Use Case 3: CI/CD Integration with Maven

# Add to Jenkins/GitLab CI pipeline
mvn clean gatling:test \
  -Dgatling.simulationClass=com.example.PerformanceTest \
  -DbaseUrl=${TEST_URL} \
  -Dusers=${CONCURRENT_USERS} \
  -Dduration=${TEST_DURATION}

# Check exit code for pass/fail
if [ $? -eq 0 ]; then
  echo "Performance test passed"
else
  echo "Performance test failed"
  exit 1
fi

# Archive results
tar -czf gatling-results.tar.gz target/gatling/

Use Case 4: Recording Browser Session

# Start recorder
recorder.sh

# Configure in GUI:
# - Listening Port: 8000
# - Output folder: user-files/simulations
# - Class name: RecordedSimulation

# Configure browser proxy to localhost:8000
# Perform actions in browser
# Stop recording

# Run recorded simulation
gatling.sh -s RecordedSimulation

Use Case 5: Data-Driven Testing with Feeders

# Create CSV data file
cat > user-files/resources/users.csv << 'EOF'
username,password
user1,pass1
user2,pass2
user3,pass3
EOF

# Create simulation with feeder
cat > user-files/simulations/DataDrivenTest.scala << 'EOF'
import io.gatling.core.Predef._
import io.gatling.http.Predef._

class DataDrivenTest extends Simulation {
  val httpProtocol = http.baseUrl("https://api.example.com")
  
  val feeder = csv("users.csv").circular

  val scn = scenario("Login Test")
    .feed(feeder)
    .exec(http("Login")
      .post("/login")
      .body(StringBody("""{"username":"${username}","password":"${password}"}"""))
      .check(status.is(200)))

  setUp(scn.inject(atOnceUsers(10))).protocols(httpProtocol)
}
EOF

# Run test
gatling.sh -s DataDrivenTest

Best Practices

  • Use Appropriate Load Profiles: Start with gradual ramp-up (rampUsers) rather than atOnceUsers to simulate realistic traffic patterns and avoid overwhelming the system immediately

  • Set Realistic Timeouts: Configure connection and request timeouts based on your SLAs (e.g., requestTimeout = 30000 for 30 seconds) to catch performance issues early

  • Implement Proper Assertions: Add assertions to automatically fail tests when performance degrades (global.responseTime.percentile3.lt(2000) ensures 95th percentile under 2 seconds)

  • Use Feeders for Dynamic Data: Leverage CSV, JSON, or custom feeders instead of hardcoding test data to simulate real user behavior and avoid cache hits

  • Allocate Sufficient Memory: For large-scale tests, increase JVM heap size (-Xms4G -Xmx8G) to prevent OutOfMemory errors and ensure smooth execution

  • Monitor System Resources: Watch CPU, memory, and network usage on both load generator and target system during tests to identify bottlenecks accurately

  • Run Tests from Production-Like Environment: Execute load tests from infrastructure similar to production (network latency, bandwidth) for accurate results

  • Version Control Your Simulations: Store simulation code in Git alongside application code to track changes and enable collaboration

  • Separate Concerns with Scenarios: Break complex tests into multiple scenarios and chains for better maintainability and reusability

  • Analyze Reports Thoroughly: Don’t just check response times—examine request distribution, error rates, and response time percentiles to understand full performance picture

Troubleshooting

IssueSolution
OutOfMemoryError during test executionIncrease JVM heap size: JAVA_OPTS="-Xms4G -Xmx8G" gatling.sh -s MySimulation or reduce concurrent users
”Simulation class not found” errorEnsure simulation is in user-files/simulations/ and class name matches file name. Recompile if needed: mvn clean compile
Connection timeout errorsIncrease timeout in gatling.conf: gatling.http.connectTimeout = 30000 or check network connectivity to target system
SSL/TLS certificate errorsDisable certificate validation in simulation: .disableCaching.disableWarmUp.shareConnections.silentResources or add certificate to Java keystore
Recorder proxy not workingCheck browser proxy settings (localhost:8000), ensure recorder is running, verify no other proxy/VPN is interfering
Reports not generatingCheck disk space, verify write permissions on results directory, ensure test completed successfully without crashes
High response times on load generatorLoad generator is overloaded—reduce concurrent users, increase resources, or use distributed testing with multiple generators
”Too many open files” error (Linux)Increase file descriptor limit: ulimit -n 65536 before running Gatling, or add to /etc/security/limits.conf
Simulations compile but don’t runCheck for syntax errors in Scala code, verify all imports are correct, ensure Gatling version compatibility
Maven/Gradle plugin not foundUpdate plugin version in pom.xml/build.gradle, run mvn clean install or gradle clean build, check Maven Central connectivity
Inconsistent results between runsWarm up target system first, ensure consistent test environment, check for external factors (other traffic, scheduled jobs)
WebSocket connection failuresVerify WebSocket protocol in simulation: .ws("Connect").connect("/socket"), check target server WebSocket support
Feeder file not foundPlace CSV/JSON files in user-files/resources/, use relative path: csv("data.csv") not absolute path
Docker container exits immediatelyMount volumes correctly: -v $(pwd)/user-files:/opt/gatling/user-files, ensure simulation files exist in mounted directory

Quick Reference: Load Injection Profiles

// Immediate load
atOnceUsers(100)

// Gradual ramp-up
rampUsers(100) during (60 seconds)

// Constant rate
constantUsersPerSec(20) during (5 minutes)

// Gradual rate increase
rampUsersPerSec(10) to 50 during (2 minutes)

// Staircase pattern
incrementUsersPerSec(5)
  .times(5)
  .eachLevelLasting(30 seconds)
  .separatedByRampsLasting(10 seconds)
  .startingFrom(10)

// Complex scenario
nothingFor(5 seconds),
atOnceUsers(10),
rampUsers(50) during (30 seconds),
constantUsersPerSec(20) during (60 seconds)

Useful File Locations

PathDescription
user-files/simulations/Simulation Scala files
user-files/resources/Feeder data files (CSV, JSON)
user-files/bodies/Request body templates
results/Generated HTML reports
conf/gatling.confMain configuration file
conf/logback.xmlLogging configuration
target/gatling/Maven build output and reports