-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4 from habbes/dotnet-perf-analysis-intro
Dotnet perf analysis intro
- Loading branch information
Showing
15 changed files
with
340 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
**/.classpath | ||
**/.dockerignore | ||
**/.env | ||
**/.git | ||
**/.gitignore | ||
**/.project | ||
**/.settings | ||
**/.toolstarget | ||
**/.vs | ||
**/.vscode | ||
**/*.*proj.user | ||
**/*.dbmdl | ||
**/*.jfm | ||
**/azds.yaml | ||
**/bin | ||
**/charts | ||
**/docker-compose* | ||
**/Dockerfile* | ||
**/node_modules | ||
**/npm-debug.log | ||
**/obj | ||
**/secrets.dev.yaml | ||
**/values.dev.yaml | ||
LICENSE | ||
README.md | ||
!**/.gitignore | ||
!.git/HEAD | ||
!.git/config | ||
!.git/packed-refs | ||
!.git/refs/heads/** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
|
||
Microsoft Visual Studio Solution File, Format Version 12.00 | ||
# Visual Studio Version 17 | ||
VisualStudioVersion = 17.12.35707.178 d17.12 | ||
MinimumVisualStudioVersion = 10.0.40219.1 | ||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleApi", "SampleApi\SampleApi.csproj", "{33834EF1-FF41-4B00-8279-9AF2861C6E20}" | ||
EndProject | ||
Global | ||
GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
Debug|Any CPU = Debug|Any CPU | ||
Release|Any CPU = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
{33834EF1-FF41-4B00-8279-9AF2861C6E20}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||
{33834EF1-FF41-4B00-8279-9AF2861C6E20}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||
{33834EF1-FF41-4B00-8279-9AF2861C6E20}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||
{33834EF1-FF41-4B00-8279-9AF2861C6E20}.Release|Any CPU.Build.0 = Release|Any CPU | ||
EndGlobalSection | ||
GlobalSection(SolutionProperties) = preSolution | ||
HideSolutionNode = FALSE | ||
EndGlobalSection | ||
EndGlobal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# .NET Performance analysis intro | ||
|
||
This sample project aims to demonstrate how to analyze and improve the performance of a .NET | ||
service using Visual Studio profilers. | ||
|
||
In this exercise we attempt to improve the latency and throughput of a simple API. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
namespace SampleApi; | ||
|
||
internal class DataReader | ||
{ | ||
public static async Task<List<LocationData>> ReadDataAsync(Stream input) | ||
{ | ||
List<LocationData> data = new(); | ||
var reader = new StreamReader(input); | ||
|
||
string content = await reader.ReadToEndAsync(); | ||
|
||
var lines = content.Split(Environment.NewLine); | ||
|
||
foreach (var line in lines) | ||
{ | ||
var words = line.Split(" "); | ||
string name = default; | ||
double temperature = default; | ||
foreach (var word in words) | ||
{ | ||
if (word.StartsWith("location:")) | ||
{ | ||
name = word.Split(':')[1]; | ||
} | ||
else if (word.StartsWith("temp:")) | ||
{ | ||
temperature = double.Parse(word.Split(':')[1]); | ||
} | ||
} | ||
|
||
var locationData = new LocationData(name!, temperature); | ||
data.Add(locationData); | ||
} | ||
|
||
return data; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
namespace SampleApi; | ||
|
||
internal class DataStore | ||
{ | ||
private Dictionary<string, RecordStats> cache = new(); | ||
|
||
public void Update(IEnumerable<LocationData> data) | ||
{ | ||
lock (cache) | ||
{ | ||
foreach (var item in data) | ||
{ | ||
if (cache.TryGetValue(item.Name, out RecordStats stats)) | ||
{ | ||
stats.Count++; | ||
stats.Sum += item.Temperature; | ||
stats.Max = Math.Max(stats.Max, item.Temperature); | ||
stats.Min = Math.Min(stats.Min, item.Temperature); | ||
} | ||
else | ||
{ | ||
cache[item.Name] = new RecordStats | ||
{ | ||
Count = 1, | ||
Sum = item.Temperature, | ||
Max = item.Temperature, | ||
Min = item.Temperature | ||
}; | ||
} | ||
} | ||
} | ||
} | ||
|
||
public LocationStats GetStats(string location) | ||
{ | ||
lock (cache) | ||
{ | ||
if (cache.TryGetValue(location, out RecordStats stats)) | ||
{ | ||
return new LocationStats(location, stats.Max, stats.Min, stats.Sum / stats.Count); | ||
} | ||
} | ||
|
||
return new LocationStats(location, 0, 0, 0); | ||
} | ||
|
||
class RecordStats | ||
{ | ||
public int Count { get; set; } | ||
public double Sum { get; set; } | ||
public double Max { get; set; } | ||
public double Min { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging. | ||
|
||
# This stage is used when running from VS in fast mode (Default for Debug configuration) | ||
FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS base | ||
USER $APP_UID | ||
WORKDIR /app | ||
EXPOSE 8080 | ||
EXPOSE 8081 | ||
|
||
|
||
# This stage is used to build the service project | ||
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build | ||
ARG BUILD_CONFIGURATION=Release | ||
WORKDIR /src | ||
COPY ["SampleApi/SampleApi.csproj", "SampleApi/"] | ||
RUN dotnet restore "./SampleApi/SampleApi.csproj" | ||
COPY . . | ||
WORKDIR "/src/SampleApi" | ||
RUN dotnet build "./SampleApi.csproj" -c $BUILD_CONFIGURATION -o /app/build | ||
|
||
# This stage is used to publish the service project to be copied to the final stage | ||
FROM build AS publish | ||
ARG BUILD_CONFIGURATION=Release | ||
RUN dotnet publish "./SampleApi.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false | ||
|
||
# This stage is used in production or when running from VS in regular mode (Default when not using the Debug configuration) | ||
FROM base AS final | ||
WORKDIR /app | ||
COPY --from=publish /app/publish . | ||
ENTRYPOINT ["dotnet", "SampleApi.dll"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
namespace SampleApi; | ||
|
||
record LocationData(string Name, double Temperature); | ||
|
||
record LocationStats(string Name, double MaxTemperature, double MinTemperature, double MeanTemperature); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using SampleApi; | ||
|
||
var builder = WebApplication.CreateBuilder(args); | ||
builder.Services.AddSingleton<DataStore>(); | ||
var app = builder.Build(); | ||
|
||
app.MapPost("/readings", async (DataStore store, HttpRequest request) => { | ||
var data = await DataReader.ReadDataAsync(request.Body); | ||
store.Update(data); | ||
|
||
return data; | ||
}); | ||
|
||
app.MapGet("/readings/{location}", (DataStore store, string location) => store.GetStats(location)); | ||
|
||
app.Run(); |
34 changes: 34 additions & 0 deletions
34
DotNetPerfAnalysisIntro/SampleApi/Properties/launchSettings.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"profiles": { | ||
"http": { | ||
"commandName": "Project", | ||
"launchBrowser": true, | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"dotnetRunMessages": true, | ||
"applicationUrl": "http://localhost:5208" | ||
}, | ||
"https": { | ||
"commandName": "Project", | ||
"launchBrowser": true, | ||
"environmentVariables": { | ||
"ASPNETCORE_ENVIRONMENT": "Development" | ||
}, | ||
"dotnetRunMessages": true, | ||
"applicationUrl": "https://localhost:7121;http://localhost:5208" | ||
}, | ||
"Container (Dockerfile)": { | ||
"commandName": "Docker", | ||
"launchBrowser": true, | ||
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}", | ||
"environmentVariables": { | ||
"ASPNETCORE_HTTPS_PORTS": "8081", | ||
"ASPNETCORE_HTTP_PORTS": "8080" | ||
}, | ||
"publishAllPorts": true, | ||
"useSSL": true | ||
} | ||
}, | ||
"$schema": "https://json.schemastore.org/launchsettings.json" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>net9.0</TargetFramework> | ||
<Nullable>enable</Nullable> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<UserSecretsId>39974002-6ee7-4e20-9bbc-abf4fc53fe51</UserSecretsId> | ||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.21.0" /> | ||
</ItemGroup> | ||
|
||
</Project> |
8 changes: 8 additions & 0 deletions
8
DotNetPerfAnalysisIntro/SampleApi/appsettings.Development.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft.AspNetCore": "Warning" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"Logging": { | ||
"LogLevel": { | ||
"Default": "Information", | ||
"Microsoft.AspNetCore": "Warning" | ||
} | ||
}, | ||
"AllowedHosts": "*" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# For more info on HTTP files go to https://aka.ms/vs/httpfile | ||
|
||
|
||
POST http://localhost:5208/readings | ||
Content-Type: text/plain | ||
Accept-Language: en-US,en;q=0.5 | ||
|
||
location:Nairobi temp:24.5 | ||
location:Kisumu temp:30.5 | ||
location:Mombasa temp:28.5 | ||
location:Nairobi temp:30 | ||
|
||
### | ||
|
||
|
||
POST http://localhost:5208/readings | ||
Content-Type: text/plain | ||
Accept-Language: en-US,en;q=0.5 | ||
|
||
location:Mombasa temp:26.6 | ||
location:Mombasa temp:6.6 | ||
location:Mombasa temp:34.9 | ||
location:Dublin temp:33.6 | ||
location:Nairobi temp:3.1 | ||
location:Dublin temp:36.1 | ||
location:Mombasa temp:29.0 | ||
location:Mombasa temp:21.0 | ||
location:Mombasa temp:9.5 | ||
location:Dublin temp:41.0 | ||
|
||
### | ||
|
||
|
||
GET http://localhost:5208/readings/Nairobi | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { sleep } from 'k6'; | ||
import http from 'k6/http'; | ||
|
||
const BASE_URL = __ENV.BASE_URL || "http://localhost:5208"; | ||
|
||
const places = ['Nairobi', 'Mombasa', 'Dublin', 'Redmond']; | ||
|
||
function generateValue(size) { | ||
|
||
let s = ''; | ||
|
||
for (let i = 0; i < size; i++) { | ||
const place = places[Math.floor(Math.random() * places.length)]; | ||
const temp = (Math.random() * 50).toFixed(1); | ||
s += `location:${place} temp:${temp}\n`; | ||
} | ||
|
||
return s; | ||
} | ||
|
||
const data = generateValue(10000); | ||
|
||
export default function () { | ||
|
||
http.post(`${BASE_URL}/readings`, data, { | ||
headers: { | ||
'Content-Type': 'text/plain' | ||
} | ||
}); | ||
|
||
// sleep(1); | ||
|
||
http.get(`${BASE_URL}/readings/Nairobi`); | ||
|
||
// sleep(1); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters