Skip to content

Instantly share code, notes, and snippets.

@AnandPilania
Last active September 28, 2023 10:39
Show Gist options
  • Save AnandPilania/2d6df7264bc7e0bf1b9599dcfec49dd2 to your computer and use it in GitHub Desktop.
Save AnandPilania/2d6df7264bc7e0bf1b9599dcfec49dd2 to your computer and use it in GitHub Desktop.
Laravel Load Testing Command with GuzzleHttp

Laravel Load Testing

Perform load testing on a specified URL with a customizable number of concurrent connections using this Laravel Artisan command. It measures response times, HTTP status codes, and memory usage for each connection and displays the results in a clean table format. GuzzleHttp is used for asynchronous HTTP requests, ensuring efficient testing and minimal resource consumption.

Usage

php artisan load-test {url} {connections?}

`url`: Optional URL to test;
`connections`: Number of concurrent connections (default: 10)

Ideal for assessing the performance and scalability of your Laravel application.
<?php
namespace App\Console\Commands;
use GuzzleHttp\Client;
use GuzzleHttp\Pool;
use Illuminate\Console\Command;
class LoadTestCommand extends Command
{
/**
* @var string
*/
protected $signature = 'load-test {url}
{connections=10}';
/**
* @var string
*/
protected $description = 'Perform load testing on a specified URL with a customizable number of concurrent connections.';
public function handle(): int
{
$url = $this->argument('url');
$connections = $this->argument('connections');
$client = new Client([
'verify' => false,
]);
$results = collect([]);
$progressBar = $this->output->createProgressBar($connections);
$progressBar->start();
function convertToReadableFormat($size): string
{
$unit = array('b', 'kb', 'mb', 'gb', 'tb', 'pb');
return @round($size / (1024 ** ($i = floor(log($size, 1024)))), 2) . ' ' . $unit[$i];
}
$requests = static function () use ($client, $url, $connections, &$results, $progressBar) {
for ($i = 0; $i < $connections; $i++) {
yield static function () use ($client, $url, &$results, $i, $progressBar) {
$start = microtime(true);
$memoryUsageStart = memory_get_usage(true);
return $client->getAsync($url)->then(
function ($response) use (&$results, $i, $start, $memoryUsageStart, $progressBar) {
$statusCode = $response->getStatusCode();
$responseTime = (microtime(true) - $start) * 1000;
$memoryUsageEnd = memory_get_usage(true);
$memoryUsageDelta = $memoryUsageEnd - $memoryUsageStart;
$results->push([
'connection' => $i + 1,
'status_code' => $statusCode,
'memory_usage' => convertToReadableFormat($memoryUsageDelta),
'response_time' => $responseTime . ' ms',
]);
$progressBar->advance();
},
function ($reason) use (&$results, $i, $progressBar) {
$results->push([
'connection' => $i + 1,
'status_code' => 'Failed',
'memory_usage' => 'N/A',
'error' => $reason->getMessage(),
]);
$progressBar->advance();
}
);
};
}
};
$pool = new Pool($client, $requests(), [
'concurrency' => $connections,
]);
$promise = $pool->promise();
$promise->wait();
$progressBar->finish();
$this->newLine();
$this->table([
'Connection',
'Status Code',
'Memory Usage',
'Response Time/Error'
], $results->sortBy('status_code')->sortBy('response_time'));
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment