From 86e79a75cbb0b5a077c871eec876c7e299b6fa30 Mon Sep 17 00:00:00 2001 From: hadestructhor <60148800+hadestructhor@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:25:22 +0100 Subject: [PATCH] feat: benchmark init [SKIP CI] --- README.md | 30 +++++++- benchmark.md | 4 + benchmark.nu | 71 ++++++++++++++++++ build_results/bun-rspack-dockerfile.csv | 2 + build_results/nginx-distroless-dockerfile.csv | 2 + .../bun-rspack-dockerfile.csv | 2 + .../nginx-distroless-dockerfile.csv | 2 + bun.lockb | Bin 0 -> 14128 bytes 8 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 benchmark.md create mode 100644 benchmark.nu create mode 100644 build_results/bun-rspack-dockerfile.csv create mode 100644 build_results/nginx-distroless-dockerfile.csv create mode 100644 build_results2025-01-09_11-18-56/bun-rspack-dockerfile.csv create mode 100644 build_results2025-01-09_11-18-56/nginx-distroless-dockerfile.csv create mode 100644 bun.lockb diff --git a/README.md b/README.md index 4dfb550..7131acb 100644 --- a/README.md +++ b/README.md @@ -289,6 +289,20 @@ This is the biggest optimization in image size to date! A 1 998,2 MB less than I personally love distroless images. I've seen people say that you can debug them less, and not having basic tools like a shell is contraining, but I personally think it's not needed. You can simply build both a distroless and alpine image of your same code, then when there's a need to debug, scitch the container image for the alpine version. Or even better, use distroless images in production environments and alpines in development environments. +### Benchmark of build times using docker build --no-cache + +Here's the link to the result of the benchmark made to recreate the image 100 times for each branch that contains each optimization: +[benchmark.md](./benchmark.md) + +The nushell script used to generate this benchmark is [benchmark.nu](./benchmark.nu). + +You can execute the following command to run the build 100 times on each branch: +```shell +nu benchmark.nu 100 +``` + +By default the script runs 5 builds. + # Français @@ -578,4 +592,18 @@ Et voici la taille des images juste ici : C'est la plus grosse optimisation de taille jusqu'à présent ! Une différence de 1 998,2 MB de moins que l'image original, c'est 63,83 fois plus petit!!! C'est une réduction folle de 98,43% ! Et le meilleur dans tout ça? L'application est beaucoup plus sécurisé !!!!! Personnellement j'adore les images distroless. J'ai vu certaines personnes dire qu'elles sont moins débuggable en n'ayant aucun outil basique comme un bash mais je pense que ce n'est pas nécessaire. -Vous pouvez tout simplement construire une image alpine et distroless de votre application, puis remplacer votre image distroless par l'alpine pour débugger en cas de bug. Ou encore mieux et ce que je fais personnelelement, utiliser une image alpine en environnement de développement et distroless en production. \ No newline at end of file +Vous pouvez tout simplement construire une image alpine et distroless de votre application, puis remplacer votre image distroless par l'alpine pour débugger en cas de bug. Ou encore mieux et ce que je fais personnelelement, utiliser une image alpine en environnement de développement et distroless en production. + +## Benchmark temps de build avec docker build --no-cache + +Voici le lien du benchmark réalisé pour chaque branche en lançant la construction des conteneurs 100 fois: +[benchmark.md](./benchmark.md) + +Le script nushell pour générer ce benchmark se trouve dans [benchmark.nu](./benchmark.nu) + +Vous pouvez l'exécuter en lançant la commande suivante, pour lancer 100 build de chaque docker: +```shell +nu benchmark.nu 100 +``` + +Par défaut le script lance 5 build de chaque image. \ No newline at end of file diff --git a/benchmark.md b/benchmark.md new file mode 100644 index 0000000..033c4d6 --- /dev/null +++ b/benchmark.md @@ -0,0 +1,4 @@ +| tag | image | image size | median_time | max_time | min_time | benchmark_size | +| --------------------------- | ---------------------- | ---------- | ------------------------ | ------------------------ | ------------------------ | -------------- | +| bun-rspack-dockerfile | react-bun-rspack | 66.5MB | 29sec 166ms 270µs 300ns | 29sec 166ms 270µs 300ns | 29sec 166ms 270µs 300ns | 1 | +| nginx-distroless-dockerfile | react-nginx-distroless | 31.8MB | 10sec 81ms 405µs | 10sec 81ms 405µs | 10sec 81ms 405µs | 1 | \ No newline at end of file diff --git a/benchmark.nu b/benchmark.nu new file mode 100644 index 0000000..21a2f0d --- /dev/null +++ b/benchmark.nu @@ -0,0 +1,71 @@ +def main [benchmark_size:int=5] -> table { + let date = date now | format date '%F_%H-%M-%S' + echo $'build_results_($date)' + mkdir $'build_results_($date)' + let bench = [ + ['tag', 'image']; + # ['simple-dockerfile', 'react-simple], + # ['multi-stage-dockerfile', 'react-multistage'], + # ['node-alpine-dockerfile', 'react-multistage-alpine'], + # ['nginx-dockerfile', 'react-nginx'], + # ['nginx-alpine-dockerfile', 'react-nginx-alpine'], + ['bun-rspack-dockerfile', 'react-bun-rspack'], + ['nginx-distroless-dockerfile', 'react-nginx-distroless'] + ] + + # let images = [ + # 'node:18', + # 'node:18-alpine' + # 'nginx', + # 'nginx:stable-alpine', + # 'oven/bun', + # 'cgr.dev/chainguard/nginx' + # ] + + # echo 'Pulling all docker images in advance' + # echo '' + + # for entry in $images { + # docker pull $entry + # echo '' + # } + # echo '' + + mut benchmark: table = [] + + for entry: record in $bench { + echo $'Switching to branch ($entry.tag)' + echo '' + git checkout $entry.tag + mut sum = 0ns + mut max = 0ns + mut min = 0ns + mut json_result = [] + for i in 1..$benchmark_size { + let time = $'(timeit {docker build --no-cache -t $entry.image .})' | into duration + $sum += $time + + if $max == 0ns or $time >= $max { + $max = $time + } + if $min == 0ns or $time <= $min { + $min = $time + } + $json_result = ($json_result ++ [['tag', 'image', 'time']; [$entry.tag, $entry.image, $time]]) + } + let row table = [ + ['tag', 'image', 'image size', 'median_time', 'max_time', 'min_time', 'benchmark_size']; + [$'($entry.tag)', $'($entry.image)', $"(docker image ls $entry.image | from ssv | get 0 | get SIZE)", ($sum / $benchmark_size), $max, $min, $benchmark_size] + ] + $benchmark = ($benchmark ++ $row) + echo $json_result + $json_result | to csv | save -f $'./build_results_($date)/($entry.tag).csv' + } + + git checkout main + $benchmark | to md --pretty | save -f benchmark.md + cp -r $'./build_results_($date)/. ./build_results' + # git commit -m $"updated README for benchmarks (date now | format date '%+') [CI SKIP]" + # git push + return $benchmark +} diff --git a/build_results/bun-rspack-dockerfile.csv b/build_results/bun-rspack-dockerfile.csv new file mode 100644 index 0000000..8bdaf23 --- /dev/null +++ b/build_results/bun-rspack-dockerfile.csv @@ -0,0 +1,2 @@ +tag,image,time +bun-rspack-dockerfile,react-bun-rspack,9sec 220ms 258µs 900ns diff --git a/build_results/nginx-distroless-dockerfile.csv b/build_results/nginx-distroless-dockerfile.csv new file mode 100644 index 0000000..62658c3 --- /dev/null +++ b/build_results/nginx-distroless-dockerfile.csv @@ -0,0 +1,2 @@ +tag,image,time +nginx-distroless-dockerfile,react-nginx-distroless,9sec 221ms 865µs 600ns diff --git a/build_results2025-01-09_11-18-56/bun-rspack-dockerfile.csv b/build_results2025-01-09_11-18-56/bun-rspack-dockerfile.csv new file mode 100644 index 0000000..3397bec --- /dev/null +++ b/build_results2025-01-09_11-18-56/bun-rspack-dockerfile.csv @@ -0,0 +1,2 @@ +tag,image,time +bun-rspack-dockerfile,react-bun-rspack,29sec 166ms 270µs 300ns diff --git a/build_results2025-01-09_11-18-56/nginx-distroless-dockerfile.csv b/build_results2025-01-09_11-18-56/nginx-distroless-dockerfile.csv new file mode 100644 index 0000000..0012622 --- /dev/null +++ b/build_results2025-01-09_11-18-56/nginx-distroless-dockerfile.csv @@ -0,0 +1,2 @@ +tag,image,time +nginx-distroless-dockerfile,react-nginx-distroless,10sec 81ms 405µs diff --git a/bun.lockb b/bun.lockb new file mode 100644 index 0000000000000000000000000000000000000000..f0690d67d8b3a24cd530b75ab9fa65b8fc7cf97b GIT binary patch literal 14128 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 MpwiRG|KH#L0X%`1z5oCK literal 0 HcmV?d00001