Sommaire
Bonjour 'nal,
En ces temps de fortes chaleurs où les esprits s'échauffent et la bière se fait rare, une constante demeure : quand Java est là, C# n'est pas loin.
Le programme
7 lignes (écrit d'un seul trait, sans tester):
var app = WebApplication.CreateBuilder(args).Build();
app.MapGet("/", (HttpRequest request) =>
{
request.Headers.Add("Location", $"https://avatar.spacefox.fr/Renard-{Random.Shared.Next(int.Parse(args.ElementAtOrDefault(1) ?? "0") + 1)}.png");
return System.Net.HttpStatusCode.Redirect;
});
app.Run($"http://localhost:{args.FirstOrDefault() ?? "5001"}");
Fait grâce à ce tuto
dotnet new webapi -minimal
Le framework
ASP .NET 7 Preview 5, sorti hier. Avec comme toutes les versions, beaucoup d'améliorations de performances.
Le tuning
Pas possible, la CLI dotnet ne propose pas d'options permettant de modifier ces valeurs. :(
Et commeent on fait pour avoir une toute petite stack et heap, alors ?
Cela n'existe pas en dotnet, à moins d'aller créer son propre hôte pour le CLR. Autrement dit, c'est hard !
Une autre option serait docker (au moins pour limiter la taille mémoire à 16 Mo) mais je connais pas assez docker pour ce faire, et il se fait tard. :p
Et avec une compilation en natif ?
Oui, ça arrive timidement mais officiellement avec .NET 7.
Hélas, c'est encore une fois pas possible, car ça dépend du trimming et ASP .NET utilise encore pas mal d'API non-trimmables.
On se tape plein de warnings rien qu'avec le trimming:
dotnet publish -c Release --self-contained true -p:PublishTrimmed=true
Bon ben un ReadyToRun au moins ?
On peut au moins faire une première passe du JIT offline et ainsi réduire drastiqement le temps de démarrage :
dotnet publish -c Release -r linux-x64 --self-contained true -p:PublishReadyToRun=true
Et le setup avec NGINX et le serveur d'images môssieur ?
Ah ben moi je sais pas, j'ai juste le serveur libre Kestrel… ¯\(ツ)//¯
Et ceci, en appelant encore la CLI (dotnet run):
dotnet run -- 5001 1
Et la taille du package ?
En un seul fichier avec le runtime .NET intégré :
dotnet publish -c Release -r linux-x64 -p:PublishReadyToRun=true -p:PublishSingleFile=true --self-contained true -o bin/pub
-> % ls -l bin/pub
total 83808
-rw-r--r--. 1 max max 119 15 juin 20:37 appsettings.Development.json
-rw-r--r--. 1 max max 142 15 juin 20:37 appsettings.json
-rwxr-xr-x. 1 max max 85789791 15 juin 21:54 Fr.SpaceFox.Avatar
-rw-r--r--. 1 max max 19532 15 juin 21:54 Fr.SpaceFox.Avatar.pdb
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣤⣴⣶⣿⠿⣿⣿⠿⠿⠿⠿⠿⢿⣿⣷⣶⣶⣤⣄⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣶⣿⣿⣿⣿⣭⣤⣤⠤⠤⢤⣀⣀⣀⣀⣀⣀⣀⡈⠉⢙⣿⣿⣿⣶⣤⣀⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢀⣤⣾⠟⠋⠀⠀⣀⣤⣴⣿⡿⠿⢲⣤⣤⣄⣀⣀⠀⡀⠀⠀⣠⡾⠿⠟⠛⠛⠿⢿⣿⣿⣶⣤⣤⣀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⣰⣾⠟⠁⢀⣤⣾⣿⠟⠋⣉⣀⣀⣀⣈⣉⣩⠭⠭⠭⠭⠭⠭⠭⠤⠤⠀⠀⠀⣠⣶⠿⠿⠿⠿⣿⣿⣿⣿⣶⠀⠀⠀⠀
⠀⠀⠀⠀⢠⣾⡟⠁⣠⣾⣿⡿⠋⠀⣠⡾⠛⠋⠉⠉⠙⠛⠿⣦⡀⠀⠀⠀⠀⠀⠀⠀⢀⣴⡿⠋⠀⠀⠀⣠⣾⣿⡟⢻⣿⠀⠀⠀⠀⠀
⠀⠀⠀⢠⣿⠏⠠⠞⠛⠛⠋⠀⢀⣾⠋⠀⠀⠀⠀⠀⠀⠀⠀⠸⣷⠀⠀⠀⠀⠀⠀⠀⣾⠏⠀⠀⠀⠀⠀⠙⠻⠿⠁⢸⣿⠀⠀⠀⠀⠀
⠀⠀⠀⣾⡿⠀⠀⠀⠀⠀⠀⠀⣸⡏⠀⣀⣤⣤⡀⠀⠀⠀⠀⠀⣿⡄⠀⠀⠀⠀⠀⠠⣏⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣾⣿⠀⠀⠀⠀⠀
⠀⠀⢠⣿⠃⠀⠀⠀⠀⠀⢰⣶⣿⡇⠀⣿⣿⣿⡿⠂⠀⠀⠀⠀⣿⠃⠀⠀⠀⠀⠀⠀⢿⣄⠀⠀⠀⠀⠀⠀⠀⣀⣼⠏⣿⡇⠀⠀⠀⠀
⠀⠀⢸⣿⠀⠀⠀⠀⠀⠚⠛⢛⣿⣿⣤⡙⠛⠋⠀⠀⠀⠀⢀⣼⠟⠀⠀⠀⠀⠀⠀⠀⠈⠙⠛⠳⣶⣶⠿⠛⠛⠛⠿⣦⣿⣿⠀⠀⠀⠀
⠀⠀⣾⡇⠀⠀⠀⠀⠀⠀⠀⠞⠉⠀⠈⠛⠿⠶⣦⣤⣴⡾⠟⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⣴⠟⠁⢀⣀⣤⣀⡀⠀⠙⢿⣧⠀⠀⠀
⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⢤⣤⣤⣤⣤⡤⠴⠖⢻⣿⠃⢀⣴⡿⠉⠉⠉⠻⣦⠀⠀⢿⣧⠀⠀
⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣤⣤⣤⣤⣤⣤⠤⠖⠀⣠⣿⠃⠀⣼⡿⣿⡟⢲⡶⣤⣿⣆⠀⢸⣿⠀⠀
⠀⠀⣿⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠻⠿⢯⣥⣤⣤⣤⠖⠀⣿⡏⠀⢰⣿⣀⣿⣀⣸⣀⣿⣉⣿⠀⢸⣿⠀⠀
⠀⠀⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠠⣤⣤⣤⣤⣤⣄⣀⣀⠀⣿⡇⠀⢸⡇⠀⠀⠀⠀⠀⠀⠀⣿⠂⣼⡇⠀⠀
⠀⠀⢸⣇⠀⢠⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣧⠀⢸⡇⠀⠀⠀⠀⠀⠀⢰⡿⢠⣿⠁⠀⠀
⠀⠀⠘⣿⡀⠈⣧⠀⠸⡆⠀⢤⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⢸⡇⠀⠀⠀⠀⠀⢠⣿⠁⣾⡇⠀⠀⠀
⠀⠀⠀⢸⣧⠀⠸⣧⠀⣷⠀⠀⠳⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⢸⡇⠀⠀⠀⠀⠀⣾⡇⠀⣿⠀⠀⠀⠀
⠀⠀⠀⠀⢿⡄⠀⠘⣷⣻⡇⠀⠀⠙⢦⠀⠀⠀⠀⠀⠤⣤⣤⣤⣀⠀⠀⠀⠀⠀⠀⠀⢸⣿⠀⣾⡇⠀⠀⠀⠀⠀⣿⡇⠀⣿⡇⠀⠀⠀
⠀⠀⠀⠀⠘⣿⡀⠀⠘⣿⣿⡀⠀⠀⠈⣷⠀⠀⠀⠀⠀⠐⠒⠾⠿⣷⣦⡀⠀⠀⠀⠀⣸⡏⢀⣿⠀⠀⠀⠀⠀⠀⢿⡇⠀⠸⣷⠀⠀⠀
⠀⠀⠀⠀⠀⠹⣧⠀⠀⢸⣿⣷⠀⠀⠀⢻⠀⠀⠀⠀⠀⠀⠐⠲⢶⣬⡙⠻⣦⠀⠀⢀⡿⠁⢸⡟⠉⠙⠓⠲⣄⠀⢸⣷⠀⠀⡇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⢹⣇⠀⠀⢻⡟⣧⠀⠀⠸⣄⠀⠀⠀⠀⢀⣀⣀⠀⠈⠻⢦⣄⠀⠀⣾⡇⠀⣿⡇⠀⠀⠀⠀⠈⢷⡀⣿⠀⠀⡇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⢿⣆⠀⠈⢷⡘⣧⠀⠀⠈⠳⣄⠀⠀⠀⠉⠉⠛⠲⣦⡀⠙⠷⠀⣿⠀⠀⣿⠶⠶⡶⠶⡶⢶⠶⢿⣿⠀⠀⡇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠈⢿⣆⠀⠀⠻⣿⡷⣤⣀⠀⠈⠳⣄⠀⠀⠀⠀⠀⠀⠙⠷⣄⠀⣿⠀⠀⢿⣧⣸⣧⣤⡇⢸⣆⣼⡏⠀⢀⡇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠈⢿⣧⡀⠀⠈⠳⣄⠉⠓⢦⣀⠈⠻⢦⡀⠀⠀⠀⠀⠀⠈⢷⣿⠀⠀⠘⣿⣅⠀⠈⠉⢙⣻⡟⠀⠀⣼⡇⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠙⢿⣦⡀⠀⠈⠙⠶⣤⣽⣿⣦⣄⡀⠀⠀⠀⠀⠀⠀⠀⢿⣇⠀⠀⠈⠙⠻⠿⠿⠟⠋⠀⠀⣼⡿⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⢷⣦⣀⠀⠀⠈⠙⠻⠿⢿⣿⣶⣶⡶⠶⠶⣤⣼⣿⣷⣄⣀⠀⠀⠀⠀⢀⣀⣤⡾⠋⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠛⠿⣶⣤⣄⡀⠀⠀⠈⠉⠙⠛⠓⠶⠶⠶⠆⠀⠉⠛⠛⢻⣾⣿⡿⠟⠋⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠙⠿⢿⣶⣦⣄⡀⠀⠀⠀⠀⠀⢀⣶⣶⣶⡶⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠉⠙⠻⢷⣶⣶⣶⣶⠾⠟⠉⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Tu veux pas voir la taille sans inclure le runtime ?
Non. Ça fera plusieurs Mio de toutes façons, autant y aller à fond les ballons. :p
Et puis maintenant que c'est multiplateforme, tout le monde n'a pas le runtime.
On est plus sous Windows, Dorothée !
Les performances
Sur un vieux laptop Fedora vieux de 10 ans et sur batterie.
On a peur de rien ici !
/home/max/dotnet/dotnet publish -r linux-x64 -p:PublishReadyToRun=true --self-contained true -c Release -o bin/publish
bin/publish/Fr.SpaceFox.Avatar 6666 21 &
ab -n 100000 -c 10 http://localhost:6666/
Ça tourne ! :
> % info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:6666
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/max/repos/Fr.SpaceFox.Avatar
Compte-rendu:
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: Kestrel
Server Hostname: localhost
Server Port: 6666
Document Path: /
Document Length: 3 bytes
Concurrency Level: 10
Time taken for tests: 11.375 seconds
Complete requests: 100000
Failed requests: 0
Total transferred: 14200000 bytes
HTML transferred: 300000 bytes
Requests per second: 8791.22 [#/sec] (mean)
Time per request: 1.137 [ms] (mean)
Time per request: 0.114 [ms] (mean, across all concurrent requests)
Transfer rate: 1219.10 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 0 1 0.4 1 119
Waiting: 0 1 0.4 1 117
Total: 1 1 0.4 1 119
Percentage of the requests served within a certain time (ms)
50% 1
66% 1
75% 1
80% 1
90% 1
95% 1
98% 1
99% 1
100% 119 (longest request)
8791.22.
Alors c'est ma machine, le manque de compilation AOT, ma connexion de campagne, ou le setup différent, voire le fait que je sois sur batterie le coupable, à votre avis ?
J'en sais rien, mais vu que j'ai pas de bogue je suis content de moi (pour une fois). :p
Allez, ciao !
# là, java sent, là java, sent, va ...
Posté par legranblon (site web personnel) . Évalué à 5.
"quand Java est là, C# n'est pas loin."
Autrement dit, quand java est là, on c shrap sans vergogne.
Et par contre, quand java s'en va, le jazz est-il là ?
# En C99 (portable POSIX, pthreads)
Posté par Pierre Tramal (site web personnel) . Évalué à 4. Dernière modification le 16 juin 2022 à 19:12.
En trichant un peu (on ne lit pas la requête du client) on obtient cela:
~ $ wrk -c 10 -t 10 http://127.0.0.1:8000/
Running 10s test @ http://127.0.0.1:8000/
10 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 369.14us 88.04us 2.08ms 84.28%
Req/Sec 2.50k 76.09 3.22k 87.70%
250520 requests in 10.10s, 22.20MB read
Requests/sec: 24808.63
Transfer/sec: 2.20MB
pour un binaire (statiquement lié, musl) de 33ko, et 200ko de mémoire mappée.
https://gist.github.com/alex14fr/e61b85e1380ee02e2d9d7dbcfa5e6d71
[^] # Re: En C99 (portable POSIX, pthreads)
Posté par Pierre Tramal (site web personnel) . Évalué à 4.
Et en passant au write() non bloquant (et en enlevant le multi-threading) on passe à un binaire statique de 25ko avec 40 000 requêtes/s (184 ko de mémoire mappée).
https://gist.github.com/alex14fr/48af0cb92e21e24a823bb0ec1c74e0a7
# plus simple avec compilation native
Posté par TImaniac (site web personnel) . Évalué à 4.
Tu peux utiliser des API plus "basiques" et ainsi avoir un résultat compilable en natif. Je te laisse comparer les perfs sur ta bécane :)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.