[UPD] LongTest : trois étages par défaut, la mesure le dit

Le défaut promettait dix étages qu'aucune machine ne tient. Une descente
complète par ligne, sur 28 cœurs :

    étage 1 :   0 s d'amorçage,    200 s d'installation, 280 s en tout
    étage 2 :  37 s,               344 s,                495 s
    étage 3 :  93 s,               777 s,              1 064 s
    étage 4 : 15 608 s,         26 306 s,      n'a pas abouti

Trois étages coûtent une demi-heure. Le quatrième a coûté 4 h 20 d'amorçage et
7 h 18 d'installation sur la même machine : tout y est 15 à 30 fois plus lent,
pas une seule étape. C'est aussi là que les fabricants s'arrêtent — le
quatrième étage est le troisième hyperviseur imbriqué, AMD en documente deux.

La profondeur reste le seul paramètre, et le README dit désormais ce qu'on
achète en la montant.

--- EN ---

The default promised ten levels no machine can hold. One full descent per row,
on 28 cores:

    level 1:      0 s boot,    200 s install,   280 s total
    level 2:     37 s,         344 s,           495 s
    level 3:     93 s,         777 s,         1 064 s
    level 4: 15 608 s,      26 306 s,      did not finish

Three levels cost half an hour. The fourth cost 4 h 20 of boot and 7 h 18 of
install on the same machine: everything there is 15 to 30 times slower, not one
step. It is also where the vendors stop — level 4 is the third nested
hypervisor, and AMD documents two.

Depth remains the only parameter, and the README now says what raising it buys.

Assisted-by: claude-opus-5
(cherry picked from commit 226d6ffa3c664ba9e1a6dfdf48d52027b52eda23)
This commit is contained in:
Mathieu Benoit 2026-08-28 00:21:51 -04:00
parent 30399b4559
commit 8e5f5b9097
7 changed files with 187 additions and 16 deletions

View file

@ -33,11 +33,36 @@ Which is the point of the script: a number obtained once, on one machine, in
one chain, is an anecdote.
```
./LongTest/deep_proxmox.py --depth 10 --dry-run # the plan, nothing created
./LongTest/deep_proxmox.py --depth 10 # hours
./LongTest/deep_proxmox.py # three levels, ~30 minutes
./LongTest/deep_proxmox.py --dry-run # the plan, nothing created
./LongTest/deep_proxmox.py --depth 5 # ask for more, knowingly
./LongTest/deep_proxmox.py --detruire # undo it
```
### How deep is worth asking for
The depth is the only setting, and **three** is the default because three
works. Measured on a 28-core machine, one full descent per row:
| level | boot (ssh) | install | total |
|------:|-----------:|--------:|------:|
| 1 | 0 s | 200 s | 280 s |
| 2 | 37 s | 344 s | 495 s |
| 3 | 93 s | 777 s | 1 064 s |
| 4 | **15 608 s** | **26 306 s** | did not finish |
Three levels cost half an hour. The **fourth** cost 4 h 20 of boot and 7 h 18
of install on the same machine — everything there is 15 to 30 times slower, not
just one step. And it lands exactly where the hardware vendors stop: level 4 is
the *third* nested hypervisor, and AMD documents two.
A wider guest makes it worse, sharply: at level 4, one extra vCPU multiplied
the boot by 9.4 (1 664 s at two vCPU, 15 608 s at three), and at eight vCPU the
guest read 32 MiB in 106 minutes with a static instruction pointer. At levels 2
and 3 that same vCPU costs nothing.
So: three by default, five if you want to know, ten only to watch the wall.
The descent is **uniform**. Every level, the first included, goes through the
same six steps: create, wait for ssh, install Proxmox, reboot and check the
kernel, bring pmxcfs back up, check the storage. Only creation differs —
@ -141,11 +166,37 @@ D'où le script : un chiffre obtenu une fois, sur une machine, dans une chaîne,
est une anecdote.
```
./LongTest/deep_proxmox.py --depth 10 --dry-run # le plan, rien de créé
./LongTest/deep_proxmox.py --depth 10 # des heures
./LongTest/deep_proxmox.py # trois étages, ~30 minutes
./LongTest/deep_proxmox.py --dry-run # le plan, rien de créé
./LongTest/deep_proxmox.py --depth 5 # en demander plus, sciemment
./LongTest/deep_proxmox.py --detruire # défaire
```
### Quelle profondeur vaut la peine d'être demandée
La profondeur est le seul réglage, et **trois** est le défaut parce que trois
marche. Mesuré sur une machine à 28 cœurs, une descente complète par ligne :
| étage | amorçage (ssh) | installation | total |
|------:|---------------:|-------------:|------:|
| 1 | 0 s | 200 s | 280 s |
| 2 | 37 s | 344 s | 495 s |
| 3 | 93 s | 777 s | 1 064 s |
| 4 | **15 608 s** | **26 306 s** | n'a pas abouti |
Trois étages coûtent une demi-heure. Le **quatrième** a coûté 4 h 20
d'amorçage et 7 h 18 d'installation sur la même machine — tout y est 15 à 30
fois plus lent, pas une seule étape. Et cela tombe précisément là où les
fabricants s'arrêtent : le quatrième étage est le *troisième* hyperviseur
imbriqué, et AMD en documente deux.
Un invité plus large aggrave brutalement : au quatrième étage, un vCPU de plus
a multiplié l'amorçage par 9,4 (1 664 s à deux vCPU, 15 608 s à trois), et à
huit vCPU l'invité a lu 32 Mio en 106 minutes, pointeur d'instruction
immobile. Aux étages 2 et 3, ce même vCPU ne coûte rien.
Donc : trois par défaut, cinq pour savoir, dix seulement pour voir le mur.
La descente est **uniforme**. Chaque étage, le premier compris, passe par les
mêmes six étapes : créer, attendre le ssh, installer Proxmox, redémarrer et
vérifier le noyau, remettre pmxcfs debout, contrôler le stockage. Seule la

View file

@ -32,11 +32,37 @@ D'où le script : un chiffre obtenu une fois, sur une machine, dans une chaîne,
est une anecdote.
```
./LongTest/deep_proxmox.py --depth 10 --dry-run # le plan, rien de créé
./LongTest/deep_proxmox.py --depth 10 # des heures
./LongTest/deep_proxmox.py # trois étages, ~30 minutes
./LongTest/deep_proxmox.py --dry-run # le plan, rien de créé
./LongTest/deep_proxmox.py --depth 5 # en demander plus, sciemment
./LongTest/deep_proxmox.py --detruire # défaire
```
### Quelle profondeur vaut la peine d'être demandée
La profondeur est le seul réglage, et **trois** est le défaut parce que trois
marche. Mesuré sur une machine à 28 cœurs, une descente complète par ligne :
| étage | amorçage (ssh) | installation | total |
|------:|---------------:|-------------:|------:|
| 1 | 0 s | 200 s | 280 s |
| 2 | 37 s | 344 s | 495 s |
| 3 | 93 s | 777 s | 1 064 s |
| 4 | **15 608 s** | **26 306 s** | n'a pas abouti |
Trois étages coûtent une demi-heure. Le **quatrième** a coûté 4 h 20
d'amorçage et 7 h 18 d'installation sur la même machine — tout y est 15 à 30
fois plus lent, pas une seule étape. Et cela tombe précisément là où les
fabricants s'arrêtent : le quatrième étage est le *troisième* hyperviseur
imbriqué, et AMD en documente deux.
Un invité plus large aggrave brutalement : au quatrième étage, un vCPU de plus
a multiplié l'amorçage par 9,4 (1 664 s à deux vCPU, 15 608 s à trois), et à
huit vCPU l'invité a lu 32 Mio en 106 minutes, pointeur d'instruction
immobile. Aux étages 2 et 3, ce même vCPU ne coûte rien.
Donc : trois par défaut, cinq pour savoir, dix seulement pour voir le mur.
La descente est **uniforme**. Chaque étage, le premier compris, passe par les
mêmes six étapes : créer, attendre le ssh, installer Proxmox, redémarrer et
vérifier le noyau, remettre pmxcfs debout, contrôler le stockage. Seule la

View file

@ -28,11 +28,36 @@ Which is the point of the script: a number obtained once, on one machine, in
one chain, is an anecdote.
```
./LongTest/deep_proxmox.py --depth 10 --dry-run # the plan, nothing created
./LongTest/deep_proxmox.py --depth 10 # hours
./LongTest/deep_proxmox.py # three levels, ~30 minutes
./LongTest/deep_proxmox.py --dry-run # the plan, nothing created
./LongTest/deep_proxmox.py --depth 5 # ask for more, knowingly
./LongTest/deep_proxmox.py --detruire # undo it
```
### How deep is worth asking for
The depth is the only setting, and **three** is the default because three
works. Measured on a 28-core machine, one full descent per row:
| level | boot (ssh) | install | total |
|------:|-----------:|--------:|------:|
| 1 | 0 s | 200 s | 280 s |
| 2 | 37 s | 344 s | 495 s |
| 3 | 93 s | 777 s | 1 064 s |
| 4 | **15 608 s** | **26 306 s** | did not finish |
Three levels cost half an hour. The **fourth** cost 4 h 20 of boot and 7 h 18
of install on the same machine — everything there is 15 to 30 times slower, not
just one step. And it lands exactly where the hardware vendors stop: level 4 is
the *third* nested hypervisor, and AMD documents two.
A wider guest makes it worse, sharply: at level 4, one extra vCPU multiplied
the boot by 9.4 (1 664 s at two vCPU, 15 608 s at three), and at eight vCPU the
guest read 32 MiB in 106 minutes with a static instruction pointer. At levels 2
and 3 that same vCPU costs nothing.
So: three by default, five if you want to know, ten only to watch the wall.
The descent is **uniform**. Every level, the first included, goes through the
same six steps: create, wait for ssh, install Proxmox, reboot and check the
kernel, bring pmxcfs back up, check the storage. Only creation differs —

View file

@ -1174,7 +1174,13 @@ def principal(argv=None):
parseur = argparse.ArgumentParser(
description="Jusqu'à quel étage un Proxmox dans un Proxmox tient-il ?"
)
parseur.add_argument("--depth", type=int, default=10)
# Trois par défaut, et c'est une MESURE, pas une prudence : les trois
# premiers étages coûtent 280, 495 et 1 064 secondes — une demi-heure en
# tout. Le quatrième en a coûté 7 h 18 d'installation et 4 h 20 d'amorçage
# sur la même machine. Un défaut à dix promettait ce qu'aucune machine ne
# peut tenir ; la profondeur reste un paramètre, et c'est à qui la demande
# de savoir ce qu'il demande.
parseur.add_argument("--depth", type=int, default=3)
parseur.add_argument("--dry-run", action="store_true")
parseur.add_argument("--detruire", action="store_true")
args = parseur.parse_args(argv)

View file

@ -87,6 +87,12 @@ class LongTestMenuMixin:
print(t("Command not found !"))
def _longtest_depth(self):
"""Profondeur demandée. Dix par défaut : c'est ce qu'on veut mesurer."""
brut = input(f"{t('Depth (default 10): ')}").strip()
return int(brut) if brut.isdigit() and int(brut) > 0 else 10
"""Profondeur demandée. Trois par défaut, parce que trois marche.
Mesuré sur cette machine : les trois premiers étages prennent 280, 495
et 1 064 secondes — une demi-heure. Le quatrième a demandé 7 h 18
d'installation et 4 h 20 d'amorçage, et les suivants se comptent en
jours. Dix par défaut promettait ce qu'aucune machine ne tient.
"""
brut = input(f"{t('Depth (default 3): ')}").strip()
return int(brut) if brut.isdigit() and int(brut) > 0 else 3

View file

@ -3454,9 +3454,9 @@ TRANSLATIONS = {
"fr": "Script introuvable :",
"en": "Script not found:",
},
"Depth (default 10): ": {
"fr": "Profondeur (défaut 10) : ",
"en": "Depth (default 10): ",
"Depth (default 3): ": {
"fr": "Profondeur (défaut 3) : ",
"en": "Depth (default 3): ",
},
"Nesting level": {
"fr": "Étage d'imbrication",

View file

@ -208,15 +208,72 @@ class TestLEssaiABlanc(unittest.TestCase):
(int(n), int(v), int(r), int(d)) for n, v, r, d in plan
)
for parent, enfant in zip(etages, etages[1:]):
for i, quoi in ((1, "vCPU"), (2, "RAM"), (3, "disque")):
# Mémoire et disque : STRICTEMENT décroissants, chaque parent
# portant son enfant en plus de lui-même.
for i, quoi in ((2, "RAM"), (3, "disque")):
self.assertGreater(
parent[i], enfant[i], f"étage {parent[0]} : {quoi}"
)
# Le processeur : jamais plus étroit, mais pas toujours plus
# large. Deux étages imbriqués peu profonds ont la même largeur —
# au quatrième étage, un vCPU de plus multiplie l'amorçage par
# 9,4, alors qu'aux étages 2 et 3 il ne coûte rien.
self.assertGreaterEqual(
parent[1], enfant[1], f"étage {parent[0]} : vCPU"
)
# Et le plus profond reçoit ce qu'un Proxmox de test demande, pas ce
# qui reste.
self.assertEqual(etages[-1][1], 2, "vCPU du plus profond")
class TestLaProfondeurParDefaut(unittest.TestCase):
"""Trois, et c'est une MESURE, pas une prudence.
Sur la machine où ce test a été écrit, les trois premiers étages coûtent
280, 495 et 1 064 secondes — une demi-heure en tout. Le quatrième a demandé
7 h 18 d'installation et 4 h 20 d'amorçage, et les suivants se comptent en
jours. Un défaut à dix promettait ce qu'aucune machine ne peut tenir : la
profondeur reste un paramètre, mais le défaut doit marcher."""
def test_the_script_defaults_to_three(self):
import inspect
import sys as _sys
_sys.path.insert(0, os.path.join(RACINE, "LongTest"))
import deep_proxmox
src = inspect.getsource(deep_proxmox.principal)
self.assertIn('"--depth", type=int, default=3', src)
def test_the_menu_defaults_to_three(self):
import inspect
from script.todo.todo import TODO
src = inspect.getsource(TODO._longtest_depth)
self.assertIn("else 3", src)
# Et l'invite le DIT : un défaut caché se subit, il ne se choisit pas.
self.assertIn("Depth (default 3): ", src)
def test_the_prompt_is_translated(self):
from script.todo.todo_i18n import TRANSLATIONS
entree = TRANSLATIONS.get("Depth (default 3): ")
self.assertIsNotNone(entree, "invite non traduite")
self.assertIn("3", entree["fr"])
def test_the_default_depth_fits_a_modest_machine(self):
"""Le défaut doit tenir là où le test sera lancé, pas seulement sur la
machine de celui qui l'a écrit."""
from script.proxmox import nesting
plan = nesting.nesting_plan(
3, cpu_hote=8, ram_dispo_mo=24000, disque_libre_go=120
)
self.assertEqual(plan["atteignable"], 3)
self.assertEqual(plan["arret"], "")
class TestDefaireSansEffacerAutreChose(unittest.TestCase):
"""« --detruire » effaçait par SOUS-CHAÎNE de nom, dans le mauvais ordre,
sans confirmation et sans honorer --dry-run.