[PERF] Quadratic (O(N^2)) serialization time for large BOMs — `Bom.validate()` → `register_dependency()` linear scan
メンテナーはふだん 1 日以内に返信
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 36/100
- issue の種類
- バグ
- 明瞭さ
- 明確に書かれている
- 活発さ
- 停滞
- 技術スタック
- python
- 領域
- performance
調査の方向性
cyclonedx/model/bom.py の Bom.validate() と register_dependency() から始め、次に cyclonedx/output/json.py を調べてシリアライズの経路を確認します。リンクされている pull request #1007 をレビューし、バイト単位で同一の出力を維持しながら、ほぼ線形の挙動を示すリグレッション/スケーリングテストを追加または実行します。
索引モデルが issue の本文から書いたものです。
説明
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.
- 主要言語
- Python
- スター
- 117
- フォーク
- 67
- 平均マージ
- 21時間 9分
- マージ済み PR(30日)
- 3
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
CycloneDX/cyclonedx-python-lib のほかの issue
-
tests: test all model enums再び着手できるかも @jkowalleck が 125 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンQA
CycloneDX/cyclonedx-python-lib#991 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
feat(deps)!: make all de/serialization libraries optional再び着手できるかも @Simoh23999 が 72 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンbreaking change dependencies
難易度 5/5 1週間以上 初心者へのやさしさ 35/100
CycloneDX/cyclonedx-python-lib#979 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
feat: Add support for Component signature対応中かも @wiebe-vandendriessche が 124 日前に担当しました。 オープンenhancement help wanted schema 1.4
難易度 3/5 1〜2日 初心者へのやさしさ 58/100
CycloneDX/cyclonedx-python-lib#978 · コメント 4 件 ·
メンテナーはふだん 1 日以内に返信
-
chore: have coverage uploaded consitently再び着手できるかも @jkowalleck が 171 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンchore
CycloneDX/cyclonedx-python-lib#966 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
chore: use dependabot cooldown period再び着手できるかも @jkowalleck が 174 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンchore
CycloneDX/cyclonedx-python-lib#965 · コメント 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
CycloneDX/cyclonedx-python-lib の issue をすべて見る
似ている issue
-
namespace operations
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
EclipseFdn/open-vsx.org#14043 ·
メンテナーはふだん 1 日以内に返信
-
feedback simulation workshop
難易度 2/5 1〜3時間 初心者へのやさしさ 73/100
githubnext/gh-aw-workshop#4455 ·
メンテナーはふだん 1 日以内に返信
-
Triage 🩺
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
[BUG] Container scenario crashes without expected_recovery_time, kube DNS example uses retry_waitオープンneeds-triage
難易度 2/5 1〜3時間 初心者へのやさしさ 77/100
krkn-chaos/krkn#1627 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
NousResearch/hermes-agent#136483 ·
メンテナーはふだん 1 日以内に返信