Add basis of web application benchmarks

This commit is contained in:
Robert Husák 2020-05-28 10:19:03 +02:00
Родитель 36291cdb7a
Коммит b56b47bc8d
13 изменённых файлов: 243 добавлений и 0 удалений

1
.gitignore поставляемый
Просмотреть файл

@ -3,6 +3,7 @@
# Measured benchmark results
microbenchmarks/results.json
webapps/results.json
# User-specific files
*.suo

3
webapps/.dockerignore Normal file
Просмотреть файл

@ -0,0 +1,3 @@
*.Dockerfile
run.ps1
results.json

Просмотреть файл

@ -0,0 +1,3 @@
{
"requestPath": "/hello.php"
}

Просмотреть файл

@ -0,0 +1,3 @@
<?php
echo "Hello World!";

Просмотреть файл

@ -0,0 +1,2 @@
#!/bin/bash
cp hello.php $1

Просмотреть файл

@ -0,0 +1,3 @@
FROM httpd:2.4.43
CMD ["bash"]

Просмотреть файл

@ -0,0 +1,30 @@
using System;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace peachpie.Server
{
class Program
{
static void Main(string[] args)
{
var host = WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://*:80/")
.Build();
host.Run();
}
}
class Startup
{
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
app.UsePhp(new PhpRequestOptions(scriptAssemblyName: "peachpie"));
}
}
}

Просмотреть файл

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="Version.props" Sdk="Peachpie.NET.Sdk" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Peachpie.AspNetCore.Web" Version="$(PeachpieVersion)" />
<ProjectReference Include="..\Website\Website.msbuildproj" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,12 @@
<Project Sdk="Peachpie.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>peachpie</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Compile Include="**/*.php" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,48 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Website", "Website\Website.msbuildproj", "{A271793F-72BF-429D-9EC8-83C03559CBD6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{AF5D53C1-32B5-473F-9229-817608068701}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|x64.ActiveCfg = Debug|x64
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|x64.Build.0 = Debug|x64
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|x86.ActiveCfg = Debug|x86
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Debug|x86.Build.0 = Debug|x86
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|Any CPU.Build.0 = Release|Any CPU
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|x64.ActiveCfg = Release|x64
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|x64.Build.0 = Release|x64
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|x86.ActiveCfg = Release|x86
{A271793F-72BF-429D-9EC8-83C03559CBD6}.Release|x86.Build.0 = Release|x86
{AF5D53C1-32B5-473F-9229-817608068701}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF5D53C1-32B5-473F-9229-817608068701}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF5D53C1-32B5-473F-9229-817608068701}.Debug|x64.ActiveCfg = Debug|x64
{AF5D53C1-32B5-473F-9229-817608068701}.Debug|x64.Build.0 = Debug|x64
{AF5D53C1-32B5-473F-9229-817608068701}.Debug|x86.ActiveCfg = Debug|x86
{AF5D53C1-32B5-473F-9229-817608068701}.Debug|x86.Build.0 = Debug|x86
{AF5D53C1-32B5-473F-9229-817608068701}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF5D53C1-32B5-473F-9229-817608068701}.Release|Any CPU.Build.0 = Release|Any CPU
{AF5D53C1-32B5-473F-9229-817608068701}.Release|x64.ActiveCfg = Release|x64
{AF5D53C1-32B5-473F-9229-817608068701}.Release|x64.Build.0 = Release|x64
{AF5D53C1-32B5-473F-9229-817608068701}.Release|x86.ActiveCfg = Release|x86
{AF5D53C1-32B5-473F-9229-817608068701}.Release|x86.Build.0 = Release|x86
EndGlobalSection
EndGlobal

99
webapps/run.ps1 Normal file
Просмотреть файл

@ -0,0 +1,99 @@
param (
[string] $serverDockerFilter='server-*',
[string] $appFilter='*',
[int] $seconds=30,
[int] $concurrency=20,
[string] $outputFile='results.json'
)
# Maximum theoretical number of requests to run (in practice it's limited by time instead)
$maxRequests = 10000000
# Common helper variables for consistent naming of images and containers
$network = "appbenchmarks"
$clientContainer = "${network}-client"
$serverContainer = "${network}-server"
$clientTag = "${clientContainer}:latest"
# Helper function to create a reasonably named tag for the generated image
function Get-ServerTagName {
param ($serverDockerFile, $appDir)
$serverName = $serverDockerFile.Basename.ToLower()
$appName = $appDir.Name.ToLower()
return "appbenchmarks-${serverName}-app-${appName}:latest"
}
# Helper function for parsing text information using Regex
function Select-Regex {
param ([string]$subject, [string]$pattern)
$m = $subject | Select-String -pattern $pattern
return $m.Matches[0].Groups[1].Value
}
# Gather *.Dockerfile files of servers according to the filter
$serverDockerFiles = Get-ChildItem . -Filter $serverDockerFilter | Where-Object {$_.Name -like "server-*.Dockerfile"}
# Gather all the directories of all the apps to benchmark
$appDirs = Get-ChildItem ./apps -Filter $appFilter
# Generate all the docker images, one for each pair of server and app
Foreach ($serverDockerFile in $serverDockerFiles) {
Foreach ($appDir in $appDirs) {
$tag = Get-ServerTagName $serverDockerFile $appDir
& docker build --tag $tag --file $serverDockerFile --build-arg app=$appDir .
}
}
# Generate the docker image for the benchmark client
& docker build --tag $clientTag --file ./client.Dockerfile .
# Create the network to enable communication between the containers
& docker network create $network
# Run all the apps, benchmark them and gather the results
$results = @{}
Foreach ($serverDockerFile in $serverDockerFiles) {
$results[$serverDockerFile.Basename] = @{}
Foreach ($appDir in $appDirs) {
# Run the given container in the network
$tag = Get-ServerTagName $serverDockerFile $appDir
& docker run --name $serverContainer --network $network --detach --rm $tag
# Run the client container in the network
& docker run --name $clientContainer --network $network --detach --rm --tty $clientTag
# Compose the URL to run the benchmarks on
$appDirFullPath = $appDir.Fullname
$benchmarkConfig = Get-Content "${appDirFullPath}/benchmarkConfig.json" | ConvertFrom-Json
$requestPath = $benchmarkConfig.requestPath
$url = "http://${serverContainer}${requestPath}"
# Wait for the server to start
Start-Sleep -s 10
# Warm-up server (the client is reused to prevent from cooling it down due to reset)
& docker exec $clientContainer ab -t $seconds -c $concurrency -n $maxRequests $url
# Run the benchmarks and obtain the results
$abOutput = (& docker exec $clientContainer ab -t $seconds -c $concurrency -n $maxRequests $url) | Out-String
# Gather the results from the Apache Bench output
$results[$serverDockerFile.Basename][$appDir.Name] = @{
concurrency = $concurrency;
time_ms = $seconds * 1000;
requests = (Select-Regex $abOutput "Complete requests:[ ]+([0-9]+)") -as [int];
requests_failed = (Select-Regex $abOutput "Failed requests:[ ]+([0-9]+)") -as [int];
requests_per_second = (Select-Regex $abOutput "Requests per second:[ ]+([0-9]+(?:\.[0-9]+)?) \[#\/sec\] \(mean\)") -as [double];
request_time_ms = (Select-Regex $abOutput "Time per request:[ ]+([0-9]+(?:\.[0-9]+)?) \[ms\] \(mean\)") -as [double];
}
# Stop the containers (will be removed thanks to --rm on start)
& docker stop $clientContainer $serverContainer
}
}
# Export the results
ConvertTo-Json -Compress $results | Out-File $outputFile
# Clean up
& docker network rm $network

Просмотреть файл

@ -0,0 +1,17 @@
FROM mcr.microsoft.com/dotnet/core/sdk:3.1
ARG app
COPY ./config/peachpie /peachpie
COPY ./apps/$app /app
WORKDIR /app
RUN ["/app/install.sh", "/peachpie/Website"]
WORKDIR /peachpie
RUN echo "{ \"msbuild-sdks\": { \"Peachpie.NET.Sdk\": \"0.9.981\" } }" > global.json
RUN dotnet restore
RUN dotnet build -c Release
WORKDIR /peachpie/Server
ENTRYPOINT ["dotnet", "run", "--no-build", "-c", "Release"]

Просмотреть файл

@ -0,0 +1,7 @@
FROM php:7.4.6-apache
ARG app
COPY ./apps/$app /app
WORKDIR /app
RUN ["/app/install.sh", "/var/www/html"]