[PERF] Quadratic (O(N^2)) serialization time for large BOMs — `Bom.validate()` → `register_dependency()` linear scan
Évaluation
- Difficulté
- 3/5
- Temps estimé
- 1-2 jours
- Accessibilité débutants
- 36/100
- Type d'issue
- Bug
- Clarté
- Clairement spécifiée
- Activité
- À l'abandon
- Stack technique
- python
- Domaine
- performance
Piste de recherche
Commencez dans cyclonedx/model/bom.py, au niveau de Bom.validate() et register_dependency(), puis examinez cyclonedx/output/json.py pour confirmer le chemin de sérialisation. Examinez la pull request liée #1007 et ajoutez ou exécutez un test de régression/mise à l’échelle démontrant un comportement quasi linéaire tout en préservant une sortie identique octet par octet.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Environment
cyclonedx-python-lib9.1.0 (the offending code path is unchanged onmain/ 11.x)- Python 3.10, Linux
Description
Serializing a BOM with many components scales quadratically with the number of components, not linearly. For a container SBOM with several thousand components, output_as_string() stalls for minutes, almost entirely inside Bom.validate().
Steps to reproduce
import time
from cyclonedx.model.bom import Bom
from cyclonedx.model.component import Component, ComponentType
from cyclonedx.output import make_outputter
from cyclonedx.schema import OutputFormat, SchemaVersion
for N in (1000, 2000, 4000, 8000):
bom = Bom()
bom.metadata.component = Component(name="root", type=ComponentType.CONTAINER, bom_ref="root")
for i in range(N):
bom.components.add(Component(name=f"c{i}", version="1.0",
type=ComponentType.LIBRARY, bom_ref=f"ref-{i}"))
out = make_outputter(bom=bom, output_format=OutputFormat.JSON,
schema_version=SchemaVersion.V1_6)
t = time.perf_counter(); out.output_as_string()
print(f"N={N}: {time.perf_counter()-t:.2f}s")
Expected vs actual
Expected: time grows roughly linearly with N.
Actual: time grows roughly 4x per 2x N (quadratic):
N=1000: 0.14s
N=2000: 0.48s (x3.4)
N=4000: 1.75s (x3.6)
N=8000: 6.70s (x3.8)
A cProfile run at N=15000 shows ~112M calls to the lambda at cyclonedx/model/bom.py:653.
Root cause
cyclonedx/output/json.py—generate()unconditionally callsbom.validate()during serialization (there is no opt-out).cyclonedx/model/bom.py—Bom.validate()callsself.register_dependency(target=...)once per component (and per service).cyclonedx/model/bom.py—register_dependency()locates the existing entry with a linear scan:
Called once per component over the growing dependency collection, this is O(N²) overall._d = next(filter(lambda _d: _d.ref == target.bom_ref, self.dependencies), None)
Proposed fix
Replace the linear lookup with an indexed (dict[ref -> Dependency]) lookup. In a local benchmark an indexed variant produces byte-identical output and gives ~8x speedup at N=6000 (the gap widens with N). I'm happy to open a PR with the fix and a regression/scaling test.
- Langage dominant
- Python
- Étoiles
- 117
- Forks
- 67
- Merge moyen
- 3 j 9 h
- PR mergées (30 j)
- 4
Préparer son environnement
- Aucun Dockerfile ni fichier Docker Compose
- Propose un modèle de pull request
- Lire le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de CycloneDX/cyclonedx-python-lib
-
Support Python 3.15Peut-être pris @jkowalleck l’a pris il y a 3 jours. Ouverteenhancement
CycloneDX/cyclonedx-python-lib#1056 · 1 personne assignée ·
-
tests: test all model enumsPeut-être à nouveau libre @jkowalleck l’a pris il y a 139 jours, et aucune pull request n’est ouverte. OuverteQA
CycloneDX/cyclonedx-python-lib#991 · 1 personne assignée ·
-
feat(deps)!: make all de/serialization libraries optionalPeut-être à nouveau libre @Simoh23999 l’a pris il y a 87 jours, et aucune pull request n’est ouverte. Ouvertebreaking change dependencies
Difficulté 5/5 Plus d'une semaine Accessibilité débutants 35/100
CycloneDX/cyclonedx-python-lib#979 · 2 commentaires ·
-
feat: Add support for Component signaturePeut-être pris @wiebe-vandendriessche l’a pris il y a 138 jours. Ouverteenhancement help wanted schema 1.4
Difficulté 3/5 1-2 jours Accessibilité débutants 58/100
CycloneDX/cyclonedx-python-lib#978 · 4 commentaires ·
-
chore: have coverage uploaded consitentlyPeut-être à nouveau libre @jkowalleck l’a pris il y a 185 jours, et aucune pull request n’est ouverte. Ouvertechore
CycloneDX/cyclonedx-python-lib#966 · 1 personne assignée ·
Toutes les issues de CycloneDX/cyclonedx-python-lib
Issues similaires
-
intake mcp-intake needs-ac needs-human-review priority:medium
Difficulté 2/5 1-3 heures Accessibilité débutants 67/100
Ikalus1988/MisakaNet#3848 · 2 commentaires ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 75/100
521xueweihan/HelloGitHub#4105 ·
-
Difficulté 2/5 1-3 heures Accessibilité débutants 75/100
igormcsouza/bookloud#54 ·
-
Difficulté 1/5 Moins d'une heure Accessibilité débutants 90/100
aws-samples/sample-per-model-bedrock#526 ·
Les mainteneurs répondent en général sous 1 jour
-
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
ok-oldking/ok-wuthering-waves#1802 ·
Les mainteneurs répondent en général sous 2 jours