diff --git a/Makefile b/Makefile index 6d7c5d2918..37d81b0d8c 100644 --- a/Makefile +++ b/Makefile @@ -694,3 +694,41 @@ endif run_lib_files_test: docker run --entrypoint bash -v $(realpath tests/file_lists):/test $(OVMS_CPP_DOCKER_IMAGE):$(OVMS_CPP_IMAGE_TAG)$(IMAGE_TAG_SUFFIX) ./test/test_release_files.sh ${BAZEL_DEBUG_FLAGS} > file_test.log 2>&1 ; exit_status=$$? ; tail -200 file_test.log ; exit $$exit_status + +# ── Build Metrics ────────────────────────────────────────────── +# Run all 5 build metrics inside an existing -build container: +# make build_metrics BUILD_CONTAINER=u24a_ovms1 +# +# Compare current vs baseline (git diff shows changes after commit): +# make build_metrics_compare +# +METRICS_TARGET ?= //src/... +METRICS_DIR ?= tools/build_metrics/current +BUILD_CONTAINER ?= $(OVMS_CPP_IMAGE_TAG)$(IMAGE_TAG_SUFFIX) +METRICS_BEFORE ?= tools/build_metrics/prebuild_baseline +METRICS_AFTER ?= $(METRICS_DIR) + +build_metrics: + @mkdir -p $(METRICS_DIR) + docker exec $(BUILD_CONTAINER) bash -c \ + "cd /ovms && python3 tools/build_metrics/measure_dep_fanin.py /ovms/$(METRICS_DIR)/deps.csv '$(METRICS_TARGET)'" + docker exec $(BUILD_CONTAINER) bash -c \ + "cd /ovms && python3 tools/build_metrics/measure_tu_sizes.py /ovms/$(METRICS_DIR)/tu.csv '$(METRICS_TARGET)'" + docker exec $(BUILD_CONTAINER) bash -c \ + "cd /ovms && python3 tools/build_metrics/measure_build_graph.py /ovms/$(METRICS_DIR)/trans_srcs.csv /ovms/$(METRICS_DIR)/impact.csv" + docker exec $(BUILD_CONTAINER) bash -c \ + "cd /ovms && python3 tools/build_metrics/measure_header_fanin.py /ovms/$(METRICS_DIR)/headers.csv '$(METRICS_TARGET)'" + @# Filter TU and headers to src/ only (drop external/third_party rows) + head -1 $(METRICS_DIR)/tu.csv > $(METRICS_DIR)/tu_src.csv + grep '^src/' $(METRICS_DIR)/tu.csv >> $(METRICS_DIR)/tu_src.csv || true + head -1 $(METRICS_DIR)/headers.csv > $(METRICS_DIR)/headers_src.csv + grep '^src/' $(METRICS_DIR)/headers.csv >> $(METRICS_DIR)/headers_src.csv || true + @# Remove unfiltered intermediates (only _src variants are committed) + rm -f $(METRICS_DIR)/tu.csv $(METRICS_DIR)/headers.csv + @echo "=== Metrics saved to $(METRICS_DIR)/ ===" + +build_metrics_compare: + python3 tools/build_metrics/compare_build_metrics.py \ + --before-dir $(METRICS_BEFORE) \ + --after-dir $(METRICS_AFTER) \ + --scopes all,non-test,test diff --git a/tools/build_metrics/README.md b/tools/build_metrics/README.md new file mode 100644 index 0000000000..fd6c296c30 --- /dev/null +++ b/tools/build_metrics/README.md @@ -0,0 +1,432 @@ +# OVMS Build Metrics Tools + +Tools for measuring and comparing OVMS build-graph and translation-unit +complexity. Five metrics capture different aspects of build cost and +incremental-rebuild exposure. + +All scripts use **Python 3 standard library only** — no venv or pip +install needed. They do require **Bazel** to be available (i.e. they +run inside a `-build` container where the repo is mounted at `/ovms`). + +### Quick Reference + +| Metric | Script | Output CSVs | +|--------|--------|-------------| +| **M1** — Dependency Fan-In | `tools/build_metrics/measure_dep_fanin.py` | `deps.csv` | +| **M2** — Preprocessed TU Size | `tools/build_metrics/measure_tu_sizes.py` | `tu.csv`, `tu_src.csv` | +| **M3** — Transitive Source Files | `tools/build_metrics/measure_build_graph.py` | `trans_srcs.csv` | +| **M4** — Change Impact | `tools/build_metrics/measure_build_graph.py` | `impact.csv` | +| **M5** — Header Fan-In | `tools/build_metrics/measure_header_fanin.py` | `headers.csv`, `headers_src.csv` | +| Compare | `tools/build_metrics/compare_build_metrics.py` | *(stdout report)* | + +--- + +## Metrics + +### M1 — Dependency Fan-In (Bazel targets) + +| | | +|---|---| +| **What it measures** | Number of transitive Bazel targets each source file depends on. | +| **Why it matters** | Proxy for build-graph complexity. A file with many target deps is coupled to a large part of the graph; any change in those targets triggers a recompile. | +| **Limitation** | Inflated by target splits — splitting one library into several mechanically increases dep count for all consumers even though actual build work is unchanged. Use M3 as a complementary metric. | +| **Tool** | `tools/build_metrics/measure_dep_fanin.py` | +| **Method** | Single `bazel query --output=xml` of all rules. Builds the dependency graph in memory and computes transitive closure per target in Python. | +| **Output CSV** | `deps.csv` — columns: `file, target, internal_deps, openvino, genai, tensorflow, mediapipe, grpc, protobuf, other_external, total_deps` | +| **Buckets** | 0–10, 11–20, 21–30, 31–40, 41–50, 51–60, 61–70, 71–80, 81–90, 91–100, 101–200, ≥201 deps | + +### M2 — Preprocessed Translation-Unit Size + +| | | +|---|---| +| **What it measures** | Number of lines and bytes after the C preprocessor expands all `#include`s and macros for each source file. | +| **Why it matters** | Direct proxy for frontend compile cost — the compiler must parse every preprocessed line. Smaller TUs compile faster, especially under Bazel parallelism. | +| **Tool** | `tools/build_metrics/measure_tu_sizes.py` | +| **Method** | Runs `bazel aquery` to extract real compile commands, then re-runs each with `-E -P` (preprocess only) and counts output. | +| **Prerequisite** | `bazel build //src:ovms` must have succeeded once so that generated headers (`.pb.h` etc.) exist. | +| **Output CSV** | `tu.csv` — columns: `file, pp_lines, pp_bytes` | +| **Buckets** | 0–10k, 10k–25k, 25k–50k, 50k–100k, 100k–200k, 200k–300k, ≥300k lines | + +### M3 — Transitive Source Files + +| | | +|---|---| +| **What it measures** | For each `.cpp` file, counts the total number of other `.cpp`/`.cc` files that belong to its Bazel target **and all the targets it transitively depends on**. In other words: if you do a clean build of this file's target, how many `.cpp` files need to be compiled (including itself and all its transitive library dependencies)? | +| **Why it matters** | This is a direct proxy for the size of a file's dependency subtree in terms of real compilation work. A file with `trans_src_count=222` means its target pulls in 222 source files through the chain of `deps = [...]` in BUILD files. Reducing this number (by breaking deps, splitting libraries, or removing unnecessary deps) directly shrinks what needs to be compiled. Unlike M1 which counts Bazel *targets*, this counts actual `.cpp` files, so it is immune to target-split artifacts where splitting one library into two increases the target count without changing real work. | +| **Example** | `pipelinedefinition.cpp` belonged to a target that depended (transitively) on 222 source files before optimization. After refactoring deps, it depends on only 51 — meaning 171 fewer `.cpp` files are in its compilation chain. | +| **Tool** | `tools/build_metrics/measure_build_graph.py` (first output) | +| **Method** | Single `bazel query --output=xml` of `kind("cc_library|cc_binary|cc_test", //src/...)`. Builds forward dependency graph, traverses closures, counts `.cpp`/`.cc` source files per target. | +| **Output CSV** | `trans_srcs.csv` — columns: `file, target, trans_src_count` | +| **Buckets** | 0–20, 21–50, 51–100, 101–200, 201–500, ≥501 source files | + +### M4 — Change Impact (Reverse Deps) + +| | | +|---|---| +| **What it measures** | How many source files would need to recompile if a given file's Bazel target is modified. | +| **Why it matters** | Measures the incremental-build "blast radius". High-impact files (e.g. `logging.cpp`, `status.cpp`) are bottleneck nodes — any change to them or their targets forces a large rebuild. Identifies where decoupling efforts have the highest ROI. | +| **Tool** | `tools/build_metrics/measure_build_graph.py` (second output) | +| **Method** | Same Bazel query as M3. Builds reverse dependency graph, traverses closures, counts impacted `.cpp`/`.cc` source files per target. | +| **Output CSV** | `impact.csv` — columns: `file, target, rdep_targets, impacted_srcs` | +| **Buckets** | 0–50, 51–100, 101–200, 201–500, ≥501 impacted source files | + +### M5 — Header Fan-In (Unique Header Count) + +| | | +|---|---| +| **What it measures** | Total number of unique header files resolved by the compiler for each translation unit, as well as the subset that are project headers (from `src/`). | +| **Why it matters** | Captures include-chain complexity at the compiler level (not Bazel level). A file pulling in 2000 unique headers has vastly more surface exposed to invalidation and longer preprocess/parse time than one pulling in 100. | +| **Tool** | `tools/build_metrics/measure_header_fanin.py` | +| **Method** | Runs `bazel aquery` to extract compile commands, then re-runs each with the `-M` flag (produce Makefile-format dependency list). Parses the output to count unique header paths. | +| **Prerequisite** | `bazel build //src:ovms` must have succeeded once so that generated headers exist. Without this, many files will fail. | +| **Output CSV** | `headers.csv` — columns: `file, unique_headers, unique_project_headers` | +| **Buckets** | 0–100, 101–200, 201–500, 501–1000, 1001–2000, ≥2001 headers | + +--- + +## Comparison Tool + +`tools/build_metrics/compare_build_metrics.py` — Compares before/after CSVs for any +combination of the 5 metrics and produces a report with: +- Headline stats (file count, total, average, median, P90, max) +- Bucketed distributions (count and delta per bucket) +- **Top 10 reductions** (files that improved the most) +- **Top 10 worst remaining** (files with the highest values after changes — these are the best candidates for future optimization) +- Summary verdict per metric + +Supports file scopes: `all`, `non-test`, `test` (via `--scopes`). + +All flags are optional — you can compare any subset of metrics: + +``` +--deps-before / --deps-after M1 +--tu-before / --tu-after M2 +--trans-srcs-before / --trans-srcs-after M3 +--impact-before / --impact-after M4 +--headers-before / --headers-after M5 +--scopes all,non-test,test +``` + +This script is **pure Python** with no Bazel dependency — it can run on +the host, in a container, or in CI. + +--- + +## Prerequisites + +- **Measurement scripts** (M1–M5) require **Bazel** and must run inside + a `-build` container where the repo is mounted at `/ovms`. +- **M2 and M5** additionally require a prior successful + `bazel build //src:ovms` so that generated headers (`.pb.h` etc.) + and external repos are present. Without this, many compile actions + will fail during measurement. +- **All scripts** use only Python 3 standard library — no virtual + environment or third-party packages are needed. +- The comparison script (`compare_build_metrics.py`) has no Bazel + dependency and runs anywhere with Python 3. + +--- + +## Usage + +### Option A — Makefile targets (recommended) + +Run all 5 metrics inside an existing `-build` container. By default, +CSVs are written to `tools/build_metrics/current/` which is committed +to the repository — after running, `git diff` shows exactly what changed. + +```bash +# Measure (writes to tools/build_metrics/current/ by default) +make build_metrics BUILD_CONTAINER=u24a_ovms1 + +# Compare current vs pre-optimization baseline +make build_metrics_compare + +# See per-file changes in git +git diff tools/build_metrics/current/ +``` + +You can override the output directory if needed: +```bash +make build_metrics BUILD_CONTAINER=u24a_ovms1 METRICS_DIR=tools/build_metrics/my_branch +``` + +The `build_metrics` target: +1. Runs all 5 measurement scripts via `docker exec` +2. Writes all output CSVs directly to `$(METRICS_DIR)/` (bind-mounted) +3. Filters TU and headers CSVs to `src/` rows only (`tu_src.csv`, `headers_src.csv`) + +### Option B — Run manually inside the build container + +```bash +# Inside the -build container, repo mounted at /ovms +cd /ovms + +# M1: Dependency fan-in +python3 tools/build_metrics/measure_dep_fanin.py deps.csv + +# M2: Preprocessed TU sizes (~5-30 min) +python3 tools/build_metrics/measure_tu_sizes.py tu.csv '//src:ovms' + +# M3+M4: Transitive source files + change impact (~2 min) +python3 tools/build_metrics/measure_build_graph.py trans_srcs.csv impact.csv + +# M5: Header fan-in (~10 min) +python3 tools/build_metrics/measure_header_fanin.py headers.csv '//src:ovms' + +# Filter TU to src/ rows only +head -1 tu.csv > tu_src.csv +grep '^src/' tu.csv >> tu_src.csv + +# Compare +python3 tools/build_metrics/compare_build_metrics.py \ + --deps-before deps_before.csv --deps-after deps.csv \ + --tu-before tu_before_src.csv --tu-after tu_src.csv \ + --trans-srcs-before trans_srcs_before.csv --trans-srcs-after trans_srcs.csv \ + --impact-before impact_before.csv --impact-after impact.csv \ + --headers-before headers_before.csv --headers-after headers.csv \ + --scopes all,non-test +``` + +### Option C — Drive from host via docker exec (bind-mounted repo) + +```bash +CONTAINER=u24a_ovms1 +OUT=tools/build_metrics/my_branch +mkdir -p $OUT + +# M1 +docker exec $CONTAINER bash -c \ + "cd /ovms && python3 tools/build_metrics/measure_dep_fanin.py /ovms/$OUT/deps.csv" + +# M2 +docker exec $CONTAINER bash -c \ + "cd /ovms && python3 tools/build_metrics/measure_tu_sizes.py /ovms/$OUT/tu.csv '//src:ovms'" + +# M3+M4 +docker exec $CONTAINER bash -c \ + "cd /ovms && python3 tools/build_metrics/measure_build_graph.py /ovms/$OUT/trans_srcs.csv /ovms/$OUT/impact.csv" + +# M5 +docker exec $CONTAINER bash -c \ + "cd /ovms && python3 tools/build_metrics/measure_header_fanin.py /ovms/$OUT/headers.csv '//src:ovms'" + +# Filter to src/ rows only +head -1 $OUT/tu.csv > $OUT/tu_src.csv +grep '^src/' $OUT/tu.csv >> $OUT/tu_src.csv || true +head -1 $OUT/headers.csv > $OUT/headers_src.csv +grep '^src/' $OUT/headers.csv >> $OUT/headers_src.csv || true + +python3 tools/build_metrics/compare_build_metrics.py \ + --deps-before baseline/deps.csv --deps-after $OUT/deps.csv \ + --tu-before baseline/tu_src.csv --tu-after $OUT/tu_src.csv \ + --trans-srcs-before baseline/trans_srcs.csv --trans-srcs-after $OUT/trans_srcs.csv \ + --impact-before baseline/impact.csv --impact-after $OUT/impact.csv \ + --headers-before baseline/headers_src.csv --headers-after $OUT/headers_src.csv \ + --scopes all,non-test +``` + +### Option D — Compare only (no rebuild needed) + +If you already have before/after CSVs, comparison runs on any machine +with Python 3: + +```bash +# Point to two directories — auto-resolves all CSV filenames +python3 tools/build_metrics/compare_build_metrics.py \ + --before-dir tools/build_metrics/prebuild_baseline \ + --after-dir tools/build_metrics/current \ + --scopes all,non-test,test + +# Or specify individual files (any subset works) +python3 tools/build_metrics/compare_build_metrics.py \ + --trans-srcs-before before/trans_srcs.csv \ + --trans-srcs-after after/trans_srcs.csv \ + --scopes non-test +``` + +--- + +## Committed CSVs and git-diff workflow + +Two sets of CSVs are committed in the repository: + +| Directory | Contents | +|-----------|----------| +| `tools/build_metrics/current/` | Latest metrics for the current branch. Overwritten by `make build_metrics`. | +| `tools/build_metrics/prebuild_baseline/` | Pre-optimization snapshot (commit `d1ff1c104`, main before build optimizations). | + +After running `make build_metrics`, use `git diff tools/build_metrics/current/` +to see per-file metric changes. Commit the updated CSVs with your PR so +reviewers can see the impact. + +To create a new baseline on a different branch: + +```bash +make build_metrics BUILD_CONTAINER=u24a_ovms_ref METRICS_DIR=tools/build_metrics/new_baseline +``` + +--- + +## Interpreting the outputs + +**Key insight:** Clean build time is often unchanged by refactoring, but +**incremental builds are where developers feel the impact** — in local +edit-test cycles, precommit checks, and CI pipelines that reuse caches. + +| Metric | What improving it means | +|--------|------------------------| +| **M1 (dep fan-in)** | Fewer Bazel targets in the transitive closure → more granular graph, better incremental invalidation. | +| **M2 (PP lines)** | Smaller translation units → less parsing work per compile, faster frontend. | +| **M3 (trans source files)** | Fewer real `.cpp` files in the transitive closure → same benefit as M1 but immune to target-split artifacts. | +| **M4 (change impact)** | Smaller blast radius → editing a file triggers fewer recompiles across the project. | +| **M5 (header fan-in)** | Fewer unique headers per TU → less include-chain complexity, faster preprocessing, less invalidation surface. | + +For incremental build verification, measure recompilation time after a +single-file change. For absolute clean-build impact, verify with Bazel +timing or profile output. + +--- + +## Sample Output + +### `make build_metrics` — per-metric console output + +Each measurement script prints a summary to stdout. Example excerpts: + +**M1 (Dependency Fan-In):** +``` +=== Summary === +Files: 318 +Unique targets: 236 +Avg total deps/file: 60.2 +Avg internal deps: 42.9 +Median total deps: 22 +Max total deps: 327 (src/test/openvino_remote_tensors_tests.cpp) + +Distribution: + 37 files with >200 deps + 5 files with 101-200 deps + 41 files with 51-100 deps + 80 files with 21-50 deps + 155 files with 0-20 deps +``` + +**M2 (Preprocessed TU Size):** +``` +=== Summary === +Files measured: 4037 +Total PP lines: 312,083,910 +Average PP lines: 77,305 +Max PP lines: 282,053 (src/server.cpp) + +Top 10 largest translation units: + src/server.cpp 282,053 lines 11,263 KB + src/capi_frontend/capi.cpp 281,468 lines 11,412 KB + src/prediction_service.cpp 275,939 lines 11,124 KB + ... +``` + +**M3+M4 (Transitive Source Files + Change Impact):** +``` +=== Summary: Transitive Source Files === + Files: 409 + Average: 116.6 + Max: 379 + +=== Summary: Change Impact === + Files: 409 + Average: 116.6 + Max: 349 + + Top 10 by change impact: + src/logging.cpp 349 impacted (199 rdep targets) + src/stringutils.cpp 309 impacted (162 rdep targets) + src/status.cpp 306 impacted (160 rdep targets) + ... +``` + +**M5 (Header Fan-In):** +``` +=== Summary === +Files measured: 4061 +Avg unique headers: 396 +Max unique headers: 2183 + +Top 10 files by unique header count: + src/filesystem/filesystemfactory.cpp 2183 headers (11 project) + src/filesystem/azurefilesystem.cpp 1568 headers (8 project) + src/server.cpp 1350 headers (54 project) + ... +``` + +### `make build_metrics_compare` — comparison report + +The compare tool prints a structured report per metric and scope. Example excerpt (non-test scope): + +``` +================================================================================ + METRIC 1: Dependency Fan-in per Source File [Non-Test Files] +================================================================================ + + Headline Metrics: + Before After Change + ------------------------------------------------------------------------ + Files measured 249 261 + Average total deps/file 57.5 42.8 -25.5% + Median total deps 18 18 + Max total deps 290 327 + + Top 10 Dependency Reductions: + File Before After Change + ---------------------------------------------------------------------------- + src/customloaders.cpp 282 14 -268 + src/global_sequences_viewer.cpp 282 23 -259 + src/cleaner_utils.cpp 282 25 -257 + ... + +================================================================================ + VERDICT [Non-Test Files] +================================================================================ + + [IMPROVED] Dependency fan-in reduced by 25.5% on average + [IMPROVED] High-dep files (>100): 34 -> 19 (-15) + [IMPROVED] Total preprocessed lines reduced by 18.9% + [IMPROVED] Trans source files reduced by 32.7% on average + [IMPROVED] Change impact reduced by 11.1% on average + [REGRESSED] Header fan-in increased by 2.9% on average +``` + +The full report includes all 5 metrics × all requested scopes (all, non-test, test), with distribution buckets, top 10 reductions, and top 10 worst remaining files per metric. + +--- + +## Notes + +- **M5 failures:** Header fan-in measurement requires all generated + headers to exist. If `bazel build //src:ovms` has not been run, many + compile actions will fail (the script reports the failure count). + Always build the target first. + +- **Approximate timings:** + - M1: ~1–2 min + - M2: ~5–30 min (depends on file count) + - M3+M4: ~2 min + +--- + +## Recommended KPIs for Comparing Iterations + +For each optimization batch, keep the same baseline and compare. + +**Primary KPIs:** +- M1: Average total deps/file, files with >100 deps +- M2: Total PP lines, average PP lines/file +- M3: Average transitive source files/TU +- M4: Average impacted sources/file + +**Secondary KPIs:** +- M5: Average unique headers/file, average project headers/file +- P90/P95 deps and PP lines +- Top 10 reductions and top 10 worst remaining per metric + - M5: ~10 min \ No newline at end of file diff --git a/tools/build_metrics/compare_build_metrics.py b/tools/build_metrics/compare_build_metrics.py new file mode 100644 index 0000000000..51f4eec95d --- /dev/null +++ b/tools/build_metrics/compare_build_metrics.py @@ -0,0 +1,923 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +Compare before/after build metrics and produce a comprehensive report. + +Supports two types of CSV inputs: + - Dependency metrics (from measure_deps.sh): file,target,...,total_deps + - TU size metrics (from measure_tu_sizes.py): file,pp_lines,pp_bytes + +Usage: + python3 tools/compare_build_metrics.py \\ + --deps-before deps_before.csv --deps-after deps_after.csv \\ + --tu-before tu_before.csv --tu-after tu_after.csv + + All flags are optional — you can compare deps only, TU only, or both. +""" + +import argparse +import csv +import sys +from collections import defaultdict + + +def load_deps_csv(path): + """Load deps CSV → {file: {target, internal_deps, ..., total_deps}}. + When a file appears in multiple targets, keep the entry with the + MINIMUM non-zero total_deps (smallest real target). Zero-dep entries + from config variants are ignored unless all entries are zero.""" + data = {} + with open(path) as f: + reader = csv.DictReader(f) + for row in reader: + entry = { + "target": row["target"], + "internal_deps": int(row["internal_deps"]), + "openvino": int(row["openvino"]), + "genai": int(row["genai"]), + "tensorflow": int(row["tensorflow"]), + "mediapipe": int(row["mediapipe"]), + "grpc": int(row["grpc"]), + "protobuf": int(row["protobuf"]), + "other_external": int(row["other_external"]), + "total_deps": int(row["total_deps"]), + } + fname = row["file"] + if fname not in data: + data[fname] = entry + else: + existing = data[fname]["total_deps"] + new = entry["total_deps"] + # Prefer non-zero minimum; skip bogus 0-dep entries + if existing == 0 and new > 0: + data[fname] = entry + elif new > 0 and new < existing: + data[fname] = entry + return data + + +def load_tu_csv(path): + """Load TU sizes CSV → {file: {pp_lines, pp_bytes}}""" + data = {} + with open(path) as f: + reader = csv.DictReader(f) + for row in reader: + data[row["file"]] = { + "pp_lines": int(row["pp_lines"]), + "pp_bytes": int(row["pp_bytes"]), + } + return data + + +def load_trans_srcs_csv(path): + """Load transitive source files CSV → {file: {target, trans_src_count}}""" + data = {} + with open(path) as f: + reader = csv.DictReader(f) + for row in reader: + entry = { + "target": row["target"], + "trans_src_count": int(row["trans_src_count"]), + } + fname = row["file"] + if fname not in data: + data[fname] = entry + else: + # Keep minimum non-zero count (smallest real target) + existing = data[fname]["trans_src_count"] + new = entry["trans_src_count"] + if existing == 0 and new > 0: + data[fname] = entry + elif new > 0 and new < existing: + data[fname] = entry + return data + + +def load_impact_csv(path): + """Load change impact CSV → {file: {target, rdep_targets, impacted_srcs}}""" + data = {} + with open(path) as f: + reader = csv.DictReader(f) + for row in reader: + entry = { + "target": row["target"], + "rdep_targets": int(row["rdep_targets"]), + "impacted_srcs": int(row["impacted_srcs"]), + } + fname = row["file"] + if fname not in data: + data[fname] = entry + else: + # Keep max impact (worst case per file) + if entry["impacted_srcs"] > data[fname]["impacted_srcs"]: + data[fname] = entry + return data + + +def load_headers_csv(path): + """Load header fan-in CSV → {file: {unique_headers, unique_project_headers}}""" + data = {} + with open(path) as f: + reader = csv.DictReader(f) + for row in reader: + data[row["file"]] = { + "unique_headers": int(row["unique_headers"]), + "unique_project_headers": int(row["unique_project_headers"]), + } + return data + + +def percentile(sorted_values, p): + """Compute the p-th percentile of a sorted list.""" + if not sorted_values: + return 0 + k = (len(sorted_values) - 1) * p / 100 + f = int(k) + c = f + 1 if f + 1 < len(sorted_values) else f + d = k - f + return sorted_values[f] + d * (sorted_values[c] - sorted_values[f]) + + +def pct_change(before, after): + """Format percentage change string.""" + if before == 0: + return "N/A" + pct = (after - before) / before * 100 + return f"{pct:+.1f}%" + + +def fmt_count(n): + return f"{n:,}" + + +def print_section(title): + print() + print("=" * 80) + print(f" {title}") + print("=" * 80) + + +def is_test_file(path): + return path.startswith("src/test/") + + +def filter_by_scope(data, scope): + if data is None: + return None + if scope == "all": + return data + if scope == "non-test": + return {k: v for k, v in data.items() if not is_test_file(k)} + if scope == "test": + return {k: v for k, v in data.items() if is_test_file(k)} + raise ValueError(f"Unknown scope: {scope}") + + +def scope_label(scope): + if scope == "all": + return "All Files" + if scope == "non-test": + return "Non-Test Files" + if scope == "test": + return "Test Files" + return scope + + +def format_bucket_label(lower, upper, suffix=""): + if upper is None: + return f">={lower}{suffix}" + return f"{lower}-{upper}{suffix}" + + +def count_bucket(values, lower, upper): + if upper is None: + return sum(1 for value in values if value >= lower) + return sum(1 for value in values if lower <= value <= upper) + + +def print_bucket_table(title, before_vals, after_vals, buckets, suffix=""): + print() + print(f" {title}:") + print(f" {'Bucket':<24s} {'Before':>10s} {'After':>10s} {'Change':>10s}") + print(f" {'-'*58}") + for lower, upper in buckets: + before_count = count_bucket(before_vals, lower, upper) + after_count = count_bucket(after_vals, lower, upper) + delta = after_count - before_count + label = format_bucket_label(lower, upper, suffix) + print(f" {label:<24s} {before_count:>10} {after_count:>10} {delta:>+10}") + + +def compare_deps(before, after, label=""): + """Compare dependency metrics and print report.""" + title = "METRIC 1: Dependency Fan-in per Source File" + if label: + title += f" [{label}]" + print_section(title) + + all_files = sorted(set(before.keys()) | set(after.keys())) + common_files = sorted(set(before.keys()) & set(after.keys())) + + # Extract total_deps values + before_vals = sorted(d["total_deps"] for d in before.values()) + after_vals = sorted(d["total_deps"] for d in after.values()) + + before_avg = sum(before_vals) / len(before_vals) if before_vals else 0 + after_avg = sum(after_vals) / len(after_vals) if after_vals else 0 + + before_internal = sorted(d["internal_deps"] for d in before.values()) + after_internal = sorted(d["internal_deps"] for d in after.values()) + before_int_avg = sum(before_internal) / len(before_internal) if before_internal else 0 + after_int_avg = sum(after_internal) / len(after_internal) if after_internal else 0 + + # --- Headline metrics --- + print() + print(" Headline Metrics:") + print(f" {'':40s} {'Before':>10s} {'After':>10s} {'Change':>10s}") + print(f" {'-'*72}") + print(f" {'Files measured':<40s} {len(before_vals):>10,} {len(after_vals):>10,}") + print(f" {'Average total deps/file':<40s} {before_avg:>10.1f} {after_avg:>10.1f} {pct_change(before_avg, after_avg):>10s}") + print(f" {'Average internal deps/file':<40s} {before_int_avg:>10.1f} {after_int_avg:>10.1f} {pct_change(before_int_avg, after_int_avg):>10s}") + print(f" {'Median total deps':<40s} {percentile(before_vals, 50):>10.0f} {percentile(after_vals, 50):>10.0f}") + print(f" {'P90 total deps':<40s} {percentile(before_vals, 90):>10.0f} {percentile(after_vals, 90):>10.0f}") + print(f" {'P95 total deps':<40s} {percentile(before_vals, 95):>10.0f} {percentile(after_vals, 95):>10.0f}") + print(f" {'Max total deps':<40s} {max(before_vals) if before_vals else 0:>10} {max(after_vals) if after_vals else 0:>10}") + + # --- Bucket distribution --- + dep_buckets = [ + (0, 10), + (11, 20), + (21, 30), + (31, 40), + (41, 50), + (51, 60), + (61, 70), + (71, 80), + (81, 90), + (91, 100), + (101, 200), + (201, None), + ] + print_bucket_table( + "Dependency Distribution Buckets", + before_vals, + after_vals, + dep_buckets, + suffix=" deps", + ) + + # --- Per-file changes (top improvements) --- + changes = [] + for f in common_files: + b = before[f]["total_deps"] + a = after[f]["total_deps"] + if b != a: + changes.append((f, b, a, a - b)) + + if changes: + changes.sort(key=lambda x: x[3]) # Most improved first + print() + print(" Top 10 Dependency Reductions:") + print(f" {'File':<50s} {'Before':>8s} {'After':>8s} {'Change':>8s}") + print(f" {'-'*76}") + for f, b, a, d in changes[:10]: + name = f if len(f) <= 50 else "..." + f[-47:] + print(f" {name:<50s} {b:>8} {a:>8} {d:>+8}") + + # Worst remaining + worst = sorted( + [(f, after[f]["total_deps"]) for f in after], + key=lambda x: -x[1] + )[:10] + print() + print(" Top 10 Remaining Highest-Dep Files (after):") + print(f" {'File':<50s} {'Deps':>8s} {'Target':<30s}") + print(f" {'-'*90}") + for f, d in worst: + target = after[f]["target"] + name = f if len(f) <= 50 else "..." + f[-47:] + tgt = target if len(target) <= 30 else "..." + target[-27:] + print(f" {name:<50s} {d:>8} {tgt:<30s}") + + # --- Unique targets analysis --- + before_targets = set(d["target"] for d in before.values()) + after_targets = set(d["target"] for d in after.values()) + print() + print(f" Unique targets containing source files:") + print(f" Before: {len(before_targets)}") + print(f" After: {len(after_targets)}") + if len(after_targets) > len(before_targets): + print(f" (+{len(after_targets) - len(before_targets)} new targets = more granular build graph)") + + +def compare_tu(before, after, label=""): + """Compare translation unit size metrics and print report.""" + title = "METRIC 2: Translation Unit Sizes (Preprocessed)" + if label: + title += f" [{label}]" + print_section(title) + + common_files = sorted(set(before.keys()) & set(after.keys())) + + before_lines = sorted(d["pp_lines"] for d in before.values()) + after_lines = sorted(d["pp_lines"] for d in after.values()) + + before_total = sum(before_lines) + after_total = sum(after_lines) + before_avg = before_total / len(before_lines) if before_lines else 0 + after_avg = after_total / len(after_lines) if after_lines else 0 + + before_bytes = sum(d["pp_bytes"] for d in before.values()) + after_bytes = sum(d["pp_bytes"] for d in after.values()) + + # --- Headline metrics --- + print() + print(" Headline Metrics:") + print(f" {'':40s} {'Before':>12s} {'After':>12s} {'Change':>10s}") + print(f" {'-'*76}") + print(f" {'Files measured':<40s} {len(before_lines):>12,} {len(after_lines):>12,}") + print(f" {'Total PP lines':<40s} {before_total:>12,} {after_total:>12,} {pct_change(before_total, after_total):>10s}") + print(f" {'Total PP size (MB)':<40s} {before_bytes/1024/1024:>12.1f} {after_bytes/1024/1024:>12.1f} {pct_change(before_bytes, after_bytes):>10s}") + print(f" {'Average PP lines/file':<40s} {before_avg:>12,.0f} {after_avg:>12,.0f} {pct_change(before_avg, after_avg):>10s}") + print(f" {'Median PP lines':<40s} {percentile(before_lines, 50):>12,.0f} {percentile(after_lines, 50):>12,.0f}") + print(f" {'P90 PP lines':<40s} {percentile(before_lines, 90):>12,.0f} {percentile(after_lines, 90):>12,.0f}") + print(f" {'Max PP lines':<40s} {max(before_lines) if before_lines else 0:>12,} {max(after_lines) if after_lines else 0:>12,}") + + # --- Bucket distribution --- + pp_buckets = [ + (0, 10000), + (10001, 25000), + (25001, 50000), + (50001, 100000), + (100001, 200000), + (200001, 300000), + (300001, None), + ] + print_bucket_table( + "PP Line Distribution Buckets", + before_lines, + after_lines, + pp_buckets, + suffix="", + ) + + # --- Per-file changes --- + changes = [] + for f in common_files: + b = before[f]["pp_lines"] + a = after[f]["pp_lines"] + if b > 0 and abs(a - b) > max(100, b * 0.01): + changes.append((f, b, a, a - b)) + + if changes: + changes.sort(key=lambda x: x[3]) # Most reduced first + print() + print(" Top 10 TU Size Reductions:") + print(f" {'File':<50s} {'Before':>10s} {'After':>10s} {'Change':>10s} {'Pct':>8s}") + print(f" {'-'*80}") + for f, b, a, d in changes[:10]: + name = f if len(f) <= 50 else "..." + f[-47:] + print(f" {name:<50s} {b:>10,} {a:>10,} {d:>+10,} {pct_change(b, a):>8s}") + + # Top regressions (if any) + regressions = [c for c in changes if c[3] > 0] + if regressions: + regressions.sort(key=lambda x: -x[3]) + print() + print(" Top 5 TU Size Regressions (if any):") + print(f" {'File':<50s} {'Before':>10s} {'After':>10s} {'Change':>10s}") + print(f" {'-'*80}") + for f, b, a, d in regressions[:5]: + name = f if len(f) <= 50 else "..." + f[-47:] + print(f" {name:<50s} {b:>10,} {a:>10,} {d:>+10,}") + + # Largest remaining TUs + worst = sorted(after.items(), key=lambda x: -x[1]["pp_lines"])[:10] + print() + print(" Top 10 Largest TUs (after):") + print(f" {'File':<55s} {'PP Lines':>10s} {'PP KB':>10s}") + print(f" {'-'*76}") + for f, d in worst: + name = f if len(f) <= 55 else "..." + f[-52:] + print(f" {name:<55s} {d['pp_lines']:>10,} {d['pp_bytes']/1024:>10,.0f}") + + +def compare_trans_srcs(before, after, label=""): + """Compare transitive source file counts and print report.""" + title = "METRIC 3: Transitive Source Files per TU" + if label: + title += f" [{label}]" + print_section(title) + + common_files = sorted(set(before.keys()) & set(after.keys())) + + before_vals = sorted(d["trans_src_count"] for d in before.values()) + after_vals = sorted(d["trans_src_count"] for d in after.values()) + + before_avg = sum(before_vals) / len(before_vals) if before_vals else 0 + after_avg = sum(after_vals) / len(after_vals) if after_vals else 0 + + # --- Headline metrics --- + print() + print(" Headline Metrics:") + print(f" {'':40s} {'Before':>10s} {'After':>10s} {'Change':>10s}") + print(f" {'-'*72}") + print(f" {'Files measured':<40s} {len(before_vals):>10,} {len(after_vals):>10,}") + print(f" {'Average trans src files/TU':<40s} {before_avg:>10.1f} {after_avg:>10.1f} {pct_change(before_avg, after_avg):>10s}") + print(f" {'Median trans src files':<40s} {percentile(before_vals, 50):>10.0f} {percentile(after_vals, 50):>10.0f}") + print(f" {'P90 trans src files':<40s} {percentile(before_vals, 90):>10.0f} {percentile(after_vals, 90):>10.0f}") + print(f" {'Max trans src files':<40s} {max(before_vals) if before_vals else 0:>10} {max(after_vals) if after_vals else 0:>10}") + + # --- Bucket distribution --- + trans_buckets = [ + (0, 20), + (21, 50), + (51, 100), + (101, 200), + (201, 500), + (501, None), + ] + print_bucket_table( + "Trans Source Files Distribution", + before_vals, + after_vals, + trans_buckets, + suffix=" srcs", + ) + + # --- Per-file changes --- + changes = [] + for f in common_files: + b = before[f]["trans_src_count"] + a = after[f]["trans_src_count"] + if b != a: + changes.append((f, b, a, a - b)) + + if changes: + changes.sort(key=lambda x: x[3]) + print() + print(" Top 10 Trans Src Reductions:") + print(f" {'File':<50s} {'Before':>8s} {'After':>8s} {'Change':>8s}") + print(f" {'-'*76}") + for f, b, a, d in changes[:10]: + name = f if len(f) <= 50 else "..." + f[-47:] + print(f" {name:<50s} {b:>8} {a:>8} {d:>+8}") + + # Largest remaining + worst = sorted(after.items(), key=lambda x: -x[1]["trans_src_count"])[:10] + print() + print(" Top 10 Largest Trans Src Counts (after):") + print(f" {'File':<50s} {'Count':>8s} {'Target':<30s}") + print(f" {'-'*90}") + for f, d in worst: + name = f if len(f) <= 50 else "..." + f[-47:] + tgt = d["target"] + tgt = tgt if len(tgt) <= 30 else "..." + tgt[-27:] + print(f" {name:<50s} {d['trans_src_count']:>8} {tgt:<30s}") + + +def compare_impact(before, after, label=""): + """Compare change impact metrics and print report.""" + title = "METRIC 4: Change Impact (Reverse Deps)" + if label: + title += f" [{label}]" + print_section(title) + + common_files = sorted(set(before.keys()) & set(after.keys())) + + before_vals = sorted(d["impacted_srcs"] for d in before.values()) + after_vals = sorted(d["impacted_srcs"] for d in after.values()) + + before_avg = sum(before_vals) / len(before_vals) if before_vals else 0 + after_avg = sum(after_vals) / len(after_vals) if after_vals else 0 + + before_rdeps = sorted(d["rdep_targets"] for d in before.values()) + after_rdeps = sorted(d["rdep_targets"] for d in after.values()) + before_rdep_avg = sum(before_rdeps) / len(before_rdeps) if before_rdeps else 0 + after_rdep_avg = sum(after_rdeps) / len(after_rdeps) if after_rdeps else 0 + + # --- Headline metrics --- + print() + print(" Headline Metrics:") + print(f" {'':40s} {'Before':>10s} {'After':>10s} {'Change':>10s}") + print(f" {'-'*72}") + print(f" {'Files measured':<40s} {len(before_vals):>10,} {len(after_vals):>10,}") + print(f" {'Average impacted srcs/file':<40s} {before_avg:>10.1f} {after_avg:>10.1f} {pct_change(before_avg, after_avg):>10s}") + print(f" {'Average rdep targets/file':<40s} {before_rdep_avg:>10.1f} {after_rdep_avg:>10.1f} {pct_change(before_rdep_avg, after_rdep_avg):>10s}") + print(f" {'Median impacted srcs':<40s} {percentile(before_vals, 50):>10.0f} {percentile(after_vals, 50):>10.0f}") + print(f" {'P90 impacted srcs':<40s} {percentile(before_vals, 90):>10.0f} {percentile(after_vals, 90):>10.0f}") + print(f" {'Max impacted srcs':<40s} {max(before_vals) if before_vals else 0:>10} {max(after_vals) if after_vals else 0:>10}") + + # --- Bucket distribution --- + impact_buckets = [ + (0, 50), + (51, 100), + (101, 200), + (201, 500), + (501, None), + ] + print_bucket_table( + "Change Impact Distribution", + before_vals, + after_vals, + impact_buckets, + suffix=" srcs", + ) + + # --- Per-file changes --- + changes = [] + for f in common_files: + b = before[f]["impacted_srcs"] + a = after[f]["impacted_srcs"] + if b != a: + changes.append((f, b, a, a - b)) + + if changes: + changes.sort(key=lambda x: x[3]) + print() + print(" Top 10 Impact Reductions:") + print(f" {'File':<50s} {'Before':>8s} {'After':>8s} {'Change':>8s}") + print(f" {'-'*76}") + for f, b, a, d in changes[:10]: + name = f if len(f) <= 50 else "..." + f[-47:] + print(f" {name:<50s} {b:>8} {a:>8} {d:>+8}") + + # Largest remaining + worst = sorted(after.items(), key=lambda x: -x[1]["impacted_srcs"])[:10] + print() + print(" Top 10 Largest Change Impact (after):") + print(f" {'File':<50s} {'Impact':>8s} {'Rdeps':>8s} {'Target':<25s}") + print(f" {'-'*93}") + for f, d in worst: + name = f if len(f) <= 50 else "..." + f[-47:] + tgt = d["target"] + tgt = tgt if len(tgt) <= 25 else "..." + tgt[-22:] + print(f" {name:<50s} {d['impacted_srcs']:>8} {d['rdep_targets']:>8} {tgt:<25s}") + + +def compare_headers(before, after, label=""): + """Compare header fan-in metrics and print report.""" + title = "METRIC 5: Header Fan-in per TU" + if label: + title += f" [{label}]" + print_section(title) + + common_files = sorted(set(before.keys()) & set(after.keys())) + + before_vals = sorted(d["unique_headers"] for d in before.values()) + after_vals = sorted(d["unique_headers"] for d in after.values()) + + before_avg = sum(before_vals) / len(before_vals) if before_vals else 0 + after_avg = sum(after_vals) / len(after_vals) if after_vals else 0 + + before_proj = sorted(d["unique_project_headers"] for d in before.values()) + after_proj = sorted(d["unique_project_headers"] for d in after.values()) + before_proj_avg = sum(before_proj) / len(before_proj) if before_proj else 0 + after_proj_avg = sum(after_proj) / len(after_proj) if after_proj else 0 + + # --- Headline metrics --- + print() + print(" Headline Metrics:") + print(f" {'':40s} {'Before':>10s} {'After':>10s} {'Change':>10s}") + print(f" {'-'*72}") + print(f" {'Files measured':<40s} {len(before_vals):>10,} {len(after_vals):>10,}") + print(f" {'Average unique headers/file':<40s} {before_avg:>10.1f} {after_avg:>10.1f} {pct_change(before_avg, after_avg):>10s}") + print(f" {'Average project headers/file':<40s} {before_proj_avg:>10.1f} {after_proj_avg:>10.1f} {pct_change(before_proj_avg, after_proj_avg):>10s}") + print(f" {'Median unique headers':<40s} {percentile(before_vals, 50):>10.0f} {percentile(after_vals, 50):>10.0f}") + print(f" {'P90 unique headers':<40s} {percentile(before_vals, 90):>10.0f} {percentile(after_vals, 90):>10.0f}") + print(f" {'Max unique headers':<40s} {max(before_vals) if before_vals else 0:>10} {max(after_vals) if after_vals else 0:>10}") + + # --- Bucket distribution --- + header_buckets = [ + (0, 100), + (101, 200), + (201, 500), + (501, 1000), + (1001, 2000), + (2001, None), + ] + print_bucket_table( + "Unique Headers Distribution", + before_vals, + after_vals, + header_buckets, + suffix="", + ) + + # --- Per-file changes --- + changes = [] + for f in common_files: + b = before[f]["unique_headers"] + a = after[f]["unique_headers"] + if b != a and abs(a - b) > max(5, b * 0.02): + changes.append((f, b, a, a - b)) + + if changes: + changes.sort(key=lambda x: x[3]) + print() + print(" Top 10 Header Count Reductions:") + print(f" {'File':<50s} {'Before':>8s} {'After':>8s} {'Change':>8s} {'Pct':>8s}") + print(f" {'-'*78}") + for f, b, a, d in changes[:10]: + name = f if len(f) <= 50 else "..." + f[-47:] + print(f" {name:<50s} {b:>8} {a:>8} {d:>+8} {pct_change(b, a):>8s}") + + # Largest remaining + worst = sorted(after.items(), key=lambda x: -x[1]["unique_headers"])[:10] + print() + print(" Top 10 Highest Header Fan-in (after):") + print(f" {'File':<55s} {'Total':>8s} {'Project':>8s}") + print(f" {'-'*73}") + for f, d in worst: + name = f if len(f) <= 55 else "..." + f[-52:] + print(f" {name:<55s} {d['unique_headers']:>8} {d['unique_project_headers']:>8}") + + +def print_verdict(deps_before, deps_after, tu_before, tu_after, label="", + trans_before=None, trans_after=None, + impact_before=None, impact_after=None, + headers_before=None, headers_after=None): + """Print overall verdict.""" + title = "VERDICT" + if label: + title += f" [{label}]" + print_section(title) + print() + + verdicts = [] + + if deps_before and deps_after: + b_avg = sum(d["total_deps"] for d in deps_before.values()) / len(deps_before) + a_avg = sum(d["total_deps"] for d in deps_after.values()) / len(deps_after) + if a_avg < b_avg: + pct = (b_avg - a_avg) / b_avg * 100 + verdicts.append(f" [IMPROVED] Dependency fan-in reduced by {pct:.1f}% on average") + elif a_avg > b_avg: + pct = (a_avg - b_avg) / b_avg * 100 + verdicts.append(f" [REGRESSED] Dependency fan-in increased by {pct:.1f}% on average") + else: + verdicts.append(f" [UNCHANGED] Dependency fan-in unchanged") + + # Count files above high threshold + b_high = sum(1 for d in deps_before.values() if d["total_deps"] > 100) + a_high = sum(1 for d in deps_after.values() if d["total_deps"] > 100) + if a_high < b_high: + verdicts.append(f" [IMPROVED] High-dep files (>100): {b_high} -> {a_high} (-{b_high - a_high})") + + if tu_before and tu_after: + b_total = sum(d["pp_lines"] for d in tu_before.values()) + a_total = sum(d["pp_lines"] for d in tu_after.values()) + if a_total < b_total: + pct = (b_total - a_total) / b_total * 100 + verdicts.append(f" [IMPROVED] Total preprocessed lines reduced by {pct:.1f}%") + elif a_total > b_total: + pct = (a_total - b_total) / b_total * 100 + verdicts.append(f" [REGRESSED] Total preprocessed lines increased by {pct:.1f}%") + else: + verdicts.append(f" [UNCHANGED] Total preprocessed lines unchanged") + + if trans_before and trans_after: + b_avg = sum(d["trans_src_count"] for d in trans_before.values()) / len(trans_before) + a_avg = sum(d["trans_src_count"] for d in trans_after.values()) / len(trans_after) + if a_avg < b_avg: + pct = (b_avg - a_avg) / b_avg * 100 + verdicts.append(f" [IMPROVED] Trans source files reduced by {pct:.1f}% on average") + elif a_avg > b_avg: + pct = (a_avg - b_avg) / b_avg * 100 + verdicts.append(f" [REGRESSED] Trans source files increased by {pct:.1f}% on average") + + if impact_before and impact_after: + b_avg = sum(d["impacted_srcs"] for d in impact_before.values()) / len(impact_before) + a_avg = sum(d["impacted_srcs"] for d in impact_after.values()) / len(impact_after) + if a_avg < b_avg: + pct = (b_avg - a_avg) / b_avg * 100 + verdicts.append(f" [IMPROVED] Change impact reduced by {pct:.1f}% on average") + elif a_avg > b_avg: + pct = (a_avg - b_avg) / b_avg * 100 + verdicts.append(f" [REGRESSED] Change impact increased by {pct:.1f}% on average") + + if headers_before and headers_after: + b_avg = sum(d["unique_headers"] for d in headers_before.values()) / len(headers_before) + a_avg = sum(d["unique_headers"] for d in headers_after.values()) / len(headers_after) + if a_avg < b_avg: + pct = (b_avg - a_avg) / b_avg * 100 + verdicts.append(f" [IMPROVED] Header fan-in reduced by {pct:.1f}% on average") + elif a_avg > b_avg: + pct = (a_avg - b_avg) / b_avg * 100 + verdicts.append(f" [REGRESSED] Header fan-in increased by {pct:.1f}% on average") + + for v in verdicts: + print(v) + print() + + +def main(): + parser = argparse.ArgumentParser( + description="Compare before/after build metrics.", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=""" +Examples: + # Compare deps only: + %(prog)s --deps-before deps_v1.csv --deps-after deps_v2.csv + + # Compare TU sizes only: + %(prog)s --tu-before tu_v1.csv --tu-after tu_v2.csv + + # Compare both: + %(prog)s --deps-before deps_v1.csv --deps-after deps_v2.csv \\ + --tu-before tu_v1.csv --tu-after tu_v2.csv + + # Compare all 5 metrics: + %(prog)s --deps-before deps_v1.csv --deps-after deps_v2.csv \\ + --tu-before tu_v1.csv --tu-after tu_v2.csv \\ + --trans-srcs-before trans_v1.csv --trans-srcs-after trans_v2.csv \\ + --impact-before impact_v1.csv --impact-after impact_v2.csv \\ + --headers-before headers_v1.csv --headers-after headers_v2.csv +""" + ) + parser.add_argument("--before-dir", + help="Directory with before CSVs (auto-resolves deps.csv, tu_src.csv, etc.)") + parser.add_argument("--after-dir", + help="Directory with after CSVs (auto-resolves deps.csv, tu_src.csv, etc.)") + parser.add_argument("--deps-before", help="Deps CSV from before changes") + parser.add_argument("--deps-after", help="Deps CSV from after changes") + parser.add_argument("--tu-before", help="TU sizes CSV from before changes") + parser.add_argument("--tu-after", help="TU sizes CSV from after changes") + parser.add_argument("--trans-srcs-before", help="Trans source files CSV from before") + parser.add_argument("--trans-srcs-after", help="Trans source files CSV from after") + parser.add_argument("--impact-before", help="Change impact CSV from before") + parser.add_argument("--impact-after", help="Change impact CSV from after") + parser.add_argument("--headers-before", help="Header fan-in CSV from before") + parser.add_argument("--headers-after", help="Header fan-in CSV from after") + parser.add_argument( + "--scopes", + default="all", + help=( + "Comma-separated file scopes to report: all,non-test,test. " + "Example: --scopes all,non-test,test" + ), + ) + args = parser.parse_args() + + # Resolve --before-dir / --after-dir to individual CSV paths + import os + DIR_FILE_MAP = { + "deps": ("deps_before", "deps_after", "deps.csv"), + "tu": ("tu_before", "tu_after", "tu_src.csv"), + "trans_srcs": ("trans_srcs_before", "trans_srcs_after", "trans_srcs.csv"), + "impact": ("impact_before", "impact_after", "impact.csv"), + "headers": ("headers_before", "headers_after", "headers_src.csv"), + } + for _metric, (before_attr, after_attr, filename) in DIR_FILE_MAP.items(): + if args.before_dir and not getattr(args, before_attr): + candidate = os.path.join(args.before_dir, filename) + if os.path.isfile(candidate): + setattr(args, before_attr, candidate) + if args.after_dir and not getattr(args, after_attr): + candidate = os.path.join(args.after_dir, filename) + if os.path.isfile(candidate): + setattr(args, after_attr, candidate) + + if not any([args.deps_before, args.tu_before, args.trans_srcs_before, + args.impact_before, args.headers_before]): + parser.error("At least one --*-before / --*-after pair is required.") + + deps_before = deps_after = tu_before = tu_after = None + trans_before = trans_after = impact_before = impact_after = None + headers_before = headers_after = None + + if args.deps_before and args.deps_after: + deps_before = load_deps_csv(args.deps_before) + deps_after = load_deps_csv(args.deps_after) + elif args.deps_before or args.deps_after: + print("WARNING: Need both --deps-before and --deps-after for comparison.", + file=sys.stderr) + + if args.tu_before and args.tu_after: + tu_before = load_tu_csv(args.tu_before) + tu_after = load_tu_csv(args.tu_after) + elif args.tu_before or args.tu_after: + print("WARNING: Need both --tu-before and --tu-after for comparison.", + file=sys.stderr) + + if args.trans_srcs_before and args.trans_srcs_after: + trans_before = load_trans_srcs_csv(args.trans_srcs_before) + trans_after = load_trans_srcs_csv(args.trans_srcs_after) + elif args.trans_srcs_before or args.trans_srcs_after: + print("WARNING: Need both --trans-srcs-before and --trans-srcs-after.", + file=sys.stderr) + + if args.impact_before and args.impact_after: + impact_before = load_impact_csv(args.impact_before) + impact_after = load_impact_csv(args.impact_after) + elif args.impact_before or args.impact_after: + print("WARNING: Need both --impact-before and --impact-after.", + file=sys.stderr) + + if args.headers_before and args.headers_after: + headers_before = load_headers_csv(args.headers_before) + headers_after = load_headers_csv(args.headers_after) + elif args.headers_before or args.headers_after: + print("WARNING: Need both --headers-before and --headers-after.", + file=sys.stderr) + + requested_scopes = [s.strip() for s in args.scopes.split(",") if s.strip()] + valid_scopes = {"all", "non-test", "test"} + invalid = [s for s in requested_scopes if s not in valid_scopes] + if invalid: + parser.error(f"Invalid scope(s): {', '.join(invalid)}. Valid scopes: all,non-test,test") + + # Remove duplicates while preserving order + seen = set() + scopes = [] + for s in requested_scopes: + if s not in seen: + scopes.append(s) + seen.add(s) + + for idx, scope in enumerate(scopes): + if idx > 0: + print() + + deps_b = filter_by_scope(deps_before, scope) if deps_before is not None else None + deps_a = filter_by_scope(deps_after, scope) if deps_after is not None else None + tu_b = filter_by_scope(tu_before, scope) if tu_before is not None else None + tu_a = filter_by_scope(tu_after, scope) if tu_after is not None else None + trans_b = filter_by_scope(trans_before, scope) if trans_before is not None else None + trans_a = filter_by_scope(trans_after, scope) if trans_after is not None else None + impact_b = filter_by_scope(impact_before, scope) if impact_before is not None else None + impact_a = filter_by_scope(impact_after, scope) if impact_after is not None else None + headers_b = filter_by_scope(headers_before, scope) if headers_before is not None else None + headers_a = filter_by_scope(headers_after, scope) if headers_after is not None else None + + label = scope_label(scope) + printed = False + + if deps_b is not None and deps_a is not None: + if deps_b and deps_a: + compare_deps(deps_b, deps_a, label) + printed = True + else: + print_section(f"METRIC 1: Dependency Fan-in per Source File [{label}]") + print("\n No dependency rows in this scope.") + printed = True + + if tu_b is not None and tu_a is not None: + if tu_b and tu_a: + compare_tu(tu_b, tu_a, label) + printed = True + else: + print_section(f"METRIC 2: Translation Unit Sizes (Preprocessed) [{label}]") + print("\n No TU rows in this scope.") + printed = True + + if trans_b is not None and trans_a is not None: + if trans_b and trans_a: + compare_trans_srcs(trans_b, trans_a, label) + printed = True + else: + print_section(f"METRIC 3: Transitive Source Files per TU [{label}]") + print("\n No trans source files rows in this scope.") + printed = True + + if impact_b is not None and impact_a is not None: + if impact_b and impact_a: + compare_impact(impact_b, impact_a, label) + printed = True + else: + print_section(f"METRIC 4: Change Impact (Reverse Deps) [{label}]") + print("\n No change impact rows in this scope.") + printed = True + + if headers_b is not None and headers_a is not None: + if headers_b and headers_a: + compare_headers(headers_b, headers_a, label) + printed = True + else: + print_section(f"METRIC 5: Header Fan-in per TU [{label}]") + print("\n No header fan-in rows in this scope.") + printed = True + + if printed: + print_verdict(deps_b, deps_a, tu_b, tu_a, label, + trans_before=trans_b, trans_after=trans_a, + impact_before=impact_b, impact_after=impact_a, + headers_before=headers_b, headers_after=headers_a) + + +if __name__ == "__main__": + main() diff --git a/tools/build_metrics/current/deps.csv b/tools/build_metrics/current/deps.csv new file mode 100644 index 0000000000..3adf3276c8 --- /dev/null +++ b/tools/build_metrics/current/deps.csv @@ -0,0 +1,319 @@ +file,target,internal_deps,openvino,genai,tensorflow,mediapipe,grpc,protobuf,other_external,total_deps +src/anonymous_input_name.cpp,//src:anonymous_input_name,0,0,0,0,0,0,0,0,0 +src/audio/audio_utils.cpp,//src/audio:audio_utils,3,0,0,0,0,0,0,5,8 +src/audio/speech_to_text/s2t_calculator.cc,//src/audio/speech_to_text:s2t_calculator,16,1,1,0,1,0,1,12,32 +src/audio/speech_to_text/s2t_calculator.pb.cc,//src/audio/speech_to_text:s2t_calculator_cc_proto,0,0,0,0,1,0,1,1,3 +src/audio/speech_to_text/s2t_calculator_options_lib.cc,//src/audio/speech_to_text:s2t_calculator_options_registry,1,0,0,0,1,0,1,8,11 +src/audio/speech_to_text/stt_node_initializer.cpp,//src/audio/speech_to_text:s2t_calculator,16,1,1,0,1,0,1,12,32 +src/audio/text_to_speech/t2s_calculator.cc,//src/audio/text_to_speech:t2s_calculator,16,1,1,0,1,0,1,12,32 +src/audio/text_to_speech/t2s_calculator.pb.cc,//src/audio/text_to_speech:t2s_calculator_cc_proto,0,0,0,0,1,0,1,1,3 +src/audio/text_to_speech/t2s_calculator_options_lib.cc,//src/audio/text_to_speech:t2s_calculator_options_registry,1,0,0,0,1,0,1,8,11 +src/audio/text_to_speech/t2s_servable.cpp,//src/audio/text_to_speech:t2s_servable,5,1,1,0,1,0,1,11,20 +src/audio/text_to_speech/tts_node_initializer.cpp,//src/audio/text_to_speech:t2s_calculator,16,1,1,0,1,0,1,12,32 +src/capi_frontend/buffer.cpp,//src:libovmscapibuffer,2,0,0,0,0,0,0,4,6 +src/capi_frontend/capi.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/capi_frontend/capi_backend_impls.cpp,//src:capi_backend_impl,71,1,0,0,0,0,0,9,81 +src/capi_frontend/capi_dag_utils.cpp,//src:capi_dag_utils,23,1,0,0,0,0,0,4,28 +src/capi_frontend/capi_request_utils.cpp,//src:capi_request_utils,22,1,0,0,0,0,0,4,27 +src/capi_frontend/capi_utils.cpp,//src:libovmscapi_utils,22,1,0,0,0,0,0,4,27 +src/capi_frontend/capi_validation.cpp,//src:capi_validation,28,1,0,0,0,0,0,5,34 +src/capi_frontend/capimodule.cpp,//src:capimodule,5,0,0,0,0,0,0,4,9 +src/capi_frontend/deserialization.cpp,//src:capi_deserialization,31,1,0,0,0,0,0,6,38 +src/capi_frontend/inferenceparameter.cpp,//src:capiinferenceparameter,17,1,0,0,0,0,0,4,22 +src/capi_frontend/inferencerequest.cpp,//src:inferencerequest,20,1,0,0,0,0,0,4,25 +src/capi_frontend/inferenceresponse.cpp,//src:inferenceresponse,20,1,0,0,0,0,0,4,25 +src/capi_frontend/inferencetensor.cpp,//src:inferencetensor,6,1,0,0,0,0,0,4,11 +src/capi_frontend/servablemetadata.cpp,//src:libovms_capi_servable_metadata,9,1,0,0,0,0,0,4,14 +src/capi_frontend/server_settings.cpp,//src:libovms_server_settings,1,0,0,0,0,0,0,0,1 +src/capi_frontend/tensor_conversion.cpp,//src:capi_backend_impl,71,1,0,0,0,0,0,9,81 +src/cleaner_utils.cpp,//src:cleaner_utils,19,1,0,0,0,0,0,5,25 +src/cli_parser.cpp,//src:libovms_cliparser,19,0,0,0,0,0,0,7,26 +src/color_format_configuration.cpp,//src:libovmscolor_format_configuration,3,1,0,0,0,0,0,4,8 +src/config.cpp,//src:libovms_config,31,1,0,0,0,0,0,7,39 +src/config_export_module/config_export.cpp,//src/config_export_module:config_export,10,0,0,0,0,0,0,6,16 +src/custom_nodes/add_one/add_one.cpp,//src:libcustom_node_add_one.so,2,0,0,0,0,0,0,0,2 +src/custom_nodes/common/buffersqueue.cpp,//src:custom_nodes_common_buffersqueue,1,0,0,0,0,0,0,0,1 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,//src:libcustom_node_add_one.so,2,0,0,0,0,0,0,0,2 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,//src:libcustom_node_model_zoo_intel_object_detection.so,3,0,0,0,0,0,0,1,4 +src/custom_nodes/east_ocr/east_ocr.cpp,//src:libcustom_node_east_ocr.so,1,0,0,0,0,0,0,1,2 +src/custom_nodes/face_blur/face_blur.cpp,//src:libcustom_node_face_blur.so,1,0,0,0,0,0,0,1,2 +src/custom_nodes/horizontal_ocr/horizontal_ocr.cpp,//src:libcustom_node_horizontal_ocr.so,1,0,0,0,0,0,0,1,2 +src/custom_nodes/image_transformation/image_transformation.cpp,//src:libcustom_node_image_transformation.so,1,0,0,0,0,0,0,1,2 +src/custom_nodes/model_zoo_intel_object_detection/model_zoo_intel_object_detection.cpp,//src:libcustom_node_model_zoo_intel_object_detection.so,3,0,0,0,0,0,0,1,4 +src/customloaders.cpp,//src:customloaders,8,0,0,0,0,0,0,6,14 +src/dags/custom_node.cpp,//src/dags:custom_node,36,1,0,0,0,0,0,5,42 +src/dags/custom_node_library_manager.cpp,//src/dags:custom_node_library_manager,8,0,0,0,0,0,0,5,13 +src/dags/custom_node_output_allocator.cpp,//src/dags:custom_node_output_allocator,3,0,0,0,0,0,0,4,7 +src/dags/customnodesession.cpp,//src/dags:customnodesession,33,1,0,0,0,0,0,5,39 +src/dags/dag_capi.cpp,//src/dags:dag_capi,96,1,0,0,0,0,0,9,106 +src/dags/dag_kfs.cpp,//src/dags:dag_kfs,93,1,0,0,0,0,1,10,105 +src/dags/dag_tfs.cpp,//src/dags:dag_tfs,97,1,0,1,0,0,1,26,126 +src/dags/dl_node.cpp,//src/dags:dl_node,54,1,0,0,0,0,0,8,63 +src/dags/dlnodesession.cpp,//src/dags:dlnodesession,52,1,0,0,0,0,0,8,61 +src/dags/gathernodeinputhandler.cpp,//src/dags:gathernodeinputhandler,21,1,0,0,0,0,0,5,27 +src/dags/node.cpp,//src/dags:node,28,1,0,0,0,0,0,5,34 +src/dags/node_library.cpp,//src/dags:node_library,1,0,0,0,0,0,0,0,1 +src/dags/node_library_utils.cpp,//src/dags:node_library_utils,18,1,0,0,0,0,0,5,24 +src/dags/nodeinputhandler.cpp,//src/dags:nodeinputhandler,6,1,0,0,0,0,0,4,11 +src/dags/nodesession.cpp,//src/dags:nodesession,22,1,0,0,0,0,0,5,28 +src/dags/nodesessionmetadata.cpp,//src/dags:nodesessionmetadata,3,0,0,0,0,0,0,4,7 +src/dags/nodestreamidguard.cpp,//src/dags:nodestreamidguard,18,1,0,0,0,0,0,8,27 +src/dags/pipeline.cpp,//src/dags:pipeline,29,1,0,0,0,0,0,5,35 +src/dags/pipeline_config_parser.cpp,//src/dags:pipeline_config_parser,88,1,0,0,0,0,0,9,98 +src/dags/pipeline_factory.cpp,//src/dags:pipeline_factory,70,1,0,0,0,0,0,8,79 +src/dags/pipelinedefinition.cpp,//src/dags:pipelinedefinition,69,1,0,0,0,0,0,8,78 +src/dags/pipelinedefinitionstatus.cpp,//src/dags:pipelinedefinitionstatus,3,0,0,0,0,0,0,4,7 +src/deserialization_common.cpp,//src:deserialization_common,20,1,0,0,0,0,0,6,27 +src/drogon_http_async_writer_impl.cpp,//src:libdrogon_http_server,34,1,0,0,1,0,0,10,46 +src/drogon_http_server.cpp,//src:libdrogon_http_server,34,1,0,0,1,0,0,10,46 +src/embeddings/embeddings_api.cpp,//src/embeddings:embeddings_api,5,1,0,0,1,0,1,11,19 +src/embeddings/embeddings_calculator.pb.cc,//src/embeddings:embeddings_calculator_cc_proto,0,0,0,0,1,0,1,1,3 +src/embeddings/embeddings_calculator_options_lib.cc,//src/embeddings:embeddings_calculator_options_registry,1,0,0,0,1,0,1,8,11 +src/embeddings/embeddings_calculator_ov.cc,//src/embeddings:embeddingscalculator_ov,35,1,1,0,1,0,1,15,54 +src/embeddings/embeddings_calculator_ov.pb.cc,//src/embeddings:embeddings_calculator_ov_cc_proto,0,0,0,0,1,0,1,1,3 +src/embeddings/embeddings_calculator_ov_options_lib.cc,//src/embeddings:embeddings_calculator_ov_options_registry,1,0,0,0,1,0,1,8,11 +src/embeddings/embeddings_node_initializer.cpp,//src/embeddings:embeddingscalculator_ov,35,1,1,0,1,0,1,15,54 +src/embeddings/embeddings_servable.cpp,//src/embeddings:embeddings_servable,14,1,1,0,1,0,1,12,30 +src/executingstreamidguard.cpp,//src:executingstreamidguard,16,1,0,0,0,0,0,7,24 +src/filesystem/azurefilesystem.cpp,//src/filesystem:libovmsazurefilesystem,6,0,0,0,0,0,0,7,13 +src/filesystem/azurestorage.cpp,//src/filesystem:libovmsazurefilesystem,6,0,0,0,0,0,0,7,13 +src/filesystem/filesystem.cpp,//src/filesystem:libovmsfilesystem,5,0,0,0,0,0,0,5,10 +src/filesystem/filesystemfactory.cpp,//src/filesystem:libovmsfilesystemfactory,11,0,0,0,0,0,0,14,25 +src/filesystem/gcsfilesystem.cpp,//src/filesystem:libovmsgcsfilesystem,6,0,0,0,0,0,0,11,17 +src/filesystem/localfilesystem.cpp,//src/filesystem:libovmslocalfilesystem,6,0,0,0,0,0,0,5,11 +src/filesystem/s3filesystem.cpp,//src/filesystem:libovmss3filesystem,6,0,0,0,0,0,0,6,12 +src/get_model_metadata_impl.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/global_sequences_viewer.cpp,//src:global_sequences_viewer,17,1,0,0,0,0,0,5,23 +src/graph_export/embeddings_graph_cli_parser.cpp,//src/graph_export:embeddings_graph_cli_parser,6,0,0,0,0,0,0,5,11 +src/graph_export/graph_cli_parser.cpp,//src/graph_export:graph_cli_parser,5,0,0,0,0,0,0,5,10 +src/graph_export/graph_export.cpp,//src/graph_export:graph_export,14,0,0,0,1,0,1,12,28 +src/graph_export/image_generation_graph_cli_parser.cpp,//src/graph_export:image_generation_graph_cli_parser,8,0,0,0,0,0,0,6,14 +src/graph_export/rerank_graph_cli_parser.cpp,//src/graph_export:rerank_graph_cli_parser,6,0,0,0,0,0,0,5,11 +src/graph_export/s2t_graph_cli_parser.cpp,//src/graph_export:s2t_graph_cli_parser,6,0,0,0,0,0,0,5,11 +src/graph_export/t2s_graph_cli_parser.cpp,//src/graph_export:t2s_graph_cli_parser,6,0,0,0,0,0,0,5,11 +src/grpc_utils.cpp,//src:grpc_utils,2,0,0,0,0,1,0,5,8 +src/grpcservermodule.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/http_frontend/http_graph_executor_impl.cpp,//src:libovms_mediapipe_http_executor,48,1,0,0,1,0,1,18,69 +src/http_frontend/multi_part_parser_drogon_impl.cpp,//src:libmultipart_parser_drogon_impl,1,0,0,0,0,0,0,3,4 +src/http_rest_api_handler.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/http_server.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/httpservermodule.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/image_conversion.cpp,//src:image_conversion,9,1,0,0,0,0,0,7,17 +src/image_gen/http_image_gen_calculator.cc,//src/image_gen:image_gen_calculator,22,1,1,0,1,0,1,14,40 +src/image_gen/image_gen_calculator.pb.cc,//src/image_gen:image_gen_calculator_cc_proto,0,0,0,0,1,0,1,1,3 +src/image_gen/image_gen_calculator_options_lib.cc,//src/image_gen:image_gen_calculator_options_registry,1,0,0,0,1,0,1,8,11 +src/image_gen/image_gen_node_initializer.cpp,//src/image_gen:image_gen_calculator,22,1,1,0,1,0,1,14,40 +src/image_gen/imagegen_init.cpp,//src/image_gen:imagegen_init,18,1,1,0,1,0,1,10,32 +src/image_gen/imagegenutils.cpp,//src/image_gen:imagegenutils,14,1,1,0,0,0,0,8,24 +src/image_gen/pipelines.cpp,//src/image_gen:pipelines,4,1,1,0,0,0,0,4,10 +src/json_parser.cpp,//src:libmodelconfigjsonparser,3,1,0,0,0,0,0,5,9 +src/kfs_frontend/deserialization.cpp,//src:kfs_deserialization,26,1,0,0,0,0,1,7,35 +src/kfs_frontend/kfs_backend_impl.cpp,//src:kfs_backend_impl,66,1,0,0,0,0,1,10,78 +src/kfs_frontend/kfs_graph_executor_impl.cpp,//src:libovms_mediapipe_kfs_executor,54,1,0,1,1,1,1,33,92 +src/kfs_frontend/kfs_grpc_inference_service.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/kfs_frontend/kfs_request_utils.cpp,//src:kfs_request_utils,22,1,0,0,0,0,1,7,31 +src/kfs_frontend/kfs_utils.cpp,//src:libovms_kfs_utils,19,1,0,0,0,0,1,7,28 +src/kfs_frontend/serialization.cpp,//src:kfs_serialization,22,1,0,0,0,0,1,7,31 +src/kfs_frontend/tensor_conversion.cpp,//src:kfs_backend_impl,66,1,0,0,0,0,1,10,78 +src/kfs_frontend/validation.cpp,//src:kfs_validation,23,1,0,0,0,0,1,7,32 +src/kfserving_api/grpc_predict_v2.grpc.pb.cc,//src/kfserving_api:kfserving_api_cpp,0,0,0,0,0,0,1,1,2 +src/kfserving_api/grpc_predict_v2.pb.cc,//src/kfserving_api:kfserving_api_cpp,0,0,0,0,0,0,1,1,2 +src/layout.cpp,//src:libovmslayout,5,1,0,0,0,0,0,4,10 +src/layout_configuration.cpp,//src:libovmslayout_configuration,6,1,0,0,0,0,0,4,11 +src/llm/apis/openai_api_handler.cpp,//src/llm:openai_api_handler,22,1,1,0,1,0,1,15,41 +src/llm/apis/openai_completions.cpp,//src/llm:openai_completions_api_handler,23,1,1,0,1,0,1,15,42 +src/llm/apis/openai_responses.cpp,//src/llm:openai_responses_handler,23,1,1,0,1,0,1,15,42 +src/llm/http_llm_calculator.cc,//src/llm:llmcalculator,41,1,1,0,1,0,1,18,63 +src/llm/io_processing/base_generation_config_builder.cpp,//src/llm:generation_config_builders,4,0,1,0,0,0,0,5,10 +src/llm/io_processing/base_output_parser.cpp,//src/llm:io_processing_base_output_parser,4,0,1,0,0,0,0,1,6 +src/llm/io_processing/devstral/generation_config_builder.cpp,//src/llm:generation_config_builders,4,0,1,0,0,0,0,5,10 +src/llm/io_processing/devstral/tool_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/gptoss/harmony.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/gptoss/reasoning_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/gptoss/tool_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/hermes3/generation_config_builder.cpp,//src/llm:generation_config_builders,4,0,1,0,0,0,0,5,10 +src/llm/io_processing/hermes3/tool_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/llama3/generation_config_builder.cpp,//src/llm:generation_config_builders,4,0,1,0,0,0,0,5,10 +src/llm/io_processing/llama3/tool_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/mistral/tool_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/output_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/partial_json_builder.cpp,//src/llm:partial_json_builder,3,0,0,0,0,0,0,1,4 +src/llm/io_processing/phi4/generation_config_builder.cpp,//src/llm:generation_config_builders,4,0,1,0,0,0,0,5,10 +src/llm/io_processing/phi4/tool_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/qwen3/reasoning_parser.cpp,//src/llm:output_parsers,12,0,1,0,0,0,0,5,18 +src/llm/io_processing/qwen3coder/qwen3coder_tool_parser.cpp,//src/llm:io_processing_qwen3coder_tool_parser,9,0,1,0,0,0,0,5,15 +src/llm/io_processing/utils.cpp,//src/llm:io_processing_utils,0,0,0,0,0,0,0,0,0 +src/llm/language_model/continuous_batching/servable.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/language_model/continuous_batching/servable_initializer.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/language_model/legacy/legacy_executor.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/language_model/legacy/servable.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/language_model/legacy/servable_initializer.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/llm_calculator.pb.cc,//src/llm:llmcalculator_cc_proto,0,0,0,0,1,0,1,1,3 +src/llm/llm_node_initializer.cpp,//src/llm:llmcalculator,41,1,1,0,1,0,1,18,63 +src/llm/llmcalculator_options_lib.cc,//src/llm:llmcalculator_options_registry,1,0,0,0,1,0,1,8,11 +src/llm/py_jinja_template_processor.cpp,//src/llm:py_jinja_template_processor,2,1,0,0,1,0,1,13,18 +src/llm/servable.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/servable_initializer.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/visual_language_model/continuous_batching/servable.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/visual_language_model/legacy/legacy_executor.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/visual_language_model/legacy/servable.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/llm/visual_language_model/legacy/servable_initializer.cpp,//src/llm:genai_servables,38,1,1,0,1,0,1,18,60 +src/logging.cpp,//src:libovmslogging,0,0,0,0,0,0,0,4,4 +src/main.cpp,//src:ovms,249,1,1,1,1,1,1,72,327 +src/main_benchmark.cpp,//src:capi_benchmark,243,1,1,1,1,1,1,71,320 +src/main_capi.cpp,//src:capi_cpp_example,243,1,1,1,1,1,1,71,320 +src/main_windows.cpp,//src:ovms,249,1,1,1,1,1,1,72,327 +src/mediapipe_calculators/ovmscalculator.pb.cc,//src:ovmscalculatoroptions_cc_proto,0,0,0,0,1,0,1,1,3 +src/mediapipe_internal/mediapipe_utils.cpp,//src/mediapipe_internal:mediapipe_utils,3,0,0,0,0,0,0,4,7 +src/mediapipe_internal/mediapipefactory.cpp,//src/mediapipe_internal:libovms_mediapipe,41,1,0,0,1,0,1,17,61 +src/mediapipe_internal/mediapipegraphconfig.cpp,//src/mediapipe_internal:libovms_mediapipe,41,1,0,0,1,0,1,17,61 +src/mediapipe_internal/mediapipegraphdefinition.cpp,//src/mediapipe_internal:libovms_mediapipe,41,1,0,0,1,0,1,17,61 +src/mediapipe_internal/mediapipegraphexecutor.cpp,//src/mediapipe_internal:libovms_mediapipe,41,1,0,0,1,0,1,17,61 +src/mediapipe_internal/node_initializer.cpp,//src/mediapipe_internal:node_initializer,2,0,0,0,0,0,0,4,6 +src/metrics/metric.cpp,//src/metrics:libovmsmetrics,11,0,0,0,0,0,0,7,18 +src/metrics/metric_config.cpp,//src/metrics:libovmsmetrics,11,0,0,0,0,0,0,7,18 +src/metrics/metric_family.cpp,//src/metrics:libovmsmetrics,11,0,0,0,0,0,0,7,18 +src/metrics/metric_module.cpp,//src/metrics:libovmsmetrics,11,0,0,0,0,0,0,7,18 +src/metrics/metric_registry.cpp,//src/metrics:libovmsmetrics,11,0,0,0,0,0,0,7,18 +src/model.cpp,//src:model,67,1,0,0,0,0,0,9,77 +src/model_metric_reporter.cpp,//src:model_metric_reporter,13,0,0,0,0,0,0,7,20 +src/model_service.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/model_version_policy.cpp,//src:libovmsmodelversioning,1,0,0,0,0,0,0,0,1 +src/modelchangesubscription.cpp,//src:modelchangesubscription,2,0,0,0,0,0,0,4,6 +src/modelconfig.cpp,//src:modelconfig,18,1,0,0,0,0,0,6,25 +src/modelextensions.cpp,//src:modelextensions,0,0,0,0,0,0,0,0,0 +src/modelinstance.cpp,//src:modelinstance,56,1,0,0,0,0,0,9,66 +src/modelinstanceunloadguard.cpp,//src:modelinstanceunloadguard,35,1,0,0,0,0,0,8,44 +src/modelmanager.cpp,//src:modelmanager,130,1,0,0,1,0,1,27,160 +src/modelversionstatus.cpp,//src:libovmsmodelversionstatus,2,0,0,0,0,0,0,4,6 +src/module_names.cpp,//src:cpp_headers,2,0,0,0,0,0,0,4,6 +src/net_http_async_writer_impl.cpp,//src:libnet_http_server,4,0,0,1,0,0,1,21,27 +src/network_utils.cpp,//src:network_utils,1,0,0,0,0,0,0,4,5 +src/ocl_utils.cpp,//src:libovmsoclutils,1,1,0,0,0,0,0,4,6 +src/opencltensorfactory.cpp,//src:libovmstensorfactory,4,1,0,0,0,0,0,4,9 +src/outputkeeper.cpp,//src:libovms_outputkeeper,8,1,0,0,0,0,0,4,13 +src/ov_utils.cpp,//src:libovms_ov_utils,13,1,0,0,0,0,0,5,19 +src/ovinferrequestsqueue.cpp,//src:libovms_ovinferrequestsqueue,2,1,0,0,0,0,0,4,7 +src/ovmscalculatoroptions_options_lib.cc,//src:ovmscalculatoroptions_options_registry,1,0,0,0,1,0,1,8,11 +src/precision.cpp,//src:libovmsprecision,0,1,0,0,0,0,0,0,1 +src/precision_configuration.cpp,//src:libovmsprecision_configuration,3,1,0,0,0,0,0,4,8 +src/predict_request_validation_utils_impl.cpp,//src:predict_request_validation_utils_impl,9,1,0,0,0,0,0,4,14 +src/prediction_service.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/profiler.cpp,//src:libovmsprofiler,8,1,0,0,0,0,0,5,14 +src/profilermodule.cpp,//src:libovmsprofiler,8,1,0,0,0,0,0,5,14 +src/pull_module/cmd_exec.cpp,//src/pull_module:cmd_exec,2,0,0,0,0,0,0,7,9 +src/pull_module/gguf_downloader.cpp,//src/pull_module:gguf_downloader,10,0,0,0,0,0,0,7,17 +src/pull_module/hf_pull_model_module.cpp,//src/pull_module:hf_pull_model_module,21,0,0,0,1,0,1,17,40 +src/pull_module/libgit2.cpp,//src/pull_module:libgit2,10,0,0,0,0,0,0,9,19 +src/pull_module/model_downloader.cpp,//src/pull_module:model_downloader,7,0,0,0,0,0,0,5,12 +src/pull_module/optimum_export.cpp,//src/pull_module:optimum_export,11,0,0,0,0,0,0,8,19 +src/python/binding/ovms_py_tensor.cpp,//src/python/binding:pyovms.so,1,0,0,0,0,0,0,3,4 +src/python/ovms_py_tensor.cpp,//src/python:ovmspytensor,0,0,0,0,0,0,0,3,3 +src/python/pytensor_ovtensor_converter_calculator.cc,//src/python:pytensorovtensorconvertercalculator,6,1,0,0,1,0,1,13,22 +src/python/pytensor_ovtensor_converter_calculator.pb.cc,//src/python:pytensorovtensorconvertercalculator_cc_proto,0,0,0,0,1,0,1,1,3 +src/python/pytensorovtensorconvertercalculator_options_lib.cc,//src/python:pytensorovtensorconvertercalculator_options_registry,1,0,0,0,1,0,1,8,11 +src/python/python_backend.cpp,//src/python:pythonbackend,2,0,0,0,0,0,0,7,9 +src/python/python_executor_calculator.cc,//src/python:pythonexecutorcalculator,10,1,0,0,1,0,1,13,26 +src/python/python_executor_calculator.pb.cc,//src/python:pythonexecutorcalculator_cc_proto,0,0,0,0,1,0,1,1,3 +src/python/python_node_initializer.cpp,//src/python:pythonexecutorcalculator,10,1,0,0,1,0,1,13,26 +src/python/pythonexecutorcalculator_options_lib.cc,//src/python:pythonexecutorcalculator_options_registry,1,0,0,0,1,0,1,8,11 +src/python/pythoninterpretermodule.cpp,//src/python:libovmspythonmodule,16,1,0,0,1,0,1,13,32 +src/python/pythonnoderesources.cpp,//src/python:pythonnoderesources,6,0,0,0,1,0,1,13,21 +src/regularovtensorfactory.cpp,//src:libovmstensorfactory,4,1,0,0,0,0,0,4,9 +src/rerank/rerank_calculator.cc,//src/rerank:rerankcalculator,20,1,0,0,1,0,1,13,36 +src/rerank/rerank_calculator.pb.cc,//src/rerank:rerank_calculator_cc_proto,0,0,0,0,1,0,1,1,3 +src/rerank/rerank_calculator_options_lib.cc,//src/rerank:rerank_calculator_options_registry,1,0,0,0,1,0,1,8,11 +src/rerank/rerank_calculator_ov.cc,//src/rerank:rerankcalculator_ov,35,1,1,0,1,0,1,15,54 +src/rerank/rerank_calculator_ov.pb.cc,//src/rerank:rerank_calculator_ov_cc_proto,0,0,0,0,1,0,1,1,3 +src/rerank/rerank_calculator_ov_options_lib.cc,//src/rerank:rerank_calculator_ov_options_registry,1,0,0,0,1,0,1,8,11 +src/rerank/rerank_node_initializer.cpp,//src/rerank:rerankcalculator_ov,35,1,1,0,1,0,1,15,54 +src/rerank/rerank_utils.cpp,//src/rerank:rerank_api_handler,12,1,0,0,1,0,1,12,27 +src/rest_parser.cpp,//src:rest_parser_utils,23,1,0,1,0,1,1,24,51 +src/rest_utils.cpp,//src:rest_parser_utils,23,1,0,1,0,1,1,24,51 +src/schema.cpp,//src:libovmsschema,7,0,0,0,0,0,0,6,13 +src/sequence.cpp,//src:libovms_sequence,14,1,0,0,0,0,0,5,20 +src/sequence_manager.cpp,//src:libovms_sequence_manager,16,1,0,0,0,0,0,5,22 +src/serialization_common.cpp,//src:serialization_common,13,1,0,0,0,0,0,5,19 +src/servable_definition_unload_guard.cpp,//src:libovms_single_version_servable_definition,13,1,0,0,0,0,0,4,18 +src/servablemanagermodule.cpp,//src:servablemanagermodule,131,1,0,0,1,0,1,27,161 +src/servables_config_manager_module/listmodels.cpp,//src/servables_config_manager_module:listmodels,7,0,0,0,0,0,0,5,12 +src/servables_config_manager_module/servablesconfigmanagermodule.cpp,//src/servables_config_manager_module:servablesconfigmanagermodule,15,0,0,0,0,0,0,6,21 +src/server.cpp,//src:ovms_lib,242,1,1,1,1,1,1,71,319 +src/shape.cpp,//src:libovmsshape,4,1,0,0,0,0,0,4,9 +src/sidepacket_servable.cpp,//src:sidepacket_servable,10,1,1,0,1,0,1,12,26 +src/single_version_servable_definition.cpp,//src:libovms_single_version_servable_definition,13,1,0,0,0,0,0,4,18 +src/statefulmodelinstance.cpp,//src:statefulmodelinstance,65,1,0,0,0,0,0,9,75 +src/status.cpp,//src:libovmsstatus,1,0,0,0,0,0,0,4,5 +src/stringutils.cpp,//src:libovmsstring_utils,0,0,0,0,0,0,0,0,0 +src/systeminfo.cpp,//src:libovms_systeminfo,2,0,0,0,0,0,0,4,6 +src/tensor_conversion.cpp,//src:tensor_conversion,16,1,0,0,0,0,0,6,23 +src/tensor_conversion_common.cpp,//src:tensor_conversion_common,17,1,0,0,0,0,0,6,24 +src/tensorinfo.cpp,//src:libovms_tensorinfo,7,1,0,0,0,0,0,4,12 +src/test/c_api_test_utils.cpp,//src:test_utils,246,1,1,1,1,1,1,71,323 +src/test/config_export_full_test.cpp,//src:config_export_full_test,249,1,1,1,1,1,1,71,326 +src/test/config_export_test.cpp,//src:config_export_test,14,0,0,0,0,0,0,9,23 +src/test/constructor_enabled_model_manager.cpp,//src:test_constructor_enabled_model_manager,243,1,1,1,1,1,1,71,320 +src/test/custom_nodes/node_choose_maximum.cpp,//src:lib_node_choose_maximum.so,0,0,0,0,0,0,0,0,0 +src/test/custom_nodes/node_dynamic_demultiplex.cpp,//src:lib_node_dynamic_demultiplex.so,0,0,0,0,0,0,0,0,0 +src/test/custom_nodes/node_perform_different_operations.cpp,//src:lib_node_perform_different_operations.so,0,0,0,0,0,0,0,0,0 +src/test/embeddings_handler_test.cpp,//src:embeddings_handler_tests,6,1,0,0,1,0,1,13,22 +src/test/environment.cpp,//src:libtest_environment,1,0,0,0,0,0,0,7,8 +src/test/gguf_environment.cpp,//src:test_gguf_environment,1,0,0,0,0,0,0,7,8 +src/test/gpuenvironment.cpp,//src:libtest_gpuenvironment,1,0,0,0,0,0,0,7,8 +src/test/graph_export_test.cpp,//src:graph_export_test,18,0,0,0,1,0,1,14,34 +src/test/inferencerequest_test.cpp,//src:inferencerequest_test,22,1,0,0,0,0,0,7,30 +src/test/libgit2_test.cpp,//src:libgit2_test,249,1,1,1,1,1,1,71,326 +src/test/light_test_utils.cpp,//src:test_light_test_utils,0,0,0,0,0,0,0,2,2 +src/test/listdirectorymodels_test.cpp,//src:listdirectorymodels_test,248,1,1,1,1,1,1,71,325 +src/test/llm/output_parsers/base_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/devstral_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/gptoss_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/hermes3_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/llama3_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/mistral_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/partial_json_builder_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/phi4_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/qwen3_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/qwen3coder_output_parser_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/llm/output_parsers/stream_output_cache_test.cpp,//src:test_llm_output_parser_tests,14,0,1,0,0,0,0,8,23 +src/test/mediapipe/calculators/exceptionduringclosecalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/exceptionduringgetcontractcalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/exceptionduringopencalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/exceptionduringprocesscalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/multipart_accepting_calculator.cpp,//src/test/mediapipe/calculators:dependency_free_http_test_calculators,3,0,0,1,1,0,1,35,41 +src/test/mediapipe/calculators/negative_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/nooutputstreamsproducedcalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/openai_chat_completions_mock_calculator.cpp,//src/test/mediapipe/calculators:dependency_free_http_test_calculators,3,0,0,1,1,0,1,35,41 +src/test/mediapipe/calculators/ovms_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/ovms_image_input_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/ovms_kfs_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/ovmscalculator.pb.cc,//src/test/mediapipe/calculators:ovmscalculatoroptions_cc_proto,0,0,0,0,1,0,1,1,3 +src/test/mediapipe/calculators/ovmscalculatoroptions_options_lib.cc,//src/test/mediapipe/calculators:ovmscalculatoroptions_options_registry,1,0,0,0,1,0,1,8,11 +src/test/mediapipe/calculators/streaming_test_calculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/mediapipe/calculators/two_input_calculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,244,1,1,1,1,1,1,71,321 +src/test/network_utils_test.cpp,//src:network_utils_test,247,1,1,1,1,1,1,71,324 +src/test/openvino_remote_tensors_tests.cpp,//src:openvino_remote_tensors_tests,250,1,1,1,1,1,1,71,327 +src/test/openvino_tests.cpp,//src:openvino_tests,247,1,1,1,1,1,1,71,324 +src/test/optimum_cli_mock.cpp,//src:optimum-cli,0,0,0,0,0,0,0,0,0 +src/test/platform_utils.cpp,//src:test_platform_utils,0,0,0,0,0,0,0,3,3 +src/test/pull_gguf_hf_model_test.cpp,//src:pull_gguf_hf_model_test,249,1,1,1,1,1,1,71,326 +src/test/pull_hf_model_test.cpp,//src:pull_hf_model_test,250,1,1,1,1,1,1,71,327 +src/test/python_environment.cpp,//src:libtest_pythonenvironment,0,0,0,0,0,0,0,6,6 +src/test/test_cmd_exec.cpp,//src:test_cmd_exec,3,0,0,0,0,0,0,7,10 +src/test/test_file_utils.cpp,//src:test_file_utils,0,0,0,0,0,0,0,0,0 +src/test/test_utils.cpp,//src:test_utils,246,1,1,1,1,1,1,71,323 +src/test/test_with_temp_dir.cpp,//src:test_test_with_temp_dir,2,0,0,0,0,0,0,7,9 +src/test/text2image_test.cpp,//src:text2image_test,247,1,1,1,1,1,1,71,324 +src/test/tokenize_parser_test.cpp,//src:tokenize_parser_tests,5,1,0,0,1,0,1,13,21 +src/tfs_frontend/deserialization.cpp,//src:tfs_deserialization,25,1,0,1,0,0,1,23,51 +src/tfs_frontend/serialization.cpp,//src:tfs_serialization,21,1,0,1,0,0,1,23,47 +src/tfs_frontend/tensor_conversion.cpp,//src:tfs_backend_impl,65,1,0,1,0,0,1,26,94 +src/tfs_frontend/tfs_backend_impl.cpp,//src:tfs_backend_impl,65,1,0,1,0,0,1,26,94 +src/tfs_frontend/tfs_request_utils.cpp,//src:tfs_request_utils,27,1,0,1,0,0,1,23,53 +src/tfs_frontend/tfs_utils.cpp,//src:tfs_utils,18,1,0,1,0,0,1,23,44 +src/tfs_frontend/validation.cpp,//src:tfs_validation,22,1,0,1,0,0,1,23,48 +src/tokenize/tokenize_parser.cpp,//src/tokenize:tokenize_parser,4,1,0,0,1,0,1,11,18 +src/utils/env_guard.cpp,//src/utils:env_guard,1,0,0,0,0,0,0,7,8 +src/utils/rapidjson_utils.cpp,//src/utils:rapidjson_utils,3,0,0,0,0,0,0,1,4 +src/vaapitensorfactory.cpp,//src:libovmstensorfactory,4,1,0,0,0,0,0,4,9 +src/version.cpp,//src:libovms_version_impl,1,1,1,0,0,0,0,0,3 diff --git a/tools/build_metrics/current/headers_src.csv b/tools/build_metrics/current/headers_src.csv new file mode 100644 index 0000000000..234ad976a4 --- /dev/null +++ b/tools/build_metrics/current/headers_src.csv @@ -0,0 +1,398 @@ +file,unique_headers,unique_project_headers +src/anonymous_input_name.cpp,148,1 +src/audio/audio_utils.cpp,394,4 +src/audio/speech_to_text/s2t_calculator.cc,885,12 +src/audio/speech_to_text/s2t_calculator.pb.cc,336,1 +src/audio/speech_to_text/stt_node_initializer.cpp,867,8 +src/audio/text_to_speech/t2s_calculator.cc,850,8 +src/audio/text_to_speech/t2s_calculator.pb.cc,336,1 +src/audio/text_to_speech/t2s_servable.cpp,607,5 +src/audio/text_to_speech/tts_node_initializer.cpp,552,7 +src/capi_frontend/buffer.cpp,381,3 +src/capi_frontend/capi.cpp,1298,82 +src/capi_frontend/capi_backend_impls.cpp,618,50 +src/capi_frontend/capi_dag_utils.cpp,462,21 +src/capi_frontend/capi_request_utils.cpp,443,12 +src/capi_frontend/capi_utils.cpp,459,19 +src/capi_frontend/capi_validation.cpp,462,20 +src/capi_frontend/capimodule.cpp,419,8 +src/capi_frontend/deserialization.cpp,548,23 +src/capi_frontend/inferenceparameter.cpp,455,15 +src/capi_frontend/inferencerequest.cpp,346,8 +src/capi_frontend/inferenceresponse.cpp,432,8 +src/capi_frontend/inferencetensor.cpp,430,6 +src/capi_frontend/servablemetadata.cpp,350,6 +src/capi_frontend/server_settings.cpp,175,2 +src/capi_frontend/tensor_conversion.cpp,602,15 +src/cleaner_utils.cpp,385,6 +src/cli_parser.cpp,449,17 +src/color_format_configuration.cpp,453,3 +src/config.cpp,535,21 +src/config_export_module/config_export.cpp,471,9 +src/custom_nodes/add_one/add_one.cpp,266,6 +src/custom_nodes/common/buffersqueue.cpp,248,2 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,257,4 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,257,4 +src/custom_nodes/east_ocr/east_ocr.cpp,394,5 +src/custom_nodes/face_blur/face_blur.cpp,393,4 +src/custom_nodes/horizontal_ocr/horizontal_ocr.cpp,393,4 +src/custom_nodes/image_transformation/image_transformation.cpp,393,4 +src/custom_nodes/model_zoo_intel_object_detection/model_zoo_intel_object_detection.cpp,410,7 +src/customloaders.cpp,380,4 +src/dags/custom_node.cpp,475,29 +src/dags/custom_node_library_manager.cpp,436,8 +src/dags/custom_node_output_allocator.cpp,380,4 +src/dags/customnodesession.cpp,464,23 +src/dags/dag_capi.cpp,642,77 +src/dags/dag_kfs.cpp,774,73 +src/dags/dag_tfs.cpp,1243,77 +src/dags/dl_node.cpp,561,38 +src/dags/dlnodesession.cpp,562,38 +src/dags/gathernodeinputhandler.cpp,491,16 +src/dags/node.cpp,495,18 +src/dags/node_library.cpp,153,2 +src/dags/node_library_utils.cpp,486,13 +src/dags/nodeinputhandler.cpp,439,6 +src/dags/nodesession.cpp,447,13 +src/dags/nodesessionmetadata.cpp,396,4 +src/dags/nodestreamidguard.cpp,484,9 +src/dags/pipeline.cpp,458,17 +src/dags/pipeline_config_parser.cpp,499,29 +src/dags/pipeline_factory.cpp,465,24 +src/dags/pipelinedefinition.cpp,516,39 +src/dags/pipelinedefinitionstatus.cpp,389,4 +src/deserialization_common.cpp,542,14 +src/drogon_http_async_writer_impl.cpp,565,4 +src/drogon_http_server.cpp,570,9 +src/embeddings/embeddings_api.cpp,594,6 +src/embeddings/embeddings_calculator_ov.cc,914,26 +src/embeddings/embeddings_calculator_ov.pb.cc,336,1 +src/embeddings/embeddings_node_initializer.cpp,842,15 +src/embeddings/embeddings_servable.cpp,1109,14 +src/executingstreamidguard.cpp,481,8 +src/filesystem/azurefilesystem.cpp,1568,8 +src/filesystem/azurestorage.cpp,1566,7 +src/filesystem/filesystem.cpp,432,6 +src/filesystem/filesystemfactory.cpp,2183,11 +src/filesystem/gcsfilesystem.cpp,660,7 +src/filesystem/localfilesystem.cpp,431,6 +src/filesystem/s3filesystem.cpp,869,7 +src/get_model_metadata_impl.cpp,1242,49 +src/global_sequences_viewer.cpp,443,6 +src/graph_export/embeddings_graph_cli_parser.cpp,325,5 +src/graph_export/graph_cli_parser.cpp,324,4 +src/graph_export/graph_export.cpp,804,14 +src/graph_export/image_generation_graph_cli_parser.cpp,325,5 +src/graph_export/rerank_graph_cli_parser.cpp,325,5 +src/graph_export/s2t_graph_cli_parser.cpp,325,5 +src/graph_export/t2s_graph_cli_parser.cpp,325,5 +src/grpc_utils.cpp,360,2 +src/grpcservermodule.cpp,1204,36 +src/http_frontend/http_graph_executor_impl.cpp,938,12 +src/http_frontend/multi_part_parser_drogon_impl.cpp,425,2 +src/http_rest_api_handler.cpp,1691,105 +src/http_server.cpp,822,24 +src/httpservermodule.cpp,607,12 +src/image_conversion.cpp,551,3 +src/image_gen/http_image_gen_calculator.cc,886,9 +src/image_gen/image_gen_calculator.pb.cc,336,1 +src/image_gen/image_gen_node_initializer.cpp,594,10 +src/image_gen/imagegen_init.cpp,653,11 +src/image_gen/imagegenutils.cpp,656,8 +src/image_gen/pipelines.cpp,531,4 +src/json_parser.cpp,527,3 +src/kfs_frontend/deserialization.cpp,679,19 +src/kfs_frontend/kfs_backend_impl.cpp,752,48 +src/kfs_frontend/kfs_graph_executor_impl.cpp,1488,39 +src/kfs_frontend/kfs_grpc_inference_service.cpp,1100,81 +src/kfs_frontend/kfs_request_utils.cpp,587,13 +src/kfs_frontend/kfs_utils.cpp,673,13 +src/kfs_frontend/serialization.cpp,681,17 +src/kfs_frontend/tensor_conversion.cpp,739,17 +src/kfs_frontend/validation.cpp,681,20 +src/kfserving_api/grpc_predict_v2.grpc.pb.cc,417,2 +src/kfserving_api/grpc_predict_v2.pb.cc,333,1 +src/layout.cpp,443,4 +src/layout_configuration.cpp,362,5 +src/llm/apis/openai_api_handler.cpp,682,15 +src/llm/apis/openai_completions.cpp,686,16 +src/llm/apis/openai_responses.cpp,656,11 +src/llm/http_llm_calculator.cc,1005,23 +src/llm/io_processing/base_generation_config_builder.cpp,513,5 +src/llm/io_processing/base_output_parser.cpp,439,5 +src/llm/io_processing/devstral/generation_config_builder.cpp,433,5 +src/llm/io_processing/devstral/tool_parser.cpp,540,10 +src/llm/io_processing/gptoss/harmony.cpp,522,8 +src/llm/io_processing/gptoss/reasoning_parser.cpp,523,9 +src/llm/io_processing/gptoss/tool_parser.cpp,539,9 +src/llm/io_processing/hermes3/generation_config_builder.cpp,433,5 +src/llm/io_processing/hermes3/tool_parser.cpp,523,9 +src/llm/io_processing/llama3/generation_config_builder.cpp,433,5 +src/llm/io_processing/llama3/tool_parser.cpp,523,9 +src/llm/io_processing/mistral/tool_parser.cpp,539,9 +src/llm/io_processing/output_parser.cpp,535,19 +src/llm/io_processing/partial_json_builder.cpp,273,4 +src/llm/io_processing/phi4/generation_config_builder.cpp,433,5 +src/llm/io_processing/phi4/tool_parser.cpp,539,9 +src/llm/io_processing/qwen3/reasoning_parser.cpp,521,7 +src/llm/io_processing/qwen3coder/qwen3coder_tool_parser.cpp,527,10 +src/llm/io_processing/utils.cpp,192,1 +src/llm/language_model/continuous_batching/servable.cpp,1035,30 +src/llm/language_model/continuous_batching/servable_initializer.cpp,1045,31 +src/llm/language_model/legacy/legacy_executor.cpp,1029,25 +src/llm/language_model/legacy/servable.cpp,1035,31 +src/llm/language_model/legacy/servable_initializer.cpp,1040,31 +src/llm/llm_calculator.pb.cc,336,1 +src/llm/llm_node_initializer.cpp,1002,27 +src/llm/py_jinja_template_processor.cpp,874,3 +src/llm/servable.cpp,1008,31 +src/llm/servable_initializer.cpp,1064,35 +src/llm/visual_language_model/continuous_batching/servable.cpp,1030,26 +src/llm/visual_language_model/legacy/legacy_executor.cpp,1031,25 +src/llm/visual_language_model/legacy/servable.cpp,1040,34 +src/llm/visual_language_model/legacy/servable_initializer.cpp,1042,31 +src/logging.cpp,401,1 +src/main.cpp,256,4 +src/main_benchmark.cpp,362,1 +src/main_capi.cpp,268,1 +src/mediapipe_internal/mediapipe_utils.cpp,392,5 +src/mediapipe_internal/mediapipefactory.cpp,768,20 +src/mediapipe_internal/mediapipegraphconfig.cpp,462,8 +src/mediapipe_internal/mediapipegraphdefinition.cpp,876,32 +src/mediapipe_internal/mediapipegraphexecutor.cpp,880,14 +src/mediapipe_internal/node_initializer.cpp,285,2 +src/metrics/metric.cpp,208,1 +src/metrics/metric_config.cpp,448,7 +src/metrics/metric_family.cpp,235,2 +src/metrics/metric_module.cpp,303,4 +src/metrics/metric_registry.cpp,234,3 +src/model.cpp,551,32 +src/model_metric_reporter.cpp,420,8 +src/model_service.cpp,701,39 +src/model_version_policy.cpp,241,2 +src/modelchangesubscription.cpp,388,3 +src/modelconfig.cpp,532,17 +src/modelextensions.cpp,37,1 +src/modelinstance.cpp,622,39 +src/modelinstanceunloadguard.cpp,429,20 +src/modelmanager.cpp,962,63 +src/modelversionstatus.cpp,387,3 +src/module_names.cpp,148,1 +src/net_http_async_writer_impl.cpp,742,3 +src/network_utils.cpp,390,2 +src/ocl_utils.cpp,491,2 +src/opencltensorfactory.cpp,520,3 +src/outputkeeper.cpp,449,6 +src/ov_utils.cpp,484,9 +src/ovinferrequestsqueue.cpp,508,3 +src/precision.cpp,319,1 +src/precision_configuration.cpp,420,3 +src/predict_request_validation_utils_impl.cpp,447,8 +src/prediction_service.cpp,1292,68 +src/profiler.cpp,154,1 +src/profilermodule.cpp,413,9 +src/pull_module/cmd_exec.cpp,269,2 +src/pull_module/gguf_downloader.cpp,523,11 +src/pull_module/hf_pull_model_module.cpp,479,13 +src/pull_module/libgit2.cpp,507,10 +src/pull_module/model_downloader.cpp,432,7 +src/pull_module/optimum_export.cpp,438,11 +src/python/binding/ovms_py_tensor.cpp,477,1 +src/python/ovms_py_tensor.cpp,452,1 +src/python/pytensor_ovtensor_converter_calculator.cc,978,6 +src/python/pytensor_ovtensor_converter_calculator.pb.cc,339,1 +src/python/python_backend.cpp,547,3 +src/python/python_executor_calculator.cc,876,5 +src/python/python_executor_calculator.pb.cc,336,1 +src/python/python_node_initializer.cpp,859,5 +src/python/pythoninterpretermodule.cpp,553,9 +src/python/pythonnoderesources.cpp,866,6 +src/regularovtensorfactory.cpp,503,3 +src/rerank/rerank_calculator.cc,868,10 +src/rerank/rerank_calculator.pb.cc,336,1 +src/rerank/rerank_calculator_ov.cc,914,25 +src/rerank/rerank_calculator_ov.pb.cc,336,1 +src/rerank/rerank_node_initializer.cpp,861,16 +src/rerank/rerank_utils.cpp,565,6 +src/rest_parser.cpp,1168,15 +src/rest_utils.cpp,1179,16 +src/schema.cpp,463,7 +src/sequence.cpp,479,6 +src/sequence_manager.cpp,441,6 +src/serialization_common.cpp,454,9 +src/servable_definition_unload_guard.cpp,297,7 +src/servablemanagermodule.cpp,526,24 +src/servables_config_manager_module/listmodels.cpp,435,7 +src/servables_config_manager_module/servablesconfigmanagermodule.cpp,408,10 +src/server.cpp,1350,54 +src/shape.cpp,427,4 +src/sidepacket_servable.cpp,860,11 +src/single_version_servable_definition.cpp,395,10 +src/statefulmodelinstance.cpp,551,33 +src/status.cpp,280,1 +src/stringutils.cpp,258,1 +src/systeminfo.cpp,392,3 +src/tensor_conversion.cpp,597,11 +src/tensor_conversion_common.cpp,536,12 +src/tensorinfo.cpp,445,6 +src/test/audio/speech2text_test.cpp,1323,76 +src/test/audio/text2speech_test.cpp,1322,75 +src/test/azurefilesystem_test.cpp,1594,7 +src/test/c_api_stress_tests.cpp,1645,89 +src/test/c_api_test_utils.cpp,1190,63 +src/test/c_api_tests.cpp,1327,95 +src/test/capi_predict_validation_test.cpp,1219,64 +src/test/config_export_full_test.cpp,1225,72 +src/test/config_export_test.cpp,505,11 +src/test/constructor_enabled_model_manager.cpp,506,17 +src/test/custom_node_buffersqueue_test.cpp,419,2 +src/test/custom_node_output_allocator_test.cpp,454,5 +src/test/custom_nodes/node_add_sub.c,73,1 +src/test/custom_nodes/node_choose_maximum.cpp,220,1 +src/test/custom_nodes/node_dynamic_demultiplex.cpp,201,1 +src/test/custom_nodes/node_dynamic_image.c,60,1 +src/test/custom_nodes/node_missing_implementation.c,20,1 +src/test/custom_nodes/node_mock.c,20,1 +src/test/custom_nodes/node_perform_different_operations.cpp,201,1 +src/test/demultiplexer_node_test.cpp,1237,82 +src/test/deserialization_tests.cpp,1623,76 +src/test/embeddings_handler_test.cpp,608,5 +src/test/embeddingsnode_test.cpp,1322,75 +src/test/ensemble_config_change_stress.cpp,1646,90 +src/test/ensemble_flow_custom_node_tests.cpp,1581,94 +src/test/ensemble_mapping_config_tests.cpp,1529,85 +src/test/ensemble_metadata_test.cpp,624,56 +src/test/ensemble_tests.cpp,1657,109 +src/test/environment.cpp,461,2 +src/test/gather_node_test.cpp,1645,98 +src/test/gcsfilesystem_test.cpp,709,6 +src/test/get_mediapipe_graph_metadata_response_test.cpp,1601,81 +src/test/get_model_metadata_response_test.cpp,1538,66 +src/test/get_model_metadata_signature_test.cpp,1507,63 +src/test/get_model_metadata_validation_test.cpp,1063,6 +src/test/get_pipeline_metadata_response_test.cpp,1511,67 +src/test/gguf_environment.cpp,461,2 +src/test/gpuenvironment.cpp,461,2 +src/test/graph_export_test.cpp,504,10 +src/test/http_openai_handler_test.cpp,1395,85 +src/test/http_rest_api_handler_test.cpp,1229,76 +src/test/inferencerequest_test.cpp,501,10 +src/test/kfs_metadata_test.cpp,1224,69 +src/test/kfs_rest_parser_test.cpp,727,11 +src/test/kfs_rest_test.cpp,1578,76 +src/test/layout_test.cpp,461,3 +src/test/libgit2_test.cpp,1269,66 +src/test/light_test_utils.cpp,399,1 +src/test/listdirectorymodels_test.cpp,580,15 +src/test/listmodelsendpoint_test.cpp,1320,73 +src/test/llm/assisted_decoding_test.cpp,1427,98 +src/test/llm/llmnode_test.cpp,1434,105 +src/test/llm/llmtemplate_test.cpp,1443,101 +src/test/llm/max_model_length_test.cpp,1199,66 +src/test/llm/output_parsers/base_output_parser_test.cpp,519,4 +src/test/llm/output_parsers/devstral_output_parser_test.cpp,522,7 +src/test/llm/output_parsers/gptoss_output_parser_test.cpp,523,8 +src/test/llm/output_parsers/hermes3_output_parser_test.cpp,522,7 +src/test/llm/output_parsers/llama3_output_parser_test.cpp,522,7 +src/test/llm/output_parsers/mistral_output_parser_test.cpp,522,7 +src/test/llm/output_parsers/partial_json_builder_test.cpp,399,4 +src/test/llm/output_parsers/phi4_output_parser_test.cpp,522,7 +src/test/llm/output_parsers/qwen3_output_parser_test.cpp,522,7 +src/test/llm/output_parsers/qwen3coder_output_parser_test.cpp,591,10 +src/test/llm/output_parsers/stream_output_cache_test.cpp,521,6 +src/test/llm/text_streamer_test.cpp,1268,84 +src/test/llm/tokenize_endpoint_test.cpp,1426,102 +src/test/llm/visual_language_model/complete_flow_test.cpp,1384,85 +src/test/llm/visual_language_model/initialization_test.cpp,1192,65 +src/test/localfilesystem_test.cpp,500,6 +src/test/mediapipe/calculators/exceptionduringclosecalculator.cpp,761,1 +src/test/mediapipe/calculators/exceptionduringgetcontractcalculator.cpp,756,0 +src/test/mediapipe/calculators/exceptionduringopencalculator.cpp,756,0 +src/test/mediapipe/calculators/exceptionduringprocesscalculator.cpp,756,0 +src/test/mediapipe/calculators/multipart_accepting_calculator.cpp,686,3 +src/test/mediapipe/calculators/negative_calculator.cc,756,0 +src/test/mediapipe/calculators/nooutputstreamsproducedcalculator.cpp,756,0 +src/test/mediapipe/calculators/openai_chat_completions_mock_calculator.cpp,693,3 +src/test/mediapipe/calculators/ovms_calculator.cc,764,3 +src/test/mediapipe/calculators/ovms_image_input_calculator.cc,792,7 +src/test/mediapipe/calculators/ovms_kfs_calculator.cc,791,8 +src/test/mediapipe/calculators/ovmscalculator.pb.cc,339,1 +src/test/mediapipe/calculators/streaming_test_calculator.cpp,756,0 +src/test/mediapipe/calculators/two_input_calculator.cpp,756,0 +src/test/mediapipe/inputsidepacketusertestcalc.cc,757,1 +src/test/mediapipe_framework_test.cpp,1711,88 +src/test/mediapipe_validation_test.cpp,1556,69 +src/test/mediapipeflow_test.cpp,1732,93 +src/test/metric_config_test.cpp,1193,66 +src/test/metrics_flow_test.cpp,1661,82 +src/test/metrics_test.cpp,424,3 +src/test/model_cache_test.cpp,585,32 +src/test/model_service_test.cpp,1219,75 +src/test/model_test.cpp,1247,67 +src/test/model_version_policy_test.cpp,408,2 +src/test/modelconfig_test.cpp,1193,62 +src/test/modelinstance_test.cpp,1173,26 +src/test/modelmanager_test.cpp,1256,75 +src/test/modelversionstatus_test.cpp,554,2 +src/test/multi_part_parser_drogon_test.cpp,546,2 +src/test/multipart_calculator_test.cpp,1323,76 +src/test/network_utils_test.cpp,1207,63 +src/test/node_library_manager_test.cpp,533,23 +src/test/nodesessionmetadata_test.cpp,1191,64 +src/test/openvino_remote_tensors_tests.cpp,1351,70 +src/test/openvino_tests.cpp,1236,65 +src/test/optimum_cli_mock.cpp,194,0 +src/test/ov_utils_test.cpp,1246,66 +src/test/ovinferrequestqueue_test.cpp,503,3 +src/test/ovmsconfig_test.cpp,1220,67 +src/test/pipelinedefinitionstatus_test.cpp,1190,63 +src/test/platform_utils.cpp,244,1 +src/test/predict_validation_test.cpp,1612,65 +src/test/prediction_service_test.cpp,1662,95 +src/test/pull_gguf_hf_model_test.cpp,1296,75 +src/test/pull_hf_model_test.cpp,1305,79 +src/test/python_environment.cpp,546,1 +src/test/pythonnode_test.cpp,1714,86 +src/test/rerank_chunking_test.cpp,574,3 +src/test/rerank_handler_test.cpp,574,3 +src/test/reranknode_test.cpp,1354,75 +src/test/rest_utils_test.cpp,1191,64 +src/test/schema_test.cpp,444,2 +src/test/sequence_manager_test.cpp,672,10 +src/test/sequence_test.cpp,718,12 +src/test/serialization_tests.cpp,1618,71 +src/test/server_test.cpp,1298,77 +src/test/shape_test.cpp,1189,62 +src/test/standalone_http_server_test.cpp,544,0 +src/test/stateful_config_test.cpp,1192,65 +src/test/status_test.cpp,1189,62 +src/test/streaming_test.cpp,1213,73 +src/test/stringutils_test.cpp,411,1 +src/test/systeminfo_test.cpp,416,2 +src/test/tensor_conversion_test.cpp,1595,72 +src/test/tensorinfo_test.cpp,458,4 +src/test/tensorutils_test.cpp,450,1 +src/test/test_cmd_exec.cpp,363,1 +src/test/test_file_utils.cpp,270,1 +src/test/test_utils.cpp,1598,73 +src/test/test_with_temp_dir.cpp,456,2 +src/test/text2image_test.cpp,860,21 +src/test/tfs_rest_parser_binary_inputs_test.cpp,1194,63 +src/test/tfs_rest_parser_column_test.cpp,1507,63 +src/test/tfs_rest_parser_nonamed_test.cpp,1190,63 +src/test/tfs_rest_parser_row_test.cpp,1507,63 +src/test/threadsafequeue_test.cpp,452,1 +src/test/tokenize_parser_test.cpp,603,3 +src/test/unit_tests.cpp,549,4 +src/tfs_frontend/deserialization.cpp,1146,17 +src/tfs_frontend/serialization.cpp,1149,16 +src/tfs_frontend/tensor_conversion.cpp,1202,14 +src/tfs_frontend/tfs_backend_impl.cpp,1218,46 +src/tfs_frontend/tfs_request_utils.cpp,626,14 +src/tfs_frontend/tfs_utils.cpp,1139,10 +src/tfs_frontend/validation.cpp,1147,17 +src/tokenize/tokenize_parser.cpp,519,4 +src/utils/env_guard.cpp,380,2 +src/utils/rapidjson_utils.cpp,254,4 +src/vaapitensorfactory.cpp,542,4 +src/version.cpp,409,1 diff --git a/tools/build_metrics/current/impact.csv b/tools/build_metrics/current/impact.csv new file mode 100644 index 0000000000..bc6b32ad22 --- /dev/null +++ b/tools/build_metrics/current/impact.csv @@ -0,0 +1,410 @@ +file,target,rdep_targets,impacted_srcs +src/anonymous_input_name.cpp,//src:anonymous_input_name,72,179 +src/audio/audio_utils.cpp,//src/audio:audio_utils,19,133 +src/audio/speech_to_text/s2t_calculator.cc,//src/audio/speech_to_text:s2t_calculator,17,130 +src/audio/speech_to_text/s2t_calculator.pb.cc,//src/audio/speech_to_text:s2t_calculator_cc_proto,20,132 +src/audio/speech_to_text/s2t_calculator_options_lib.cc,//src/audio/speech_to_text:s2t_calculator_options_registry,1,1 +src/audio/speech_to_text/stt_node_initializer.cpp,//src/audio/speech_to_text:s2t_calculator,17,130 +src/audio/text_to_speech/t2s_calculator.cc,//src/audio/text_to_speech:t2s_calculator,17,130 +src/audio/text_to_speech/t2s_calculator.pb.cc,//src/audio/text_to_speech:t2s_calculator_cc_proto,21,133 +src/audio/text_to_speech/t2s_calculator_options_lib.cc,//src/audio/text_to_speech:t2s_calculator_options_registry,1,1 +src/audio/text_to_speech/t2s_servable.cpp,//src/audio/text_to_speech:t2s_servable,18,131 +src/audio/text_to_speech/tts_node_initializer.cpp,//src/audio/text_to_speech:t2s_calculator,17,130 +src/capi_frontend/buffer.cpp,//src:libovmscapibuffer,46,159 +src/capi_frontend/capi.cpp,//src:ovms_lib,16,128 +src/capi_frontend/capi_backend_impls.cpp,//src:capi_backend_impl,17,130 +src/capi_frontend/capi_dag_utils.cpp,//src:capi_dag_utils,18,130 +src/capi_frontend/capi_request_utils.cpp,//src:capi_request_utils,21,134 +src/capi_frontend/capi_utils.cpp,//src:libovmscapi_utils,22,134 +src/capi_frontend/capi_validation.cpp,//src:capi_validation,18,131 +src/capi_frontend/capimodule.cpp,//src:capimodule,17,129 +src/capi_frontend/deserialization.cpp,//src:capi_deserialization,19,132 +src/capi_frontend/inferenceparameter.cpp,//src:capiinferenceparameter,28,140 +src/capi_frontend/inferencerequest.cpp,//src:inferencerequest,26,138 +src/capi_frontend/inferenceresponse.cpp,//src:inferenceresponse,26,138 +src/capi_frontend/inferencetensor.cpp,//src:inferencetensor,28,140 +src/capi_frontend/servablemetadata.cpp,//src:libovms_capi_servable_metadata,17,129 +src/capi_frontend/server_settings.cpp,//src:libovms_server_settings,39,152 +src/capi_frontend/tensor_conversion.cpp,//src:capi_backend_impl,17,130 +src/cleaner_utils.cpp,//src:cleaner_utils,19,131 +src/cli_parser.cpp,//src:libovms_cliparser,24,137 +src/color_format_configuration.cpp,//src:libovmscolor_format_configuration,40,153 +src/config.cpp,//src:libovms_config,23,136 +src/config_export_module/config_export.cpp,//src/config_export_module:config_export,19,131 +src/custom_nodes/add_one/add_one.cpp,//src:libcustom_node_add_one.so,0,2 +src/custom_nodes/common/buffersqueue.cpp,//src:custom_nodes_common_buffersqueue,4,98 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,//src:libcustom_node_add_one.so,0,2 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,//src:libcustom_node_model_zoo_intel_object_detection.so,1,4 +src/custom_nodes/east_ocr/east_ocr.cpp,//src:libcustom_node_east_ocr.so,1,3 +src/custom_nodes/face_blur/face_blur.cpp,//src:libcustom_node_face_blur.so,1,3 +src/custom_nodes/horizontal_ocr/horizontal_ocr.cpp,//src:libcustom_node_horizontal_ocr.so,1,3 +src/custom_nodes/image_transformation/image_transformation.cpp,//src:libcustom_node_image_transformation.so,1,3 +src/custom_nodes/model_zoo_intel_object_detection/model_zoo_intel_object_detection.cpp,//src:libcustom_node_model_zoo_intel_object_detection.so,1,4 +src/customloaders.cpp,//src:customloaders,22,134 +src/dags/custom_node.cpp,//src/dags:custom_node,25,137 +src/dags/custom_node_library_manager.cpp,//src/dags:custom_node_library_manager,20,132 +src/dags/custom_node_output_allocator.cpp,//src/dags:custom_node_output_allocator,27,139 +src/dags/customnodesession.cpp,//src/dags:customnodesession,26,138 +src/dags/dag_capi.cpp,//src/dags:dag_capi,17,129 +src/dags/dag_kfs.cpp,//src/dags:dag_kfs,17,129 +src/dags/dag_tfs.cpp,//src/dags:dag_tfs,17,129 +src/dags/dl_node.cpp,//src/dags:dl_node,25,137 +src/dags/dlnodesession.cpp,//src/dags:dlnodesession,26,138 +src/dags/gathernodeinputhandler.cpp,//src/dags:gathernodeinputhandler,35,144 +src/dags/node.cpp,//src/dags:node,32,142 +src/dags/node_library.cpp,//src/dags:node_library,32,142 +src/dags/node_library_utils.cpp,//src/dags:node_library_utils,27,139 +src/dags/nodeinputhandler.cpp,//src/dags:nodeinputhandler,36,145 +src/dags/nodesession.cpp,//src/dags:nodesession,34,143 +src/dags/nodesessionmetadata.cpp,//src/dags:nodesessionmetadata,36,145 +src/dags/nodestreamidguard.cpp,//src/dags:nodestreamidguard,27,139 +src/dags/pipeline.cpp,//src/dags:pipeline,25,137 +src/dags/pipeline_config_parser.cpp,//src/dags:pipeline_config_parser,19,131 +src/dags/pipeline_factory.cpp,//src/dags:pipeline_factory,23,135 +src/dags/pipelinedefinition.cpp,//src/dags:pipelinedefinition,24,136 +src/dags/pipelinedefinitionstatus.cpp,//src/dags:pipelinedefinitionstatus,41,156 +src/deserialization_common.cpp,//src:deserialization_common,31,144 +src/drogon_http_async_writer_impl.cpp,//src:libdrogon_http_server,17,130 +src/drogon_http_server.cpp,//src:libdrogon_http_server,17,130 +src/embeddings/embeddings_api.cpp,//src/embeddings:embeddings_api,19,132 +src/embeddings/embeddings_calculator.pb.cc,//src/embeddings:embeddings_calculator_cc_proto,2,2 +src/embeddings/embeddings_calculator_options_lib.cc,//src/embeddings:embeddings_calculator_options_registry,1,1 +src/embeddings/embeddings_calculator_ov.cc,//src/embeddings:embeddingscalculator_ov,17,130 +src/embeddings/embeddings_calculator_ov.pb.cc,//src/embeddings:embeddings_calculator_ov_cc_proto,21,133 +src/embeddings/embeddings_calculator_ov_options_lib.cc,//src/embeddings:embeddings_calculator_ov_options_registry,1,1 +src/embeddings/embeddings_node_initializer.cpp,//src/embeddings:embeddingscalculator_ov,17,130 +src/embeddings/embeddings_servable.cpp,//src/embeddings:embeddings_servable,18,131 +src/executingstreamidguard.cpp,//src:executingstreamidguard,34,151 +src/filesystem/azurefilesystem.cpp,//src/filesystem:libovmsazurefilesystem,20,133 +src/filesystem/azurestorage.cpp,//src/filesystem:libovmsazurefilesystem,20,133 +src/filesystem/filesystem.cpp,//src/filesystem:libovmsfilesystem,79,213 +src/filesystem/filesystemfactory.cpp,//src/filesystem:libovmsfilesystemfactory,19,131 +src/filesystem/gcsfilesystem.cpp,//src/filesystem:libovmsgcsfilesystem,20,132 +src/filesystem/localfilesystem.cpp,//src/filesystem:libovmslocalfilesystem,36,149 +src/filesystem/s3filesystem.cpp,//src/filesystem:libovmss3filesystem,20,132 +src/get_model_metadata_impl.cpp,//src:ovms_lib,16,128 +src/global_sequences_viewer.cpp,//src:global_sequences_viewer,22,134 +src/graph_export/embeddings_graph_cli_parser.cpp,//src/graph_export:embeddings_graph_cli_parser,25,138 +src/graph_export/graph_cli_parser.cpp,//src/graph_export:graph_cli_parser,30,143 +src/graph_export/graph_export.cpp,//src/graph_export:graph_export,19,131 +src/graph_export/image_generation_graph_cli_parser.cpp,//src/graph_export:image_generation_graph_cli_parser,25,138 +src/graph_export/rerank_graph_cli_parser.cpp,//src/graph_export:rerank_graph_cli_parser,25,138 +src/graph_export/s2t_graph_cli_parser.cpp,//src/graph_export:s2t_graph_cli_parser,25,138 +src/graph_export/t2s_graph_cli_parser.cpp,//src/graph_export:t2s_graph_cli_parser,25,138 +src/grpc_utils.cpp,//src:grpc_utils,17,129 +src/grpcservermodule.cpp,//src:ovms_lib,16,128 +src/http_frontend/http_graph_executor_impl.cpp,//src:libovms_mediapipe_http_executor,17,129 +src/http_frontend/multi_part_parser_drogon_impl.cpp,//src:libmultipart_parser_drogon_impl,17,129 +src/http_rest_api_handler.cpp,//src:ovms_lib,16,128 +src/http_server.cpp,//src:ovms_lib,16,128 +src/httpservermodule.cpp,//src:ovms_lib,16,128 +src/image_conversion.cpp,//src:image_conversion,25,149 +src/image_gen/http_image_gen_calculator.cc,//src/image_gen:image_gen_calculator,17,130 +src/image_gen/image_gen_calculator.pb.cc,//src/image_gen:image_gen_calculator_cc_proto,21,133 +src/image_gen/image_gen_calculator_options_lib.cc,//src/image_gen:image_gen_calculator_options_registry,1,1 +src/image_gen/image_gen_node_initializer.cpp,//src/image_gen:image_gen_calculator,17,130 +src/image_gen/imagegen_init.cpp,//src/image_gen:imagegen_init,18,131 +src/image_gen/imagegenutils.cpp,//src/image_gen:imagegenutils,19,132 +src/image_gen/pipelines.cpp,//src/image_gen:pipelines,18,131 +src/json_parser.cpp,//src:libmodelconfigjsonparser,52,180 +src/kfs_frontend/deserialization.cpp,//src:kfs_deserialization,19,132 +src/kfs_frontend/kfs_backend_impl.cpp,//src:kfs_backend_impl,17,130 +src/kfs_frontend/kfs_graph_executor_impl.cpp,//src:libovms_mediapipe_kfs_executor,17,129 +src/kfs_frontend/kfs_grpc_inference_service.cpp,//src:ovms_lib,16,128 +src/kfs_frontend/kfs_request_utils.cpp,//src:kfs_request_utils,19,132 +src/kfs_frontend/kfs_utils.cpp,//src:libovms_kfs_utils,25,139 +src/kfs_frontend/serialization.cpp,//src:kfs_serialization,19,132 +src/kfs_frontend/tensor_conversion.cpp,//src:kfs_backend_impl,17,130 +src/kfs_frontend/validation.cpp,//src:kfs_validation,18,131 +src/kfserving_api/grpc_predict_v2.grpc.pb.cc,//src/kfserving_api:kfserving_api_cpp,28,143 +src/kfserving_api/grpc_predict_v2.pb.cc,//src/kfserving_api:kfserving_api_cpp,28,143 +src/layout.cpp,//src:libovmslayout,95,203 +src/layout_configuration.cpp,//src:libovmslayout_configuration,40,153 +src/llm/apis/openai_api_handler.cpp,//src/llm:openai_api_handler,21,144 +src/llm/apis/openai_completions.cpp,//src/llm:openai_completions_api_handler,19,142 +src/llm/apis/openai_responses.cpp,//src/llm:openai_responses_handler,19,142 +src/llm/http_llm_calculator.cc,//src/llm:llmcalculator,17,130 +src/llm/io_processing/base_generation_config_builder.cpp,//src/llm:generation_config_builders,19,146 +src/llm/io_processing/base_output_parser.cpp,//src/llm:io_processing_base_output_parser,25,167 +src/llm/io_processing/devstral/generation_config_builder.cpp,//src/llm:generation_config_builders,19,146 +src/llm/io_processing/devstral/tool_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/gptoss/harmony.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/gptoss/reasoning_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/gptoss/tool_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/hermes3/generation_config_builder.cpp,//src/llm:generation_config_builders,19,146 +src/llm/io_processing/hermes3/tool_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/llama3/generation_config_builder.cpp,//src/llm:generation_config_builders,19,146 +src/llm/io_processing/llama3/tool_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/mistral/tool_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/output_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/partial_json_builder.cpp,//src/llm:partial_json_builder,24,166 +src/llm/io_processing/phi4/generation_config_builder.cpp,//src/llm:generation_config_builders,19,146 +src/llm/io_processing/phi4/tool_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/qwen3/reasoning_parser.cpp,//src/llm:output_parsers,23,165 +src/llm/io_processing/qwen3coder/qwen3coder_tool_parser.cpp,//src/llm:io_processing_qwen3coder_tool_parser,24,166 +src/llm/io_processing/utils.cpp,//src/llm:io_processing_utils,26,168 +src/llm/language_model/continuous_batching/servable.cpp,//src/llm:genai_servables,18,141 +src/llm/language_model/continuous_batching/servable_initializer.cpp,//src/llm:genai_servables,18,141 +src/llm/language_model/legacy/legacy_executor.cpp,//src/llm:genai_servables,18,141 +src/llm/language_model/legacy/servable.cpp,//src/llm:genai_servables,18,141 +src/llm/language_model/legacy/servable_initializer.cpp,//src/llm:genai_servables,18,141 +src/llm/llm_calculator.pb.cc,//src/llm:llmcalculator_cc_proto,21,143 +src/llm/llm_node_initializer.cpp,//src/llm:llmcalculator,17,130 +src/llm/llmcalculator_options_lib.cc,//src/llm:llmcalculator_options_registry,1,1 +src/llm/py_jinja_template_processor.cpp,//src/llm:py_jinja_template_processor,19,142 +src/llm/servable.cpp,//src/llm:genai_servables,18,141 +src/llm/servable_initializer.cpp,//src/llm:genai_servables,18,141 +src/llm/visual_language_model/continuous_batching/servable.cpp,//src/llm:genai_servables,18,141 +src/llm/visual_language_model/legacy/legacy_executor.cpp,//src/llm:genai_servables,18,141 +src/llm/visual_language_model/legacy/servable.cpp,//src/llm:genai_servables,18,141 +src/llm/visual_language_model/legacy/servable_initializer.cpp,//src/llm:genai_servables,18,141 +src/logging.cpp,//src:libovmslogging,199,349 +src/main.cpp,//src:ovms,0,2 +src/main_benchmark.cpp,//src:capi_benchmark,0,1 +src/main_capi.cpp,//src:capi_cpp_example,0,1 +src/main_windows.cpp,//src:ovms,0,2 +src/mediapipe_calculators/ovmscalculator.pb.cc,//src:ovmscalculatoroptions_cc_proto,2,2 +src/mediapipe_internal/mediapipe_utils.cpp,//src/mediapipe_internal:mediapipe_utils,27,154 +src/mediapipe_internal/mediapipefactory.cpp,//src/mediapipe_internal:libovms_mediapipe,21,136 +src/mediapipe_internal/mediapipegraphconfig.cpp,//src/mediapipe_internal:libovms_mediapipe,21,136 +src/mediapipe_internal/mediapipegraphdefinition.cpp,//src/mediapipe_internal:libovms_mediapipe,21,136 +src/mediapipe_internal/mediapipegraphexecutor.cpp,//src/mediapipe_internal:libovms_mediapipe,21,136 +src/mediapipe_internal/node_initializer.cpp,//src/mediapipe_internal:node_initializer,30,152 +src/metrics/metric.cpp,//src/metrics:libovmsmetrics,44,166 +src/metrics/metric_config.cpp,//src/metrics:libovmsmetrics,44,166 +src/metrics/metric_family.cpp,//src/metrics:libovmsmetrics,44,166 +src/metrics/metric_module.cpp,//src/metrics:libovmsmetrics,44,166 +src/metrics/metric_registry.cpp,//src/metrics:libovmsmetrics,44,166 +src/model.cpp,//src:model,19,131 +src/model_metric_reporter.cpp,//src:model_metric_reporter,43,161 +src/model_service.cpp,//src:ovms_lib,16,128 +src/model_version_policy.cpp,//src:libovmsmodelversioning,121,250 +src/modelchangesubscription.cpp,//src:modelchangesubscription,36,149 +src/modelconfig.cpp,//src:modelconfig,39,152 +src/modelextensions.cpp,//src:modelextensions,38,151 +src/modelinstance.cpp,//src:modelinstance,21,133 +src/modelinstanceunloadguard.cpp,//src:modelinstanceunloadguard,34,148 +src/modelmanager.cpp,//src:modelmanager,18,130 +src/modelversionstatus.cpp,//src:libovmsmodelversionstatus,58,171 +src/module_names.cpp,//src:cpp_headers,117,247 +src/net_http_async_writer_impl.cpp,//src:libnet_http_server,17,129 +src/network_utils.cpp,//src:network_utils,17,129 +src/ocl_utils.cpp,//src:libovmsoclutils,2,93 +src/opencltensorfactory.cpp,//src:libovmstensorfactory,27,140 +src/outputkeeper.cpp,//src:libovms_outputkeeper,36,149 +src/ov_utils.cpp,//src:libovms_ov_utils,53,166 +src/ovinferrequestsqueue.cpp,//src:libovms_ovinferrequestsqueue,43,157 +src/ovmscalculatoroptions_options_lib.cc,//src:ovmscalculatoroptions_options_registry,1,1 +src/precision.cpp,//src:libovmsprecision,107,230 +src/precision_configuration.cpp,//src:libovmsprecision_configuration,40,153 +src/predict_request_validation_utils_impl.cpp,//src:predict_request_validation_utils_impl,58,168 +src/prediction_service.cpp,//src:ovms_lib,16,128 +src/profiler.cpp,//src:libovmsprofiler,89,214 +src/profilermodule.cpp,//src:libovmsprofiler,89,214 +src/pull_module/cmd_exec.cpp,//src/pull_module:cmd_exec,21,133 +src/pull_module/gguf_downloader.cpp,//src/pull_module:gguf_downloader,18,130 +src/pull_module/hf_pull_model_module.cpp,//src/pull_module:hf_pull_model_module,17,129 +src/pull_module/libgit2.cpp,//src/pull_module:libgit2,18,130 +src/pull_module/model_downloader.cpp,//src/pull_module:model_downloader,21,133 +src/pull_module/optimum_export.cpp,//src/pull_module:optimum_export,18,130 +src/python/binding/ovms_py_tensor.cpp,//src/python/binding:pyovms.so,0,1 +src/python/ovms_py_tensor.cpp,//src/python:ovmspytensor,26,142 +src/python/pytensor_ovtensor_converter_calculator.cc,//src/python:pytensorovtensorconvertercalculator,23,138 +src/python/pytensor_ovtensor_converter_calculator.pb.cc,//src/python:pytensorovtensorconvertercalculator_cc_proto,26,140 +src/python/pytensorovtensorconvertercalculator_options_lib.cc,//src/python:pytensorovtensorconvertercalculator_options_registry,1,1 +src/python/python_backend.cpp,//src/python:pythonbackend,25,141 +src/python/python_executor_calculator.cc,//src/python:pythonexecutorcalculator,23,139 +src/python/python_executor_calculator.pb.cc,//src/python:pythonexecutorcalculator_cc_proto,27,142 +src/python/python_node_initializer.cpp,//src/python:pythonexecutorcalculator,23,139 +src/python/pythonexecutorcalculator_options_lib.cc,//src/python:pythonexecutorcalculator_options_registry,1,1 +src/python/pythoninterpretermodule.cpp,//src/python:libovmspythonmodule,22,137 +src/python/pythonnoderesources.cpp,//src/python:pythonnoderesources,24,140 +src/regularovtensorfactory.cpp,//src:libovmstensorfactory,27,140 +src/rerank/rerank_calculator.cc,//src/rerank:rerankcalculator,17,129 +src/rerank/rerank_calculator.pb.cc,//src/rerank:rerank_calculator_cc_proto,20,131 +src/rerank/rerank_calculator_options_lib.cc,//src/rerank:rerank_calculator_options_registry,1,1 +src/rerank/rerank_calculator_ov.cc,//src/rerank:rerankcalculator_ov,17,130 +src/rerank/rerank_calculator_ov.pb.cc,//src/rerank:rerank_calculator_ov_cc_proto,20,132 +src/rerank/rerank_calculator_ov_options_lib.cc,//src/rerank:rerank_calculator_ov_options_registry,1,1 +src/rerank/rerank_node_initializer.cpp,//src/rerank:rerankcalculator_ov,17,130 +src/rerank/rerank_utils.cpp,//src/rerank:rerank_api_handler,19,132 +src/rest_parser.cpp,//src:rest_parser_utils,17,130 +src/rest_utils.cpp,//src:rest_parser_utils,17,130 +src/schema.cpp,//src:libovmsschema,55,177 +src/sequence.cpp,//src:libovms_sequence,31,144 +src/sequence_manager.cpp,//src:libovms_sequence_manager,30,143 +src/serialization_common.cpp,//src:serialization_common,30,143 +src/servable_definition_unload_guard.cpp,//src:libovms_single_version_servable_definition,28,144 +src/servablemanagermodule.cpp,//src:servablemanagermodule,17,129 +src/servables_config_manager_module/listmodels.cpp,//src/servables_config_manager_module:listmodels,18,130 +src/servables_config_manager_module/servablesconfigmanagermodule.cpp,//src/servables_config_manager_module:servablesconfigmanagermodule,17,129 +src/server.cpp,//src:ovms_lib,16,128 +src/shape.cpp,//src:libovmsshape,99,205 +src/sidepacket_servable.cpp,//src:sidepacket_servable,21,134 +src/single_version_servable_definition.cpp,//src:libovms_single_version_servable_definition,28,144 +src/statefulmodelinstance.cpp,//src:statefulmodelinstance,20,132 +src/status.cpp,//src:libovmsstatus,160,306 +src/stringutils.cpp,//src:libovmsstring_utils,162,309 +src/systeminfo.cpp,//src:libovms_systeminfo,24,137 +src/tensor_conversion.cpp,//src:tensor_conversion,34,147 +src/tensor_conversion_common.cpp,//src:tensor_conversion_common,34,150 +src/tensorinfo.cpp,//src:libovms_tensorinfo,89,197 +src/test/audio/speech2text_test.cpp,//src:ovms_test,0,91 +src/test/audio/text2speech_test.cpp,//src:ovms_test,0,91 +src/test/azurefilesystem_test.cpp,//src:ovms_test,0,91 +src/test/c_api_stress_tests.cpp,//src:ovms_test,0,91 +src/test/c_api_test_utils.cpp,//src:test_utils,10,102 +src/test/c_api_tests.cpp,//src:ovms_test,0,91 +src/test/capi_predict_validation_test.cpp,//src:ovms_test,0,91 +src/test/config_export_full_test.cpp,//src:config_export_full_test,1,92 +src/test/config_export_test.cpp,//src:config_export_test,1,92 +src/test/constructor_enabled_model_manager.cpp,//src:test_constructor_enabled_model_manager,2,93 +src/test/custom_node_buffersqueue_test.cpp,//src:ovms_test,0,91 +src/test/custom_node_output_allocator_test.cpp,//src:ovms_test,0,91 +src/test/custom_nodes/node_choose_maximum.cpp,//src:lib_node_choose_maximum.so,0,1 +src/test/custom_nodes/node_dynamic_demultiplex.cpp,//src:lib_node_dynamic_demultiplex.so,0,1 +src/test/custom_nodes/node_perform_different_operations.cpp,//src:lib_node_perform_different_operations.so,0,1 +src/test/demultiplexer_node_test.cpp,//src:ovms_test,0,91 +src/test/deserialization_tests.cpp,//src:ovms_test,0,91 +src/test/disabled_mediapipe_test.cpp,//src:ovms_test,0,91 +src/test/embeddings_handler_test.cpp,//src:embeddings_handler_tests,1,92 +src/test/embeddingsnode_test.cpp,//src:ovms_test,0,91 +src/test/ensemble_config_change_stress.cpp,//src:ovms_test,0,91 +src/test/ensemble_flow_custom_node_tests.cpp,//src:ovms_test,0,91 +src/test/ensemble_mapping_config_tests.cpp,//src:ovms_test,0,91 +src/test/ensemble_metadata_test.cpp,//src:ovms_test,0,91 +src/test/ensemble_tests.cpp,//src:ovms_test,0,91 +src/test/environment.cpp,//src:libtest_environment,3,94 +src/test/gather_node_test.cpp,//src:ovms_test,0,91 +src/test/gcsfilesystem_test.cpp,//src:ovms_test,0,91 +src/test/get_mediapipe_graph_metadata_response_test.cpp,//src:ovms_test,0,91 +src/test/get_model_metadata_response_test.cpp,//src:ovms_test,0,91 +src/test/get_model_metadata_signature_test.cpp,//src:ovms_test,0,91 +src/test/get_model_metadata_validation_test.cpp,//src:ovms_test,0,91 +src/test/get_pipeline_metadata_response_test.cpp,//src:ovms_test,0,91 +src/test/gguf_environment.cpp,//src:test_gguf_environment,2,93 +src/test/gpuenvironment.cpp,//src:libtest_gpuenvironment,2,93 +src/test/graph_export_test.cpp,//src:graph_export_test,1,92 +src/test/http_openai_handler_test.cpp,//src:ovms_test,0,91 +src/test/http_rest_api_handler_test.cpp,//src:ovms_test,0,91 +src/test/inferencerequest_test.cpp,//src:inferencerequest_test,1,92 +src/test/kfs_metadata_test.cpp,//src:ovms_test,0,91 +src/test/kfs_rest_parser_test.cpp,//src:ovms_test,0,91 +src/test/kfs_rest_test.cpp,//src:ovms_test,0,91 +src/test/layout_test.cpp,//src:ovms_test,0,91 +src/test/libgit2_test.cpp,//src:libgit2_test,1,92 +src/test/light_test_utils.cpp,//src:test_light_test_utils,13,105 +src/test/listdirectorymodels_test.cpp,//src:listdirectorymodels_test,1,92 +src/test/listmodelsendpoint_test.cpp,//src:ovms_test,0,91 +src/test/llm/assisted_decoding_test.cpp,//src:ovms_test,0,91 +src/test/llm/llmnode_test.cpp,//src:ovms_test,0,91 +src/test/llm/llmtemplate_test.cpp,//src:ovms_test,0,91 +src/test/llm/max_model_length_test.cpp,//src:ovms_test,0,91 +src/test/llm/output_parsers/base_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/devstral_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/gptoss_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/hermes3_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/llama3_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/mistral_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/partial_json_builder_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/phi4_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/qwen3_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/qwen3coder_output_parser_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/output_parsers/stream_output_cache_test.cpp,//src:test_llm_output_parser_tests,1,102 +src/test/llm/text_streamer_test.cpp,//src:ovms_test,0,91 +src/test/llm/tokenize_endpoint_test.cpp,//src:ovms_test,0,91 +src/test/llm/visual_language_model/complete_flow_test.cpp,//src:ovms_test,0,91 +src/test/llm/visual_language_model/initialization_test.cpp,//src:ovms_test,0,91 +src/test/localfilesystem_test.cpp,//src:ovms_test,0,91 +src/test/mediapipe/calculators/exceptionduringclosecalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/exceptionduringgetcontractcalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/exceptionduringopencalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/exceptionduringprocesscalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/multipart_accepting_calculator.cpp,//src/test/mediapipe/calculators:dependency_free_http_test_calculators,1,93 +src/test/mediapipe/calculators/negative_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/nooutputstreamsproducedcalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/openai_chat_completions_mock_calculator.cpp,//src/test/mediapipe/calculators:dependency_free_http_test_calculators,1,93 +src/test/mediapipe/calculators/ovms_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/ovms_image_input_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/ovms_kfs_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/ovmscalculator.pb.cc,//src/test/mediapipe/calculators:ovmscalculatoroptions_cc_proto,4,104 +src/test/mediapipe/calculators/ovmscalculatoroptions_options_lib.cc,//src/test/mediapipe/calculators:ovmscalculatoroptions_options_registry,1,1 +src/test/mediapipe/calculators/streaming_test_calculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/calculators/two_input_calculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,1,102 +src/test/mediapipe/inputsidepacketusertestcalc.cc,//src:ovms_test,0,91 +src/test/mediapipe_framework_test.cpp,//src:ovms_test,0,91 +src/test/mediapipe_validation_test.cpp,//src:ovms_test,0,91 +src/test/mediapipeflow_test.cpp,//src:ovms_test,0,91 +src/test/metric_config_test.cpp,//src:ovms_test,0,91 +src/test/metrics_flow_test.cpp,//src:ovms_test,0,91 +src/test/metrics_test.cpp,//src:ovms_test,0,91 +src/test/model_cache_test.cpp,//src:ovms_test,0,91 +src/test/model_service_test.cpp,//src:ovms_test,0,91 +src/test/model_test.cpp,//src:ovms_test,0,91 +src/test/model_version_policy_test.cpp,//src:ovms_test,0,91 +src/test/modelconfig_test.cpp,//src:ovms_test,0,91 +src/test/modelinstance_test.cpp,//src:ovms_test,0,91 +src/test/modelmanager_test.cpp,//src:ovms_test,0,91 +src/test/modelversionstatus_test.cpp,//src:ovms_test,0,91 +src/test/multi_part_parser_drogon_test.cpp,//src:ovms_test,0,91 +src/test/multipart_calculator_test.cpp,//src:ovms_test,0,91 +src/test/network_utils_test.cpp,//src:network_utils_test,1,92 +src/test/node_library_manager_test.cpp,//src:ovms_test,0,91 +src/test/nodesessionmetadata_test.cpp,//src:ovms_test,0,91 +src/test/openvino_remote_tensors_tests.cpp,//src:openvino_remote_tensors_tests,1,92 +src/test/openvino_tests.cpp,//src:openvino_tests,1,92 +src/test/optimum_cli_mock.cpp,//src:optimum-cli,1,92 +src/test/ov_utils_test.cpp,//src:ovms_test,0,91 +src/test/ovinferrequestqueue_test.cpp,//src:ovms_test,0,91 +src/test/ovmsconfig_test.cpp,//src:ovms_test,0,91 +src/test/pipelinedefinitionstatus_test.cpp,//src:ovms_test,0,91 +src/test/platform_utils.cpp,//src:test_platform_utils,15,117 +src/test/predict_validation_test.cpp,//src:ovms_test,0,91 +src/test/prediction_service_test.cpp,//src:ovms_test,0,91 +src/test/pull_gguf_hf_model_test.cpp,//src:pull_gguf_hf_model_test,1,92 +src/test/pull_hf_model_test.cpp,//src:pull_hf_model_test,1,92 +src/test/python_environment.cpp,//src:libtest_pythonenvironment,1,92 +src/test/pythonnode_test.cpp,//src:ovms_test,0,91 +src/test/rerank_chunking_test.cpp,//src:ovms_test,0,91 +src/test/rerank_handler_test.cpp,//src:ovms_test,0,91 +src/test/reranknode_test.cpp,//src:ovms_test,0,91 +src/test/rest_utils_test.cpp,//src:ovms_test,0,91 +src/test/schema_test.cpp,//src:ovms_test,0,91 +src/test/sequence_manager_test.cpp,//src:ovms_test,0,91 +src/test/sequence_test.cpp,//src:ovms_test,0,91 +src/test/serialization_tests.cpp,//src:ovms_test,0,91 +src/test/server_test.cpp,//src:ovms_test,0,91 +src/test/shape_test.cpp,//src:ovms_test,0,91 +src/test/standalone_http_server_test.cpp,//src:ovms_test,0,91 +src/test/stateful_config_test.cpp,//src:ovms_test,0,91 +src/test/status_test.cpp,//src:ovms_test,0,91 +src/test/streaming_test.cpp,//src:ovms_test,0,91 +src/test/stringutils_test.cpp,//src:ovms_test,0,91 +src/test/systeminfo_test.cpp,//src:ovms_test,0,91 +src/test/tensor_conversion_test.cpp,//src:ovms_test,0,91 +src/test/tensorinfo_test.cpp,//src:ovms_test,0,91 +src/test/tensorutils_test.cpp,//src:ovms_test,0,91 +src/test/test_cmd_exec.cpp,//src:test_cmd_exec,1,92 +src/test/test_file_utils.cpp,//src:test_file_utils,3,94 +src/test/test_utils.cpp,//src:test_utils,10,102 +src/test/test_with_temp_dir.cpp,//src:test_test_with_temp_dir,8,99 +src/test/text2image_test.cpp,//src:text2image_test,1,92 +src/test/tfs_rest_parser_binary_inputs_test.cpp,//src:ovms_test,0,91 +src/test/tfs_rest_parser_column_test.cpp,//src:ovms_test,0,91 +src/test/tfs_rest_parser_nonamed_test.cpp,//src:ovms_test,0,91 +src/test/tfs_rest_parser_row_test.cpp,//src:ovms_test,0,91 +src/test/threadsafequeue_test.cpp,//src:ovms_test,0,91 +src/test/tokenize_parser_test.cpp,//src:tokenize_parser_tests,1,92 +src/test/unit_tests.cpp,//src:ovms_test,0,91 +src/tfs_frontend/deserialization.cpp,//src:tfs_deserialization,19,132 +src/tfs_frontend/serialization.cpp,//src:tfs_serialization,19,132 +src/tfs_frontend/tensor_conversion.cpp,//src:tfs_backend_impl,17,130 +src/tfs_frontend/tfs_backend_impl.cpp,//src:tfs_backend_impl,17,130 +src/tfs_frontend/tfs_request_utils.cpp,//src:tfs_request_utils,19,132 +src/tfs_frontend/tfs_utils.cpp,//src:tfs_utils,25,139 +src/tfs_frontend/validation.cpp,//src:tfs_validation,18,131 +src/tokenize/tokenize_parser.cpp,//src/tokenize:tokenize_parser,24,149 +src/utils/env_guard.cpp,//src/utils:env_guard,22,134 +src/utils/rapidjson_utils.cpp,//src/utils:rapidjson_utils,25,167 +src/vaapitensorfactory.cpp,//src:libovmstensorfactory,27,140 +src/version.cpp,//src:libovms_version_impl,17,129 diff --git a/tools/build_metrics/current/trans_srcs.csv b/tools/build_metrics/current/trans_srcs.csv new file mode 100644 index 0000000000..8aa6c403e2 --- /dev/null +++ b/tools/build_metrics/current/trans_srcs.csv @@ -0,0 +1,410 @@ +file,target,trans_src_count +src/anonymous_input_name.cpp,//src:anonymous_input_name,1 +src/audio/audio_utils.cpp,//src/audio:audio_utils,2 +src/audio/speech_to_text/s2t_calculator.cc,//src/audio/speech_to_text:s2t_calculator,10 +src/audio/speech_to_text/s2t_calculator.pb.cc,//src/audio/speech_to_text:s2t_calculator_cc_proto,1 +src/audio/speech_to_text/s2t_calculator_options_lib.cc,//src/audio/speech_to_text:s2t_calculator_options_registry,2 +src/audio/speech_to_text/stt_node_initializer.cpp,//src/audio/speech_to_text:s2t_calculator,10 +src/audio/text_to_speech/t2s_calculator.cc,//src/audio/text_to_speech:t2s_calculator,11 +src/audio/text_to_speech/t2s_calculator.pb.cc,//src/audio/text_to_speech:t2s_calculator_cc_proto,1 +src/audio/text_to_speech/t2s_calculator_options_lib.cc,//src/audio/text_to_speech:t2s_calculator_options_registry,2 +src/audio/text_to_speech/t2s_servable.cpp,//src/audio/text_to_speech:t2s_servable,6 +src/audio/text_to_speech/tts_node_initializer.cpp,//src/audio/text_to_speech:t2s_calculator,11 +src/capi_frontend/buffer.cpp,//src:libovmscapibuffer,2 +src/capi_frontend/capi.cpp,//src:ovms_lib,234 +src/capi_frontend/capi_backend_impls.cpp,//src:capi_backend_impl,52 +src/capi_frontend/capi_dag_utils.cpp,//src:capi_dag_utils,18 +src/capi_frontend/capi_request_utils.cpp,//src:capi_request_utils,17 +src/capi_frontend/capi_utils.cpp,//src:libovmscapi_utils,17 +src/capi_frontend/capi_validation.cpp,//src:capi_validation,23 +src/capi_frontend/capimodule.cpp,//src:capimodule,5 +src/capi_frontend/deserialization.cpp,//src:capi_deserialization,24 +src/capi_frontend/inferenceparameter.cpp,//src:capiinferenceparameter,12 +src/capi_frontend/inferencerequest.cpp,//src:inferencerequest,15 +src/capi_frontend/inferenceresponse.cpp,//src:inferenceresponse,15 +src/capi_frontend/inferencetensor.cpp,//src:inferencetensor,6 +src/capi_frontend/servablemetadata.cpp,//src:libovms_capi_servable_metadata,8 +src/capi_frontend/server_settings.cpp,//src:libovms_server_settings,2 +src/capi_frontend/tensor_conversion.cpp,//src:capi_backend_impl,52 +src/cleaner_utils.cpp,//src:cleaner_utils,16 +src/cli_parser.cpp,//src:libovms_cliparser,15 +src/color_format_configuration.cpp,//src:libovmscolor_format_configuration,3 +src/config.cpp,//src:libovms_config,26 +src/config_export_module/config_export.cpp,//src/config_export_module:config_export,9 +src/custom_nodes/add_one/add_one.cpp,//src:libcustom_node_add_one.so,3 +src/custom_nodes/common/buffersqueue.cpp,//src:custom_nodes_common_buffersqueue,1 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,//src:libcustom_node_add_one.so,3 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,//src:libcustom_node_model_zoo_intel_object_detection.so,3 +src/custom_nodes/east_ocr/east_ocr.cpp,//src:libcustom_node_east_ocr.so,1 +src/custom_nodes/face_blur/face_blur.cpp,//src:libcustom_node_face_blur.so,1 +src/custom_nodes/horizontal_ocr/horizontal_ocr.cpp,//src:libcustom_node_horizontal_ocr.so,1 +src/custom_nodes/image_transformation/image_transformation.cpp,//src:libcustom_node_image_transformation.so,1 +src/custom_nodes/model_zoo_intel_object_detection/model_zoo_intel_object_detection.cpp,//src:libcustom_node_model_zoo_intel_object_detection.so,3 +src/customloaders.cpp,//src:customloaders,6 +src/dags/custom_node.cpp,//src/dags:custom_node,23 +src/dags/custom_node_library_manager.cpp,//src/dags:custom_node_library_manager,7 +src/dags/custom_node_output_allocator.cpp,//src/dags:custom_node_output_allocator,3 +src/dags/customnodesession.cpp,//src/dags:customnodesession,22 +src/dags/dag_capi.cpp,//src/dags:dag_capi,69 +src/dags/dag_kfs.cpp,//src/dags:dag_kfs,68 +src/dags/dag_tfs.cpp,//src/dags:dag_tfs,68 +src/dags/dl_node.cpp,//src/dags:dl_node,41 +src/dags/dlnodesession.cpp,//src/dags:dlnodesession,39 +src/dags/gathernodeinputhandler.cpp,//src/dags:gathernodeinputhandler,15 +src/dags/node.cpp,//src/dags:node,18 +src/dags/node_library.cpp,//src/dags:node_library,1 +src/dags/node_library_utils.cpp,//src/dags:node_library_utils,14 +src/dags/nodeinputhandler.cpp,//src/dags:nodeinputhandler,3 +src/dags/nodesession.cpp,//src/dags:nodesession,16 +src/dags/nodesessionmetadata.cpp,//src/dags:nodesessionmetadata,2 +src/dags/nodestreamidguard.cpp,//src/dags:nodestreamidguard,18 +src/dags/pipeline.cpp,//src/dags:pipeline,19 +src/dags/pipeline_config_parser.cpp,//src/dags:pipeline_config_parser,62 +src/dags/pipeline_factory.cpp,//src/dags:pipeline_factory,52 +src/dags/pipelinedefinition.cpp,//src/dags:pipelinedefinition,51 +src/dags/pipelinedefinitionstatus.cpp,//src/dags:pipelinedefinitionstatus,3 +src/deserialization_common.cpp,//src:deserialization_common,16 +src/drogon_http_async_writer_impl.cpp,//src:libdrogon_http_server,28 +src/drogon_http_server.cpp,//src:libdrogon_http_server,28 +src/embeddings/embeddings_api.cpp,//src/embeddings:embeddings_api,3 +src/embeddings/embeddings_calculator.pb.cc,//src/embeddings:embeddings_calculator_cc_proto,1 +src/embeddings/embeddings_calculator_options_lib.cc,//src/embeddings:embeddings_calculator_options_registry,2 +src/embeddings/embeddings_calculator_ov.cc,//src/embeddings:embeddingscalculator_ov,27 +src/embeddings/embeddings_calculator_ov.pb.cc,//src/embeddings:embeddings_calculator_ov_cc_proto,1 +src/embeddings/embeddings_calculator_ov_options_lib.cc,//src/embeddings:embeddings_calculator_ov_options_registry,2 +src/embeddings/embeddings_node_initializer.cpp,//src/embeddings:embeddingscalculator_ov,27 +src/embeddings/embeddings_servable.cpp,//src/embeddings:embeddings_servable,11 +src/executingstreamidguard.cpp,//src:executingstreamidguard,15 +src/filesystem/azurefilesystem.cpp,//src/filesystem:libovmsazurefilesystem,7 +src/filesystem/azurestorage.cpp,//src/filesystem:libovmsazurefilesystem,7 +src/filesystem/filesystem.cpp,//src/filesystem:libovmsfilesystem,5 +src/filesystem/filesystemfactory.cpp,//src/filesystem:libovmsfilesystemfactory,11 +src/filesystem/gcsfilesystem.cpp,//src/filesystem:libovmsgcsfilesystem,6 +src/filesystem/localfilesystem.cpp,//src/filesystem:libovmslocalfilesystem,6 +src/filesystem/s3filesystem.cpp,//src/filesystem:libovmss3filesystem,6 +src/get_model_metadata_impl.cpp,//src:ovms_lib,234 +src/global_sequences_viewer.cpp,//src:global_sequences_viewer,15 +src/graph_export/embeddings_graph_cli_parser.cpp,//src/graph_export:embeddings_graph_cli_parser,6 +src/graph_export/graph_cli_parser.cpp,//src/graph_export:graph_cli_parser,5 +src/graph_export/graph_export.cpp,//src/graph_export:graph_export,10 +src/graph_export/image_generation_graph_cli_parser.cpp,//src/graph_export:image_generation_graph_cli_parser,6 +src/graph_export/rerank_graph_cli_parser.cpp,//src/graph_export:rerank_graph_cli_parser,6 +src/graph_export/s2t_graph_cli_parser.cpp,//src/graph_export:s2t_graph_cli_parser,6 +src/graph_export/t2s_graph_cli_parser.cpp,//src/graph_export:t2s_graph_cli_parser,6 +src/grpc_utils.cpp,//src:grpc_utils,3 +src/grpcservermodule.cpp,//src:ovms_lib,234 +src/http_frontend/http_graph_executor_impl.cpp,//src:libovms_mediapipe_http_executor,40 +src/http_frontend/multi_part_parser_drogon_impl.cpp,//src:libmultipart_parser_drogon_impl,1 +src/http_rest_api_handler.cpp,//src:ovms_lib,234 +src/http_server.cpp,//src:ovms_lib,234 +src/httpservermodule.cpp,//src:ovms_lib,234 +src/image_conversion.cpp,//src:image_conversion,9 +src/image_gen/http_image_gen_calculator.cc,//src/image_gen:image_gen_calculator,18 +src/image_gen/image_gen_calculator.pb.cc,//src/image_gen:image_gen_calculator_cc_proto,1 +src/image_gen/image_gen_calculator_options_lib.cc,//src/image_gen:image_gen_calculator_options_registry,2 +src/image_gen/image_gen_node_initializer.cpp,//src/image_gen:image_gen_calculator,18 +src/image_gen/imagegen_init.cpp,//src/image_gen:imagegen_init,14 +src/image_gen/imagegenutils.cpp,//src/image_gen:imagegenutils,10 +src/image_gen/pipelines.cpp,//src/image_gen:pipelines,3 +src/json_parser.cpp,//src:libmodelconfigjsonparser,4 +src/kfs_frontend/deserialization.cpp,//src:kfs_deserialization,21 +src/kfs_frontend/kfs_backend_impl.cpp,//src:kfs_backend_impl,50 +src/kfs_frontend/kfs_graph_executor_impl.cpp,//src:libovms_mediapipe_kfs_executor,47 +src/kfs_frontend/kfs_grpc_inference_service.cpp,//src:ovms_lib,234 +src/kfs_frontend/kfs_request_utils.cpp,//src:kfs_request_utils,18 +src/kfs_frontend/kfs_utils.cpp,//src:libovms_kfs_utils,17 +src/kfs_frontend/serialization.cpp,//src:kfs_serialization,20 +src/kfs_frontend/tensor_conversion.cpp,//src:kfs_backend_impl,50 +src/kfs_frontend/validation.cpp,//src:kfs_validation,18 +src/kfserving_api/grpc_predict_v2.grpc.pb.cc,//src/kfserving_api:kfserving_api_cpp,2 +src/kfserving_api/grpc_predict_v2.pb.cc,//src/kfserving_api:kfserving_api_cpp,2 +src/layout.cpp,//src:libovmslayout,5 +src/layout_configuration.cpp,//src:libovmslayout_configuration,6 +src/llm/apis/openai_api_handler.cpp,//src/llm:openai_api_handler,26 +src/llm/apis/openai_completions.cpp,//src/llm:openai_completions_api_handler,27 +src/llm/apis/openai_responses.cpp,//src/llm:openai_responses_handler,27 +src/llm/http_llm_calculator.cc,//src/llm:llmcalculator,54 +src/llm/io_processing/base_generation_config_builder.cpp,//src/llm:generation_config_builders,6 +src/llm/io_processing/base_output_parser.cpp,//src/llm:io_processing_base_output_parser,2 +src/llm/io_processing/devstral/generation_config_builder.cpp,//src/llm:generation_config_builders,6 +src/llm/io_processing/devstral/tool_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/gptoss/harmony.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/gptoss/reasoning_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/gptoss/tool_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/hermes3/generation_config_builder.cpp,//src/llm:generation_config_builders,6 +src/llm/io_processing/hermes3/tool_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/llama3/generation_config_builder.cpp,//src/llm:generation_config_builders,6 +src/llm/io_processing/llama3/tool_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/mistral/tool_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/output_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/partial_json_builder.cpp,//src/llm:partial_json_builder,1 +src/llm/io_processing/phi4/generation_config_builder.cpp,//src/llm:generation_config_builders,6 +src/llm/io_processing/phi4/tool_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/qwen3/reasoning_parser.cpp,//src/llm:output_parsers,18 +src/llm/io_processing/qwen3coder/qwen3coder_tool_parser.cpp,//src/llm:io_processing_qwen3coder_tool_parser,6 +src/llm/io_processing/utils.cpp,//src/llm:io_processing_utils,1 +src/llm/language_model/continuous_batching/servable.cpp,//src/llm:genai_servables,49 +src/llm/language_model/continuous_batching/servable_initializer.cpp,//src/llm:genai_servables,49 +src/llm/language_model/legacy/legacy_executor.cpp,//src/llm:genai_servables,49 +src/llm/language_model/legacy/servable.cpp,//src/llm:genai_servables,49 +src/llm/language_model/legacy/servable_initializer.cpp,//src/llm:genai_servables,49 +src/llm/llm_calculator.pb.cc,//src/llm:llmcalculator_cc_proto,1 +src/llm/llm_node_initializer.cpp,//src/llm:llmcalculator,54 +src/llm/llmcalculator_options_lib.cc,//src/llm:llmcalculator_options_registry,2 +src/llm/py_jinja_template_processor.cpp,//src/llm:py_jinja_template_processor,2 +src/llm/servable.cpp,//src/llm:genai_servables,49 +src/llm/servable_initializer.cpp,//src/llm:genai_servables,49 +src/llm/visual_language_model/continuous_batching/servable.cpp,//src/llm:genai_servables,49 +src/llm/visual_language_model/legacy/legacy_executor.cpp,//src/llm:genai_servables,49 +src/llm/visual_language_model/legacy/servable.cpp,//src/llm:genai_servables,49 +src/llm/visual_language_model/legacy/servable_initializer.cpp,//src/llm:genai_servables,49 +src/logging.cpp,//src:libovmslogging,1 +src/main.cpp,//src:ovms,243 +src/main_benchmark.cpp,//src:capi_benchmark,235 +src/main_capi.cpp,//src:capi_cpp_example,235 +src/main_windows.cpp,//src:ovms,243 +src/mediapipe_calculators/ovmscalculator.pb.cc,//src:ovmscalculatoroptions_cc_proto,1 +src/mediapipe_internal/mediapipe_utils.cpp,//src/mediapipe_internal:mediapipe_utils,4 +src/mediapipe_internal/mediapipefactory.cpp,//src/mediapipe_internal:libovms_mediapipe,39 +src/mediapipe_internal/mediapipegraphconfig.cpp,//src/mediapipe_internal:libovms_mediapipe,39 +src/mediapipe_internal/mediapipegraphdefinition.cpp,//src/mediapipe_internal:libovms_mediapipe,39 +src/mediapipe_internal/mediapipegraphexecutor.cpp,//src/mediapipe_internal:libovms_mediapipe,39 +src/mediapipe_internal/node_initializer.cpp,//src/mediapipe_internal:node_initializer,3 +src/metrics/metric.cpp,//src/metrics:libovmsmetrics,12 +src/metrics/metric_config.cpp,//src/metrics:libovmsmetrics,12 +src/metrics/metric_family.cpp,//src/metrics:libovmsmetrics,12 +src/metrics/metric_module.cpp,//src/metrics:libovmsmetrics,12 +src/metrics/metric_registry.cpp,//src/metrics:libovmsmetrics,12 +src/model.cpp,//src:model,56 +src/model_metric_reporter.cpp,//src:model_metric_reporter,13 +src/model_service.cpp,//src:ovms_lib,234 +src/model_version_policy.cpp,//src:libovmsmodelversioning,1 +src/modelchangesubscription.cpp,//src:modelchangesubscription,2 +src/modelconfig.cpp,//src:modelconfig,15 +src/modelextensions.cpp,//src:modelextensions,1 +src/modelinstance.cpp,//src:modelinstance,50 +src/modelinstanceunloadguard.cpp,//src:modelinstanceunloadguard,31 +src/modelmanager.cpp,//src:modelmanager,102 +src/modelversionstatus.cpp,//src:libovmsmodelversionstatus,2 +src/module_names.cpp,//src:cpp_headers,3 +src/net_http_async_writer_impl.cpp,//src:libnet_http_server,3 +src/network_utils.cpp,//src:network_utils,2 +src/ocl_utils.cpp,//src:libovmsoclutils,2 +src/opencltensorfactory.cpp,//src:libovmstensorfactory,5 +src/outputkeeper.cpp,//src:libovms_outputkeeper,8 +src/ov_utils.cpp,//src:libovms_ov_utils,12 +src/ovinferrequestsqueue.cpp,//src:libovms_ovinferrequestsqueue,2 +src/ovmscalculatoroptions_options_lib.cc,//src:ovmscalculatoroptions_options_registry,2 +src/precision.cpp,//src:libovmsprecision,1 +src/precision_configuration.cpp,//src:libovmsprecision_configuration,3 +src/predict_request_validation_utils_impl.cpp,//src:predict_request_validation_utils_impl,9 +src/prediction_service.cpp,//src:ovms_lib,234 +src/profiler.cpp,//src:libovmsprofiler,8 +src/profilermodule.cpp,//src:libovmsprofiler,8 +src/pull_module/cmd_exec.cpp,//src/pull_module:cmd_exec,3 +src/pull_module/gguf_downloader.cpp,//src/pull_module:gguf_downloader,9 +src/pull_module/hf_pull_model_module.cpp,//src/pull_module:hf_pull_model_module,17 +src/pull_module/libgit2.cpp,//src/pull_module:libgit2,10 +src/pull_module/model_downloader.cpp,//src/pull_module:model_downloader,7 +src/pull_module/optimum_export.cpp,//src/pull_module:optimum_export,11 +src/python/binding/ovms_py_tensor.cpp,//src/python/binding:pyovms.so,2 +src/python/ovms_py_tensor.cpp,//src/python:ovmspytensor,1 +src/python/pytensor_ovtensor_converter_calculator.cc,//src/python:pytensorovtensorconvertercalculator,6 +src/python/pytensor_ovtensor_converter_calculator.pb.cc,//src/python:pytensorovtensorconvertercalculator_cc_proto,1 +src/python/pytensorovtensorconvertercalculator_options_lib.cc,//src/python:pytensorovtensorconvertercalculator_options_registry,2 +src/python/python_backend.cpp,//src/python:pythonbackend,2 +src/python/python_executor_calculator.cc,//src/python:pythonexecutorcalculator,11 +src/python/python_executor_calculator.pb.cc,//src/python:pythonexecutorcalculator_cc_proto,1 +src/python/python_node_initializer.cpp,//src/python:pythonexecutorcalculator,11 +src/python/pythonexecutorcalculator_options_lib.cc,//src/python:pythonexecutorcalculator_options_registry,2 +src/python/pythoninterpretermodule.cpp,//src/python:libovmspythonmodule,16 +src/python/pythonnoderesources.cpp,//src/python:pythonnoderesources,6 +src/regularovtensorfactory.cpp,//src:libovmstensorfactory,5 +src/rerank/rerank_calculator.cc,//src/rerank:rerankcalculator,11 +src/rerank/rerank_calculator.pb.cc,//src/rerank:rerank_calculator_cc_proto,1 +src/rerank/rerank_calculator_options_lib.cc,//src/rerank:rerank_calculator_options_registry,2 +src/rerank/rerank_calculator_ov.cc,//src/rerank:rerankcalculator_ov,26 +src/rerank/rerank_calculator_ov.pb.cc,//src/rerank:rerank_calculator_ov_cc_proto,1 +src/rerank/rerank_calculator_ov_options_lib.cc,//src/rerank:rerank_calculator_ov_options_registry,2 +src/rerank/rerank_node_initializer.cpp,//src/rerank:rerankcalculator_ov,26 +src/rerank/rerank_utils.cpp,//src/rerank:rerank_api_handler,9 +src/rest_parser.cpp,//src:rest_parser_utils,20 +src/rest_utils.cpp,//src:rest_parser_utils,20 +src/schema.cpp,//src:libovmsschema,6 +src/sequence.cpp,//src:libovms_sequence,13 +src/sequence_manager.cpp,//src:libovms_sequence_manager,14 +src/serialization_common.cpp,//src:serialization_common,12 +src/servable_definition_unload_guard.cpp,//src:libovms_single_version_servable_definition,11 +src/servablemanagermodule.cpp,//src:servablemanagermodule,103 +src/servables_config_manager_module/listmodels.cpp,//src/servables_config_manager_module:listmodels,7 +src/servables_config_manager_module/servablesconfigmanagermodule.cpp,//src/servables_config_manager_module:servablesconfigmanagermodule,13 +src/server.cpp,//src:ovms_lib,234 +src/shape.cpp,//src:libovmsshape,4 +src/sidepacket_servable.cpp,//src:sidepacket_servable,9 +src/single_version_servable_definition.cpp,//src:libovms_single_version_servable_definition,11 +src/statefulmodelinstance.cpp,//src:statefulmodelinstance,55 +src/status.cpp,//src:libovmsstatus,2 +src/stringutils.cpp,//src:libovmsstring_utils,1 +src/systeminfo.cpp,//src:libovms_systeminfo,3 +src/tensor_conversion.cpp,//src:tensor_conversion,14 +src/tensor_conversion_common.cpp,//src:tensor_conversion_common,14 +src/tensorinfo.cpp,//src:libovms_tensorinfo,7 +src/test/audio/speech2text_test.cpp,//src:ovms_test,379 +src/test/audio/text2speech_test.cpp,//src:ovms_test,379 +src/test/azurefilesystem_test.cpp,//src:ovms_test,379 +src/test/c_api_stress_tests.cpp,//src:ovms_test,379 +src/test/c_api_test_utils.cpp,//src:test_utils,238 +src/test/c_api_tests.cpp,//src:ovms_test,379 +src/test/capi_predict_validation_test.cpp,//src:ovms_test,379 +src/test/config_export_full_test.cpp,//src:config_export_full_test,241 +src/test/config_export_test.cpp,//src:config_export_test,13 +src/test/constructor_enabled_model_manager.cpp,//src:test_constructor_enabled_model_manager,235 +src/test/custom_node_buffersqueue_test.cpp,//src:ovms_test,379 +src/test/custom_node_output_allocator_test.cpp,//src:ovms_test,379 +src/test/custom_nodes/node_choose_maximum.cpp,//src:lib_node_choose_maximum.so,1 +src/test/custom_nodes/node_dynamic_demultiplex.cpp,//src:lib_node_dynamic_demultiplex.so,1 +src/test/custom_nodes/node_perform_different_operations.cpp,//src:lib_node_perform_different_operations.so,1 +src/test/demultiplexer_node_test.cpp,//src:ovms_test,379 +src/test/deserialization_tests.cpp,//src:ovms_test,379 +src/test/disabled_mediapipe_test.cpp,//src:ovms_test,379 +src/test/embeddings_handler_test.cpp,//src:embeddings_handler_tests,4 +src/test/embeddingsnode_test.cpp,//src:ovms_test,379 +src/test/ensemble_config_change_stress.cpp,//src:ovms_test,379 +src/test/ensemble_flow_custom_node_tests.cpp,//src:ovms_test,379 +src/test/ensemble_mapping_config_tests.cpp,//src:ovms_test,379 +src/test/ensemble_metadata_test.cpp,//src:ovms_test,379 +src/test/ensemble_tests.cpp,//src:ovms_test,379 +src/test/environment.cpp,//src:libtest_environment,2 +src/test/gather_node_test.cpp,//src:ovms_test,379 +src/test/gcsfilesystem_test.cpp,//src:ovms_test,379 +src/test/get_mediapipe_graph_metadata_response_test.cpp,//src:ovms_test,379 +src/test/get_model_metadata_response_test.cpp,//src:ovms_test,379 +src/test/get_model_metadata_signature_test.cpp,//src:ovms_test,379 +src/test/get_model_metadata_validation_test.cpp,//src:ovms_test,379 +src/test/get_pipeline_metadata_response_test.cpp,//src:ovms_test,379 +src/test/gguf_environment.cpp,//src:test_gguf_environment,2 +src/test/gpuenvironment.cpp,//src:libtest_gpuenvironment,2 +src/test/graph_export_test.cpp,//src:graph_export_test,14 +src/test/http_openai_handler_test.cpp,//src:ovms_test,379 +src/test/http_rest_api_handler_test.cpp,//src:ovms_test,379 +src/test/inferencerequest_test.cpp,//src:inferencerequest_test,17 +src/test/kfs_metadata_test.cpp,//src:ovms_test,379 +src/test/kfs_rest_parser_test.cpp,//src:ovms_test,379 +src/test/kfs_rest_test.cpp,//src:ovms_test,379 +src/test/layout_test.cpp,//src:ovms_test,379 +src/test/libgit2_test.cpp,//src:libgit2_test,241 +src/test/light_test_utils.cpp,//src:test_light_test_utils,1 +src/test/listdirectorymodels_test.cpp,//src:listdirectorymodels_test,240 +src/test/listmodelsendpoint_test.cpp,//src:ovms_test,379 +src/test/llm/assisted_decoding_test.cpp,//src:ovms_test,379 +src/test/llm/llmnode_test.cpp,//src:ovms_test,379 +src/test/llm/llmtemplate_test.cpp,//src:ovms_test,379 +src/test/llm/max_model_length_test.cpp,//src:ovms_test,379 +src/test/llm/output_parsers/base_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/devstral_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/gptoss_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/hermes3_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/llama3_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/mistral_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/partial_json_builder_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/phi4_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/qwen3_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/qwen3coder_output_parser_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/output_parsers/stream_output_cache_test.cpp,//src:test_llm_output_parser_tests,30 +src/test/llm/text_streamer_test.cpp,//src:ovms_test,379 +src/test/llm/tokenize_endpoint_test.cpp,//src:ovms_test,379 +src/test/llm/visual_language_model/complete_flow_test.cpp,//src:ovms_test,379 +src/test/llm/visual_language_model/initialization_test.cpp,//src:ovms_test,379 +src/test/localfilesystem_test.cpp,//src:ovms_test,379 +src/test/mediapipe/calculators/exceptionduringclosecalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/exceptionduringgetcontractcalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/exceptionduringopencalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/exceptionduringprocesscalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/multipart_accepting_calculator.cpp,//src/test/mediapipe/calculators:dependency_free_http_test_calculators,2 +src/test/mediapipe/calculators/negative_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/nooutputstreamsproducedcalculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/openai_chat_completions_mock_calculator.cpp,//src/test/mediapipe/calculators:dependency_free_http_test_calculators,2 +src/test/mediapipe/calculators/ovms_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/ovms_image_input_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/ovms_kfs_calculator.cc,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/ovmscalculator.pb.cc,//src/test/mediapipe/calculators:ovmscalculatoroptions_cc_proto,1 +src/test/mediapipe/calculators/ovmscalculatoroptions_options_lib.cc,//src/test/mediapipe/calculators:ovmscalculatoroptions_options_registry,2 +src/test/mediapipe/calculators/streaming_test_calculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/calculators/two_input_calculator.cpp,//src/test/mediapipe/calculators:mediapipe_test_calculators,246 +src/test/mediapipe/inputsidepacketusertestcalc.cc,//src:ovms_test,379 +src/test/mediapipe_framework_test.cpp,//src:ovms_test,379 +src/test/mediapipe_validation_test.cpp,//src:ovms_test,379 +src/test/mediapipeflow_test.cpp,//src:ovms_test,379 +src/test/metric_config_test.cpp,//src:ovms_test,379 +src/test/metrics_flow_test.cpp,//src:ovms_test,379 +src/test/metrics_test.cpp,//src:ovms_test,379 +src/test/model_cache_test.cpp,//src:ovms_test,379 +src/test/model_service_test.cpp,//src:ovms_test,379 +src/test/model_test.cpp,//src:ovms_test,379 +src/test/model_version_policy_test.cpp,//src:ovms_test,379 +src/test/modelconfig_test.cpp,//src:ovms_test,379 +src/test/modelinstance_test.cpp,//src:ovms_test,379 +src/test/modelmanager_test.cpp,//src:ovms_test,379 +src/test/modelversionstatus_test.cpp,//src:ovms_test,379 +src/test/multi_part_parser_drogon_test.cpp,//src:ovms_test,379 +src/test/multipart_calculator_test.cpp,//src:ovms_test,379 +src/test/network_utils_test.cpp,//src:network_utils_test,239 +src/test/node_library_manager_test.cpp,//src:ovms_test,379 +src/test/nodesessionmetadata_test.cpp,//src:ovms_test,379 +src/test/openvino_remote_tensors_tests.cpp,//src:openvino_remote_tensors_tests,242 +src/test/openvino_tests.cpp,//src:openvino_tests,239 +src/test/optimum_cli_mock.cpp,//src:optimum-cli,1 +src/test/ov_utils_test.cpp,//src:ovms_test,379 +src/test/ovinferrequestqueue_test.cpp,//src:ovms_test,379 +src/test/ovmsconfig_test.cpp,//src:ovms_test,379 +src/test/pipelinedefinitionstatus_test.cpp,//src:ovms_test,379 +src/test/platform_utils.cpp,//src:test_platform_utils,1 +src/test/predict_validation_test.cpp,//src:ovms_test,379 +src/test/prediction_service_test.cpp,//src:ovms_test,379 +src/test/pull_gguf_hf_model_test.cpp,//src:pull_gguf_hf_model_test,241 +src/test/pull_hf_model_test.cpp,//src:pull_hf_model_test,242 +src/test/python_environment.cpp,//src:libtest_pythonenvironment,1 +src/test/pythonnode_test.cpp,//src:ovms_test,379 +src/test/rerank_chunking_test.cpp,//src:ovms_test,379 +src/test/rerank_handler_test.cpp,//src:ovms_test,379 +src/test/reranknode_test.cpp,//src:ovms_test,379 +src/test/rest_utils_test.cpp,//src:ovms_test,379 +src/test/schema_test.cpp,//src:ovms_test,379 +src/test/sequence_manager_test.cpp,//src:ovms_test,379 +src/test/sequence_test.cpp,//src:ovms_test,379 +src/test/serialization_tests.cpp,//src:ovms_test,379 +src/test/server_test.cpp,//src:ovms_test,379 +src/test/shape_test.cpp,//src:ovms_test,379 +src/test/standalone_http_server_test.cpp,//src:ovms_test,379 +src/test/stateful_config_test.cpp,//src:ovms_test,379 +src/test/status_test.cpp,//src:ovms_test,379 +src/test/streaming_test.cpp,//src:ovms_test,379 +src/test/stringutils_test.cpp,//src:ovms_test,379 +src/test/systeminfo_test.cpp,//src:ovms_test,379 +src/test/tensor_conversion_test.cpp,//src:ovms_test,379 +src/test/tensorinfo_test.cpp,//src:ovms_test,379 +src/test/tensorutils_test.cpp,//src:ovms_test,379 +src/test/test_cmd_exec.cpp,//src:test_cmd_exec,4 +src/test/test_file_utils.cpp,//src:test_file_utils,1 +src/test/test_utils.cpp,//src:test_utils,238 +src/test/test_with_temp_dir.cpp,//src:test_test_with_temp_dir,3 +src/test/text2image_test.cpp,//src:text2image_test,239 +src/test/tfs_rest_parser_binary_inputs_test.cpp,//src:ovms_test,379 +src/test/tfs_rest_parser_column_test.cpp,//src:ovms_test,379 +src/test/tfs_rest_parser_nonamed_test.cpp,//src:ovms_test,379 +src/test/tfs_rest_parser_row_test.cpp,//src:ovms_test,379 +src/test/threadsafequeue_test.cpp,//src:ovms_test,379 +src/test/tokenize_parser_test.cpp,//src:tokenize_parser_tests,3 +src/test/unit_tests.cpp,//src:ovms_test,379 +src/tfs_frontend/deserialization.cpp,//src:tfs_deserialization,19 +src/tfs_frontend/serialization.cpp,//src:tfs_serialization,18 +src/tfs_frontend/tensor_conversion.cpp,//src:tfs_backend_impl,48 +src/tfs_frontend/tfs_backend_impl.cpp,//src:tfs_backend_impl,48 +src/tfs_frontend/tfs_request_utils.cpp,//src:tfs_request_utils,19 +src/tfs_frontend/tfs_utils.cpp,//src:tfs_utils,15 +src/tfs_frontend/validation.cpp,//src:tfs_validation,16 +src/tokenize/tokenize_parser.cpp,//src/tokenize:tokenize_parser,2 +src/utils/env_guard.cpp,//src/utils:env_guard,2 +src/utils/rapidjson_utils.cpp,//src/utils:rapidjson_utils,1 +src/vaapitensorfactory.cpp,//src:libovmstensorfactory,5 +src/version.cpp,//src:libovms_version_impl,1 diff --git a/tools/build_metrics/current/tu_src.csv b/tools/build_metrics/current/tu_src.csv new file mode 100644 index 0000000000..e3ea0ecbff --- /dev/null +++ b/tools/build_metrics/current/tu_src.csv @@ -0,0 +1,249 @@ +file,pp_lines,pp_bytes +src/anonymous_input_name.cpp,17371,638262 +src/audio/audio_utils.cpp,85386,3209156 +src/audio/speech_to_text/s2t_calculator.cc,159402,6285090 +src/audio/speech_to_text/s2t_calculator.pb.cc,75911,2906009 +src/audio/speech_to_text/stt_node_initializer.cpp,156870,6194126 +src/audio/text_to_speech/t2s_calculator.cc,157754,6229913 +src/audio/text_to_speech/t2s_calculator.pb.cc,76449,2930661 +src/audio/text_to_speech/t2s_servable.cpp,118068,4661851 +src/audio/text_to_speech/tts_node_initializer.cpp,110988,4349445 +src/capi_frontend/buffer.cpp,68995,2544200 +src/capi_frontend/capi.cpp,281468,11686476 +src/capi_frontend/capi_backend_impls.cpp,114679,4381169 +src/capi_frontend/capi_dag_utils.cpp,82388,3073235 +src/capi_frontend/capi_request_utils.cpp,79114,2930601 +src/capi_frontend/capi_utils.cpp,80935,3009165 +src/capi_frontend/capi_validation.cpp,81103,3024992 +src/capi_frontend/capimodule.cpp,74455,2720112 +src/capi_frontend/deserialization.cpp,105144,3939144 +src/capi_frontend/inferenceparameter.cpp,80675,2999526 +src/capi_frontend/inferencerequest.cpp,71846,2648772 +src/capi_frontend/inferenceresponse.cpp,77871,2886816 +src/capi_frontend/inferencetensor.cpp,77824,2884526 +src/capi_frontend/servablemetadata.cpp,69473,2523969 +src/capi_frontend/server_settings.cpp,27733,975906 +src/capi_frontend/tensor_conversion.cpp,111693,4185974 +src/cleaner_utils.cpp,69702,2562426 +src/cli_parser.cpp,89721,3228075 +src/color_format_configuration.cpp,79241,2939827 +src/config.cpp,98023,3620910 +src/config_export_module/config_export.cpp,96033,3615992 +src/custom_nodes/add_one/add_one.cpp,49705,1719622 +src/custom_nodes/common/buffersqueue.cpp,43326,1479081 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,48427,1661275 +src/custom_nodes/common/custom_node_library_internal_manager.cpp,48427,1661275 +src/custom_nodes/east_ocr/east_ocr.cpp,85579,3134490 +src/custom_nodes/face_blur/face_blur.cpp,85241,3117816 +src/custom_nodes/horizontal_ocr/horizontal_ocr.cpp,85330,3121728 +src/custom_nodes/image_transformation/image_transformation.cpp,85246,3119483 +src/custom_nodes/model_zoo_intel_object_detection/model_zoo_intel_object_detection.cpp,92394,3359716 +src/customloaders.cpp,68296,2518229 +src/dags/custom_node.cpp,83414,3080518 +src/dags/custom_node_library_manager.cpp,83683,3019696 +src/dags/custom_node_output_allocator.cpp,67928,2505580 +src/dags/customnodesession.cpp,82213,3034734 +src/dags/dag_capi.cpp,116899,4403929 +src/dags/dag_kfs.cpp,160747,6373215 +src/dags/dag_tfs.cpp,269415,11108244 +src/dags/dl_node.cpp,99585,3761198 +src/dags/dlnodesession.cpp,99769,3767593 +src/dags/gathernodeinputhandler.cpp,86263,3202396 +src/dags/node.cpp,86759,3224501 +src/dags/node_library.cpp,17463,641940 +src/dags/node_library_utils.cpp,86209,3200150 +src/dags/nodeinputhandler.cpp,78006,2891899 +src/dags/nodesession.cpp,79232,2932715 +src/dags/nodesessionmetadata.cpp,72086,2643155 +src/dags/nodestreamidguard.cpp,87286,3225304 +src/dags/pipeline.cpp,82111,3033980 +src/dags/pipeline_config_parser.cpp,88600,3334098 +src/dags/pipeline_factory.cpp,82929,3085464 +src/dags/pipelinedefinition.cpp,90283,3386696 +src/dags/pipelinedefinitionstatus.cpp,71726,2637593 +src/deserialization_common.cpp,104836,3922618 +src/drogon_http_async_writer_impl.cpp,99028,3523631 +src/drogon_http_server.cpp,99801,3555066 +src/embeddings/embeddings_api.cpp,101383,3837539 +src/embeddings/embeddings_calculator_ov.cc,165343,6484944 +src/embeddings/embeddings_calculator_ov.pb.cc,76140,2917156 +src/embeddings/embeddings_node_initializer.cpp,158400,6146665 +src/embeddings/embeddings_servable.cpp,168559,6669157 +src/executingstreamidguard.cpp,87230,3222404 +src/filesystem/azurefilesystem.cpp,177937,6769362 +src/filesystem/azurestorage.cpp,177658,6775559 +src/filesystem/filesystem.cpp,84472,3044538 +src/filesystem/filesystemfactory.cpp,224130,8795366 +src/filesystem/gcsfilesystem.cpp,113048,4135552 +src/filesystem/localfilesystem.cpp,83580,3016198 +src/filesystem/s3filesystem.cpp,113120,4410911 +src/get_model_metadata_impl.cpp,271394,11199986 +src/global_sequences_viewer.cpp,79461,2939581 +src/graph_export/embeddings_graph_cli_parser.cpp,75950,2691653 +src/graph_export/graph_cli_parser.cpp,75995,2694452 +src/graph_export/graph_export.cpp,160332,6307503 +src/graph_export/image_generation_graph_cli_parser.cpp,76007,2695835 +src/graph_export/rerank_graph_cli_parser.cpp,75937,2690846 +src/graph_export/s2t_graph_cli_parser.cpp,75932,2690675 +src/graph_export/t2s_graph_cli_parser.cpp,75932,2690675 +src/grpc_utils.cpp,70234,2556471 +src/grpcservermodule.cpp,263314,10965225 +src/http_frontend/http_graph_executor_impl.cpp,173295,6963736 +src/http_frontend/multi_part_parser_drogon_impl.cpp,81790,2766576 +src/http_rest_api_handler.cpp,343853,14399478 +src/http_server.cpp,191178,7538957 +src/httpservermodule.cpp,101932,3619231 +src/image_conversion.cpp,103465,3872254 +src/image_gen/http_image_gen_calculator.cc,164794,6462916 +src/image_gen/image_gen_calculator.pb.cc,76539,2934343 +src/image_gen/image_gen_node_initializer.cpp,119625,4647894 +src/image_gen/imagegen_init.cpp,130127,5078734 +src/image_gen/imagegenutils.cpp,112055,4247577 +src/image_gen/pipelines.cpp,96676,3581755 +src/json_parser.cpp,90458,3418506 +src/kfs_frontend/deserialization.cpp,149014,5908174 +src/kfs_frontend/kfs_backend_impl.cpp,158527,6350489 +src/kfs_frontend/kfs_graph_executor_impl.cpp,322748,13596431 +src/kfs_frontend/kfs_grpc_inference_service.cpp,213285,8536866 +src/kfs_frontend/kfs_request_utils.cpp,124278,4950277 +src/kfs_frontend/kfs_utils.cpp,148939,5900715 +src/kfs_frontend/serialization.cpp,149202,5914587 +src/kfs_frontend/tensor_conversion.cpp,155685,6157086 +src/kfs_frontend/validation.cpp,149399,5934012 +src/kfserving_api/grpc_predict_v2.grpc.pb.cc,97595,3843178 +src/kfserving_api/grpc_predict_v2.pb.cc,78222,3024131 +src/layout.cpp,80135,2969143 +src/layout_configuration.cpp,75642,2781580 +src/llm/apis/openai_api_handler.cpp,116716,4385927 +src/llm/apis/openai_completions.cpp,116291,4372731 +src/llm/apis/openai_responses.cpp,108599,4138127 +src/llm/http_llm_calculator.cc,171717,7003657 +src/llm/io_processing/base_generation_config_builder.cpp,92733,3511233 +src/llm/io_processing/base_output_parser.cpp,83384,3113064 +src/llm/io_processing/devstral/generation_config_builder.cpp,82459,3076792 +src/llm/io_processing/devstral/tool_parser.cpp,99548,3728677 +src/llm/io_processing/gptoss/harmony.cpp,93760,3548998 +src/llm/io_processing/gptoss/reasoning_parser.cpp,93730,3548908 +src/llm/io_processing/gptoss/tool_parser.cpp,99527,3727578 +src/llm/io_processing/hermes3/generation_config_builder.cpp,82459,3076829 +src/llm/io_processing/hermes3/tool_parser.cpp,93862,3554105 +src/llm/io_processing/llama3/generation_config_builder.cpp,82459,3076798 +src/llm/io_processing/llama3/tool_parser.cpp,93810,3552545 +src/llm/io_processing/mistral/tool_parser.cpp,99583,3730367 +src/llm/io_processing/output_parser.cpp,94835,3591608 +src/llm/io_processing/partial_json_builder.cpp,39936,1460936 +src/llm/io_processing/phi4/generation_config_builder.cpp,82489,3077661 +src/llm/io_processing/phi4/tool_parser.cpp,99586,3730014 +src/llm/io_processing/qwen3/reasoning_parser.cpp,93610,3543691 +src/llm/io_processing/qwen3coder/qwen3coder_tool_parser.cpp,94626,3594937 +src/llm/io_processing/utils.cpp,33766,1269101 +src/llm/language_model/continuous_batching/servable.cpp,175919,7178482 +src/llm/language_model/continuous_batching/servable_initializer.cpp,177702,7248266 +src/llm/language_model/legacy/legacy_executor.cpp,176526,7191241 +src/llm/language_model/legacy/servable.cpp,177171,7221486 +src/llm/language_model/legacy/servable_initializer.cpp,177339,7231324 +src/llm/llm_calculator.pb.cc,79923,3090862 +src/llm/llm_node_initializer.cpp,174488,7119448 +src/llm/py_jinja_template_processor.cpp,156704,6308857 +src/llm/servable.cpp,172537,7035727 +src/llm/servable_initializer.cpp,182366,7396438 +src/llm/visual_language_model/continuous_batching/servable.cpp,175398,7160750 +src/llm/visual_language_model/legacy/legacy_executor.cpp,176657,7197027 +src/llm/visual_language_model/legacy/servable.cpp,177639,7241761 +src/llm/visual_language_model/legacy/servable_initializer.cpp,177458,7236149 +src/logging.cpp,71577,2632013 +src/main.cpp,40860,1464184 +src/main_benchmark.cpp,81265,2842249 +src/main_capi.cpp,40326,1414764 +src/mediapipe_internal/mediapipe_utils.cpp,71997,2633118 +src/mediapipe_internal/mediapipefactory.cpp,147634,5780734 +src/mediapipe_internal/mediapipegraphconfig.cpp,89137,3281049 +src/mediapipe_internal/mediapipegraphdefinition.cpp,162282,6374585 +src/mediapipe_internal/mediapipegraphexecutor.cpp,157605,6358250 +src/mediapipe_internal/node_initializer.cpp,59210,2171094 +src/metrics/metric.cpp,30559,1081714 +src/metrics/metric_config.cpp,90566,3407258 +src/metrics/metric_family.cpp,38692,1361062 +src/metrics/metric_module.cpp,61490,2245762 +src/metrics/metric_registry.cpp,37773,1326400 +src/model.cpp,103296,3837211 +src/model_metric_reporter.cpp,74422,2829005 +src/model_service.cpp,139517,5560823 +src/model_version_policy.cpp,44713,1528374 +src/modelchangesubscription.cpp,70590,2584974 +src/modelconfig.cpp,102013,3872283 +src/modelextensions.cpp,6670,219486 +src/modelinstance.cpp,119318,4467473 +src/modelinstanceunloadguard.cpp,87396,3282544 +src/modelmanager.cpp,173537,6882928 +src/modelversionstatus.cpp,70057,2568469 +src/module_names.cpp,17387,639220 +src/net_http_async_writer_impl.cpp,152067,6226378 +src/network_utils.cpp,68289,2517076 +src/ocl_utils.cpp,95434,3550217 +src/opencltensorfactory.cpp,96344,3584762 +src/outputkeeper.cpp,79868,2959519 +src/ov_utils.cpp,86164,3199805 +src/ovinferrequestsqueue.cpp,88145,3263006 +src/precision.cpp,64312,2330997 +src/precision_configuration.cpp,76626,2831699 +src/predict_request_validation_utils_impl.cpp,80165,2969382 +src/prediction_service.cpp,275939,11390731 +src/profiler.cpp,17471,641855 +src/profilermodule.cpp,71768,2639438 +src/pull_module/cmd_exec.cpp,42787,1484762 +src/pull_module/gguf_downloader.cpp,106813,4021732 +src/pull_module/hf_pull_model_module.cpp,79933,2963208 +src/pull_module/libgit2.cpp,88854,3234750 +src/pull_module/model_downloader.cpp,83494,3011350 +src/pull_module/optimum_export.cpp,86324,3120699 +src/python/binding/ovms_py_tensor.cpp,78636,3097775 +src/python/ovms_py_tensor.cpp,67035,2550183 +src/python/pytensor_ovtensor_converter_calculator.cc,166732,6769211 +src/python/pytensor_ovtensor_converter_calculator.pb.cc,76659,2954025 +src/python/python_backend.cpp,93078,3654813 +src/python/python_executor_calculator.cc,156960,6322341 +src/python/python_executor_calculator.pb.cc,75606,2893864 +src/python/python_node_initializer.cpp,153986,6076239 +src/python/pythoninterpretermodule.cpp,93746,3676231 +src/python/pythonnoderesources.cpp,156035,6164402 +src/regularovtensorfactory.cpp,85351,3171328 +src/rerank/rerank_calculator.cc,156159,6172068 +src/rerank/rerank_calculator.pb.cc,75625,2893165 +src/rerank/rerank_calculator_ov.cc,165143,6471632 +src/rerank/rerank_calculator_ov.pb.cc,75983,2909743 +src/rerank/rerank_node_initializer.cpp,162218,6336177 +src/rerank/rerank_utils.cpp,97825,3699705 +src/rest_parser.cpp,272790,11335012 +src/rest_utils.cpp,273548,11370549 +src/schema.cpp,93080,3494623 +src/sequence.cpp,85927,3188386 +src/sequence_manager.cpp,78136,2898244 +src/serialization_common.cpp,80362,2976857 +src/servable_definition_unload_guard.cpp,62143,2274854 +src/servablemanagermodule.cpp,89588,3369148 +src/servables_config_manager_module/listmodels.cpp,84416,3048161 +src/servables_config_manager_module/servablesconfigmanagermodule.cpp,76731,2819784 +src/server.cpp,282053,11533213 +src/shape.cpp,78037,2891615 +src/sidepacket_servable.cpp,162334,6350928 +src/single_version_servable_definition.cpp,72016,2647780 +src/statefulmodelinstance.cpp,98420,3704571 +src/status.cpp,56603,2117801 +src/stringutils.cpp,45491,1640178 +src/systeminfo.cpp,72259,2635270 +src/tensor_conversion.cpp,111519,4174645 +src/tensor_conversion_common.cpp,104794,3919746 +src/tensorinfo.cpp,79963,2963962 +src/tfs_frontend/deserialization.cpp,261159,10763800 +src/tfs_frontend/serialization.cpp,261287,10769114 +src/tfs_frontend/tensor_conversion.cpp,265557,10943123 +src/tfs_frontend/tfs_backend_impl.cpp,269285,11150166 +src/tfs_frontend/tfs_request_utils.cpp,155248,6193433 +src/tfs_frontend/tfs_utils.cpp,260990,10755162 +src/tfs_frontend/validation.cpp,261529,10791668 +src/tokenize/tokenize_parser.cpp,91200,3436603 +src/utils/env_guard.cpp,68891,2537890 +src/utils/rapidjson_utils.cpp,32645,1241966 +src/vaapitensorfactory.cpp,100230,3717145 +src/version.cpp,75014,2737282 diff --git a/tools/build_metrics/measure_build_graph.py b/tools/build_metrics/measure_build_graph.py new file mode 100644 index 0000000000..baab166ec5 --- /dev/null +++ b/tools/build_metrics/measure_build_graph.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +Measure transitive source file count and change impact per source file. + +Computes two metrics from a single Bazel XML query: + + Metric 3: Transitive Source Files (trans_src_count) + For each source file, counts total .cpp/.cc files in the transitive + dependency closure of its Bazel target. Unlike the target-count metric, + this is immune to the artifact where splitting one target into several + inflates the count without changing actual build complexity. + + Metric 4: Change Impact / Reverse Deps (impacted_srcs) + For each source file, counts how many source files would need to + recompile if its Bazel target is modified. Computed via reverse + dependency graph traversal. Measures incremental build blast radius. + +Output CSV 1 (trans_srcs): file, target, trans_src_count +Output CSV 2 (change_impact): file, target, rdep_targets, impacted_srcs + +Usage: + python3 tools/measure_build_graph.py [trans_srcs.csv] [change_impact.csv] + +Must be run where bazel is available (e.g. inside the -build container). +""" + +import subprocess +import sys +import xml.etree.ElementTree as ET +from collections import defaultdict + + +def run_bazel_query(query_expr, output_format="label"): + """Run a bazel query and return stdout.""" + cmd = ["bazel", "query", query_expr, f"--output={output_format}", + "--noimplicit_deps", "--keep_going"] + result = subprocess.run(cmd, capture_output=True, text=True) + return result.stdout + + +def parse_xml_rules(xml_text): + """ + Parse bazel query XML output. + Returns dict: {target_label: {"srcs": [...], "deps": [...]}} + """ + rules = {} + try: + root = ET.fromstring(xml_text) + except ET.ParseError as e: + print(f"WARNING: XML parse error: {e}", file=sys.stderr) + return rules + + for rule in root.iter("rule"): + label = rule.get("name", "") + if not label: + continue + + srcs = [] + deps = [] + + for attr_list in rule.iter("list"): + attr_name = attr_list.get("name", "") + if attr_name == "srcs": + for item in attr_list.iter("label"): + val = item.get("value", "") + if val: + srcs.append(val) + elif attr_name in ("deps", "implementation_deps"): + for item in attr_list.iter("label"): + val = item.get("value", "") + if val: + deps.append(val) + + for attr_label in rule.iter("label"): + attr_name = attr_label.get("name", "") + if attr_name == "deps" and attr_label.get("value"): + deps.append(attr_label.get("value")) + + rules[label] = {"srcs": srcs, "deps": deps} + + return rules + + +def transitive_closure(graph, start, cache): + """Compute set of all nodes reachable from start (including start).""" + if start in cache: + return cache[start] + cache[start] = set() # cycle guard + result = {start} + for neighbor in graph.get(start, []): + result |= transitive_closure(graph, neighbor, cache) + cache[start] = result + return result + + +def count_src_files(rules, targets): + """Count .cpp/.cc/.cxx source files across a set of targets.""" + count = 0 + for t in targets: + if t in rules: + count += sum(1 for s in rules[t]["srcs"] + if s.endswith((".cpp", ".cc", ".cxx"))) + return count + + +def normalize_src_path(src): + """Convert Bazel label to workspace-relative path.""" + path = src.replace("//", "").replace(":", "/") + if path.startswith("/"): + path = path[1:] + return path + + +def main(): + trans_output = sys.argv[1] if len(sys.argv) > 1 else "trans_srcs.csv" + impact_output = sys.argv[2] if len(sys.argv) > 2 else "change_impact.csv" + + print("=== Build Graph Metrics (Trans Source Files + Change Impact) ===") + print(f"Output 1 (trans source files): {trans_output}") + print(f"Output 2 (change impact): {impact_output}") + print() + + sys.setrecursionlimit(10000) + + # Step 1: Get all targets (including tests — needed for rdep analysis) + print("Step 1: Querying all targets in //src/... ...") + target_query = 'kind("cc_library|cc_binary|cc_test", //src/...)' + targets_text = run_bazel_query(target_query, "label") + all_targets = [t.strip() for t in targets_text.strip().split("\n") if t.strip()] + print(f" Found {len(all_targets)} targets") + + # Step 2: Get rules with their deps/srcs via XML. + # We query ONLY //src/... rules (no deps() expansion) to avoid + # pulling in massive external dep trees. The resulting graph is + # internal-only, which is exactly what we want for counting + # internal source files. + print("Step 2: Querying rule definitions (single XML query)...") + xml_text = run_bazel_query(target_query, "xml") + print(f" XML response: {len(xml_text)} bytes") + + rules = parse_xml_rules(xml_text) + print(f" Parsed {len(rules)} rules") + + # Step 3: Build forward and reverse graphs (internal edges only) + print("Step 3: Building dependency graphs...") + internal_targets = set(rules.keys()) + forward_graph = {} + reverse_graph = defaultdict(list) + for target, info in rules.items(): + # Only follow edges to other internal (//src) targets + internal_deps = [d for d in info["deps"] if d in internal_targets] + forward_graph[target] = internal_deps + for dep in internal_deps: + reverse_graph[dep].append(target) + + # Step 4: Compute metrics per target, then expand to per-file + print("Step 4: Computing metrics per source file...") + forward_cache = {} + reverse_cache = {} + + trans_results = [] + impact_results = [] + + for target in sorted(all_targets): + if target not in rules: + continue + + cpp_srcs = [s for s in rules[target]["srcs"] + if s.endswith((".cpp", ".cc", ".cxx"))] + if not cpp_srcs: + continue + + # Forward: transitive source file count + fwd_targets = transitive_closure(forward_graph, target, forward_cache) + trans_src_count = count_src_files(rules, fwd_targets) + + # Reverse: change impact (blast radius) + rev_targets = transitive_closure(reverse_graph, target, reverse_cache) + impacted_src_count = count_src_files(rules, rev_targets) + rdep_target_count = sum(1 for t in rev_targets + if t != target and t in rules) + + for src in cpp_srcs: + filepath = normalize_src_path(src) + trans_results.append({ + "file": filepath, + "target": target, + "trans_src_count": trans_src_count, + }) + impact_results.append({ + "file": filepath, + "target": target, + "rdep_targets": rdep_target_count, + "impacted_srcs": impacted_src_count, + }) + + # Step 5: Write CSVs + print(f"\nStep 5: Writing {len(trans_results)} entries...") + + with open(trans_output, "w") as f: + f.write("file,target,trans_src_count\n") + for r in sorted(trans_results, key=lambda x: x["file"]): + f.write(f"{r['file']},{r['target']},{r['trans_src_count']}\n") + print(f" Wrote {trans_output}") + + with open(impact_output, "w") as f: + f.write("file,target,rdep_targets,impacted_srcs\n") + for r in sorted(impact_results, key=lambda x: x["file"]): + f.write(f"{r['file']},{r['target']},{r['rdep_targets']}," + f"{r['impacted_srcs']}\n") + print(f" Wrote {impact_output}") + + # Summary + if not trans_results: + print("\nWARNING: No results generated!") + return + + trans_vals = sorted(r["trans_src_count"] for r in trans_results) + impact_vals = sorted(r["impacted_srcs"] for r in impact_results) + + print() + print("=== Summary: Transitive Source Files ===") + print(f" Files: {len(trans_vals)}") + print(f" Average: {sum(trans_vals) / len(trans_vals):.1f}") + print(f" Median: {trans_vals[len(trans_vals) // 2]}") + print(f" Max: {max(trans_vals)}") + + print() + print(" Distribution:") + for lo, hi, label in [ + (201, None, ">200"), + (101, 200, "101-200"), + (51, 100, "51-100"), + (21, 50, "21-50"), + (0, 20, "0-20"), + ]: + if hi is None: + count = sum(1 for v in trans_vals if v > lo - 1) + else: + count = sum(1 for v in trans_vals if lo <= v <= hi) + print(f" {count:>6} files with {label:>8} trans srcs") + + print() + non_test_trans = [r for r in trans_results if "/test/" not in r["file"]] + print(" Top 10 by transitive source files (non-test):") + top_trans = sorted(non_test_trans, key=lambda r: -r["trans_src_count"])[:10] + for r in top_trans: + f = r["file"] + if len(f) > 55: + f = "..." + f[-52:] + print(f" {f:<55s} {r['trans_src_count']:>5} srcs ({r['target']})") + + print() + print("=== Summary: Change Impact ===") + print(f" Files: {len(impact_vals)}") + print(f" Average: {sum(impact_vals) / len(impact_vals):.1f}") + print(f" Median: {impact_vals[len(impact_vals) // 2]}") + print(f" Max: {max(impact_vals)}") + + print() + print(" Distribution:") + for lo, hi, label in [ + (501, None, ">500"), + (201, 500, "201-500"), + (101, 200, "101-200"), + (51, 100, "51-100"), + (0, 50, "0-50"), + ]: + if hi is None: + count = sum(1 for v in impact_vals if v > lo - 1) + else: + count = sum(1 for v in impact_vals if lo <= v <= hi) + print(f" {count:>6} files with {label:>8} impacted srcs") + + print() + print(" Top 10 by change impact:") + top_impact = sorted(impact_results, key=lambda r: -r["impacted_srcs"])[:10] + for r in top_impact: + f = r["file"] + if len(f) > 55: + f = "..." + f[-52:] + print(f" {f:<55s} {r['impacted_srcs']:>5} impacted " + f"({r['rdep_targets']} rdep targets)") + + print() + print(f"Saved to: {trans_output}, {impact_output}") + + +if __name__ == "__main__": + main() diff --git a/tools/build_metrics/measure_dep_fanin.py b/tools/build_metrics/measure_dep_fanin.py new file mode 100755 index 0000000000..ac5190946a --- /dev/null +++ b/tools/build_metrics/measure_dep_fanin.py @@ -0,0 +1,309 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +Fast dependency fan-in measurement using a SINGLE bazel query call. + +Instead of running O(n) individual `bazel query deps()` calls, +this script: + 1. Runs ONE `bazel query --output=xml` to get all rules with their + direct deps and srcs attributes. + 2. Builds the dependency graph in memory. + 3. Computes transitive dep counts per target in Python. + +This is orders of magnitude faster than the shell-based approach. + +Output CSV columns: + file, target, internal_deps, openvino, genai, tensorflow, mediapipe, + grpc, protobuf, other_external, total_deps + +Usage: + python3 tools/measure_dep_fanin.py [output.csv] + +Must be run where bazel is available (e.g. inside the -build container). +""" + +import subprocess +import sys +import xml.etree.ElementTree as ET +from collections import defaultdict + + +# External dep groups (binary: 0 or 1 per target) +EXTERNAL_GROUPS = { + "openvino": ["@linux_openvino", "@windows_openvino", "//third_party:openvino"], + "genai": ["@linux_genai", "@windows_genai", "//third_party:genai"], + "tensorflow": ["@org_tensorflow", "@tensorflow_serving"], + "mediapipe": ["@mediapipe"], + "grpc": ["@com_github_grpc_grpc"], + "protobuf": ["@com_google_protobuf"], +} + + +def run_bazel_query(query_expr, output_format="label"): + """Run a bazel query and return stdout.""" + cmd = ["bazel", "query", query_expr, f"--output={output_format}", + "--noimplicit_deps", "--keep_going"] + result = subprocess.run(cmd, capture_output=True, text=True) + # --keep_going may return non-zero but still produce useful output + return result.stdout + + +def parse_xml_rules(xml_text): + """ + Parse bazel query XML output. + Returns dict: {target_label: {"srcs": [...], "deps": [...]}} + """ + rules = {} + try: + root = ET.fromstring(xml_text) + except ET.ParseError as e: + print(f"WARNING: XML parse error: {e}", file=sys.stderr) + return rules + + for rule in root.iter("rule"): + label = rule.get("name", "") + if not label: + continue + + srcs = [] + deps = [] + + for attr_list in rule.iter("list"): + attr_name = attr_list.get("name", "") + if attr_name == "srcs": + for item in attr_list.iter("label"): + val = item.get("value", "") + if val: + srcs.append(val) + elif attr_name in ("deps", "implementation_deps"): + for item in attr_list.iter("label"): + val = item.get("value", "") + if val: + deps.append(val) + + # Also check singular attrs (non-list) + for attr_label in rule.iter("label"): + parent = attr_label + # label elements directly inside rule (not in list) + attr_name = attr_label.get("name", "") + if attr_name == "deps" and attr_label.get("value"): + deps.append(attr_label.get("value")) + + rules[label] = {"srcs": srcs, "deps": deps} + + return rules + + +def compute_transitive_deps(rules, target, cache=None): + """ + Compute the set of all transitive dependencies for a target. + Returns a set of labels (including the target itself). + """ + if cache is None: + cache = {} + if target in cache: + return cache[target] + + # Mark as in-progress to avoid cycles + cache[target] = set() + + result = {target} + if target in rules: + for dep in rules[target]["deps"]: + child_deps = compute_transitive_deps(rules, dep, cache) + result |= child_deps + + cache[target] = result + return result + + +def classify_dep(label): + """Classify a dependency label. Returns (group_name, is_internal).""" + for group, prefixes in EXTERNAL_GROUPS.items(): + for prefix in prefixes: + if label.startswith(prefix): + return group, False + + if label.startswith("//src"): + return "internal", True + + # Other external + return "other_external", False + + +def main(): + output = sys.argv[1] if len(sys.argv) > 1 else "deps_metrics.csv" + print(f"=== Dependency Fan-in Measurement (M1) ===") + print(f"Output: {output}") + print() + + # Step 1: Get all non-test targets in //src/... + print("Step 1: Querying all targets in //src/... ...") + targets_text = run_bazel_query( + 'kind("cc_library|cc_binary", //src/...) except kind("cc_test", //src/...)', + "label" + ) + all_targets = [t.strip() for t in targets_text.strip().split("\n") if t.strip()] + print(f" Found {len(all_targets)} targets") + + # Step 2: Get full rule definitions with deps and srcs via XML + # Query a broad set: all rules reachable from our targets + print("Step 2: Querying dependency graph (single XML query)...") + xml_text = run_bazel_query( + 'deps(kind("cc_library|cc_binary", //src/...) except kind("cc_test", //src/...))', + "xml" + ) + print(f" XML response: {len(xml_text)} bytes") + + rules = parse_xml_rules(xml_text) + print(f" Parsed {len(rules)} rules from XML") + + # Step 3: compute transitive deps per target + print("Step 3: Computing transitive dependencies...") + cache = {} + results = [] + + for target in sorted(all_targets): + if target not in rules: + continue + + srcs = rules[target]["srcs"] + cpp_srcs = [s for s in srcs if s.endswith((".cpp", ".cc", ".cxx"))] + if not cpp_srcs: + continue + + trans_deps = compute_transitive_deps(rules, target, cache) + # Remove self + trans_deps = trans_deps - {target} + + # Classify + internal_count = 0 + group_flags = {g: 0 for g in EXTERNAL_GROUPS} + other_repos = set() + + for dep in trans_deps: + group, is_internal = classify_dep(dep) + if is_internal: + internal_count += 1 + elif group in EXTERNAL_GROUPS: + group_flags[group] = 1 + else: + # Count unique external repos + if dep.startswith("@"): + repo = dep.split("//")[0] + other_repos.add(repo) + elif dep.startswith("//third_party:"): + other_repos.add(dep) + elif dep.startswith("//:"): + other_repos.add(dep) + + other_external = len(other_repos) + total = (internal_count + + sum(group_flags.values()) + + other_external) + + for src in cpp_srcs: + # Normalize src label to path + filepath = src.replace("//", "").replace(":", "/") + if filepath.startswith("/"): + filepath = filepath[1:] + + results.append({ + "file": filepath, + "target": target, + "internal_deps": internal_count, + "openvino": group_flags["openvino"], + "genai": group_flags["genai"], + "tensorflow": group_flags["tensorflow"], + "mediapipe": group_flags["mediapipe"], + "grpc": group_flags["grpc"], + "protobuf": group_flags["protobuf"], + "other_external": other_external, + "total_deps": total, + }) + + # Step 4: Write CSV + print(f"Step 4: Writing {len(results)} entries to {output}") + with open(output, "w") as f: + f.write("file,target,internal_deps,openvino,genai,tensorflow," + "mediapipe,grpc,protobuf,other_external,total_deps\n") + for r in sorted(results, key=lambda x: x["file"]): + f.write(f"{r['file']},{r['target']},{r['internal_deps']}," + f"{r['openvino']},{r['genai']},{r['tensorflow']}," + f"{r['mediapipe']},{r['grpc']},{r['protobuf']}," + f"{r['other_external']},{r['total_deps']}\n") + + # Summary + if not results: + print("\nWARNING: No results generated!") + return + + total_deps_vals = sorted(r["total_deps"] for r in results) + int_deps_vals = sorted(r["internal_deps"] for r in results) + avg_total = sum(total_deps_vals) / len(total_deps_vals) + avg_int = sum(int_deps_vals) / len(int_deps_vals) + median_total = total_deps_vals[len(total_deps_vals) // 2] + max_entry = max(results, key=lambda x: x["total_deps"]) + + print() + print("=== Summary ===") + print(f"Files: {len(results)}") + print(f"Unique targets: {len(set(r['target'] for r in results))}") + print(f"Avg total deps/file: {avg_total:.1f}") + print(f"Avg internal deps: {avg_int:.1f}") + print(f"Median total deps: {median_total}") + print(f"Max total deps: {max_entry['total_deps']} ({max_entry['file']})") + print() + + # Distribution + print("Distribution:") + buckets = [ + (">200", lambda v: v > 200), + ("101-200", lambda v: 101 <= v <= 200), + ("91-100", lambda v: 91 <= v <= 100), + ("81-90", lambda v: 81 <= v <= 90), + ("71-80", lambda v: 71 <= v <= 80), + ("61-70", lambda v: 61 <= v <= 70), + ("51-60", lambda v: 51 <= v <= 60), + ("41-50", lambda v: 41 <= v <= 50), + ("31-40", lambda v: 31 <= v <= 40), + ("21-30", lambda v: 21 <= v <= 30), + ("11-20", lambda v: 11 <= v <= 20), + ("0-10", lambda v: v <= 10), + ] + for label, pred in buckets: + count = sum(1 for v in total_deps_vals if pred(v)) + print(f" {count:>6} files with {label:>8} deps") + + print() + print("Top 10 files by dependency count:") + top = sorted(results, key=lambda x: -x["total_deps"])[:10] + for r in top: + f = r["file"] + if len(f) > 55: + f = "..." + f[-52:] + print(f" {f:<55s} {r['total_deps']:>4} deps " + f"(int:{r['internal_deps']} ov:{r['openvino']} ga:{r['genai']} " + f"tf:{r['tensorflow']} mp:{r['mediapipe']} gr:{r['grpc']} " + f"pb:{r['protobuf']} ext_other:{r['other_external']})") + + print() + print(f"Saved to: {output}") + + +if __name__ == "__main__": + main() diff --git a/tools/build_metrics/measure_header_fanin.py b/tools/build_metrics/measure_header_fanin.py new file mode 100644 index 0000000000..9c181970ba --- /dev/null +++ b/tools/build_metrics/measure_header_fanin.py @@ -0,0 +1,299 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +Measure header fan-in: count unique headers included per translation unit. + +Uses bazel aquery to extract compile commands, then runs the compiler +with -M flag to get the exact dependency list (all headers resolved via +real include paths, defines, and conditional compilation). + +Output CSV columns: + file, unique_headers, unique_project_headers + + unique_headers: total unique header files (project + external + system) + unique_project_headers: headers from src/ and generated from src/ protos + +Prerequisites: + - Must run where bazel is available (e.g. inside the -build container) + - A successful 'bazel build //src:ovms' should have been done first + so that generated headers (.pb.h etc.) and external repos exist. + +Usage: + python3 tools/measure_header_fanin.py [output.csv] [bazel_target] +""" + +import json +import os +import re +import subprocess +import sys + + +def get_execroot(): + """Get the bazel execution root directory.""" + result = subprocess.run( + ["bazel", "info", "execution_root"], + capture_output=True, text=True, + ) + if result.returncode != 0: + print(f"ERROR: 'bazel info execution_root' failed: {result.stderr}", + file=sys.stderr) + sys.exit(1) + return result.stdout.strip() + + +def get_compile_actions(target): + """Run bazel aquery and return parsed JSON. + We query the target directly (no deps() expansion) so that only + compile actions for OVMS source files are returned, not for + transitive external dependencies (gRPC, protobuf, etc.).""" + cmd = [ + "bazel", "aquery", + f'mnemonic("CppCompile", {target})', + "--output=jsonproto", + "--keep_going", + ] + result = subprocess.run(cmd, capture_output=True, text=True) + if not result.stdout.strip(): + print(f"ERROR: bazel aquery produced no output:\n{result.stderr}", + file=sys.stderr) + sys.exit(1) + try: + return json.loads(result.stdout) + except json.JSONDecodeError as e: + print(f"ERROR: Failed to parse aquery JSON: {e}", file=sys.stderr) + sys.exit(1) + + +def make_depfile_args(arguments): + """ + Modify a CppCompile argument list to generate dependency info (-M). + Returns (source_file, modified_args) or (None, None) on failure. + """ + source = None + new_args = [] + skip_next = False + + for i, arg in enumerate(arguments): + if skip_next: + skip_next = False + continue + + # Replace -c with -M (dependency generation, no compilation) + if arg == "-c": + new_args.append("-M") + continue + + # Drop -o + if arg == "-o": + skip_next = True + continue + + # Drop -MD / -MF / dependency-file related flags + if arg in ("-MD", "-MMD"): + continue + if arg in ("-MF", "-MQ", "-MT"): + skip_next = True + continue + + new_args.append(arg) + + # Identify source file + if not arg.startswith("-") and re.search(r"\.(cpp|cc|cxx|c)$", arg): + source = arg + + if not source: + return None, None + + return source, new_args + + +def normalize_path(path): + """Normalize to workspace-relative path like src/foo.cpp.""" + match = re.search(r"(src/.+\.(cpp|cc|cxx|c))$", path) + if match: + return match.group(1) + for prefix in ("./", "bazel-out/", "../"): + if path.startswith(prefix): + path = path[len(prefix):] + return path + + +def parse_dep_output(output_text): + """ + Parse Makefile-format dependency output from -M flag. + Returns set of unique dependency file paths (excluding the target .o). + """ + # Join continuation lines (backslash-newline) + text = output_text.replace("\\\n", " ").replace("\\\r\n", " ") + + # Split on first colon to separate target from prerequisites + parts = text.split(":", 1) + if len(parts) < 2: + return set() + + prereqs_text = parts[1].strip() + prereqs = prereqs_text.split() + + return set(prereqs) + + +def is_project_header(path): + """Check if a header path is from the project (src/ or generated from src/).""" + return (path.startswith("src/") or + (path.startswith("bazel-out/") and "/bin/src/" in path)) + + +def run_depfile(args, execroot): + """Run compiler with -M and return set of dependency paths.""" + try: + result = subprocess.run( + args, + cwd=execroot, + capture_output=True, + text=True, + timeout=120, + ) + if result.returncode != 0: + return set() + return parse_dep_output(result.stdout) + except (subprocess.TimeoutExpired, OSError): + return set() + + +def main(): + output = sys.argv[1] if len(sys.argv) > 1 else "header_fanin.csv" + target = sys.argv[2] if len(sys.argv) > 2 else "//src/..." + + print("=== Header Fan-in Measurement ===") + print(f"Target: {target}") + print(f"Output: {output}") + print() + + execroot = get_execroot() + print(f"Execroot: {execroot}") + + print("Running bazel aquery...") + data = get_compile_actions(target) + + actions = data.get("actions", []) + compile_actions = [a for a in actions if a.get("mnemonic") == "CppCompile"] + print(f"CppCompile actions: {len(compile_actions)}") + print() + + results = [] + failures = [] + + for action in compile_actions: + arguments = action.get("arguments", []) + if not arguments: + continue + + source, dep_args = make_depfile_args(arguments) + if not source: + continue + + # Skip external dependency sources + if "external/" in source: + continue + + src_path = normalize_path(source) + + deps = run_depfile(dep_args, execroot) + + if not deps: + failures.append(src_path) + else: + # Remove the source file itself — deps includes source + all headers + headers = {p for p in deps if p != source} + # Also filter by basename match in case of path variations + source_base = os.path.basename(source) + headers = {h for h in headers + if os.path.basename(h) != source_base + or not h.endswith((".cpp", ".cc", ".cxx", ".c"))} + + unique_total = len(headers) + unique_project = sum(1 for h in headers if is_project_header(h)) + + results.append((src_path, unique_total, unique_project)) + + done = len(results) + len(failures) + if done % 500 == 0: + print(f" Processed {done} files...", flush=True) + + # Write CSV + with open(output, "w") as f: + f.write("file,unique_headers,unique_project_headers\n") + for src, total, project in sorted(results): + f.write(f"{src},{total},{project}\n") + + # Summary + if not results: + print("\nWARNING: No files were successfully measured!") + print("Make sure you have done a successful build first.") + if failures: + print(f"Failed files ({len(failures)}):") + for fp in failures[:10]: + print(f" {fp}") + return + + totals = sorted(r[1] for r in results) + projects = sorted(r[2] for r in results) + + print() + print("=== Summary ===") + print(f"Files measured: {len(results)}") + if failures: + print(f"Files failed: {len(failures)}") + print(f"Avg unique headers: {sum(totals) / len(totals):.0f}") + print(f"Median unique headers: {totals[len(totals) // 2]}") + print(f"Max unique headers: {max(totals)}") + print() + print(f"Avg project headers: {sum(projects) / len(projects):.0f}") + print(f"Median project headers: {projects[len(projects) // 2]}") + print(f"Max project headers: {max(projects)}") + + print() + print("Distribution (unique headers):") + for lo, hi, label in [ + (2001, None, ">2000"), + (1001, 2000, "1001-2000"), + (501, 1000, "501-1000"), + (201, 500, "201-500"), + (101, 200, "101-200"), + (0, 100, "0-100"), + ]: + if hi is None: + count = sum(1 for v in totals if v > lo - 1) + else: + count = sum(1 for v in totals if lo <= v <= hi) + print(f" {count:>6} files with {label:>10} headers") + + print() + print("Top 10 files by unique header count:") + top = sorted(results, key=lambda r: -r[1])[:10] + for src, total, project in top: + if len(src) > 55: + src = "..." + src[-52:] + print(f" {src:<55s} {total:>6} headers ({project} project)") + + print() + print(f"Saved to: {output}") + + +if __name__ == "__main__": + main() diff --git a/tools/build_metrics/measure_tu_sizes.py b/tools/build_metrics/measure_tu_sizes.py new file mode 100755 index 0000000000..5a58ad77b1 --- /dev/null +++ b/tools/build_metrics/measure_tu_sizes.py @@ -0,0 +1,280 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +""" +Measure translation unit sizes by extracting compile commands from +bazel aquery and re-running the preprocessor (-E -P). + +This gives accurate preprocessed sizes because it uses the exact same +include paths, defines, and flags that bazel uses for the real build. + +Prerequisites: + - Must run where bazel is available (e.g. inside the -build container) + - A successful 'bazel build //src:ovms' should have been done first + so that generated headers (.pb.h etc.) and external repos exist. + +Usage: + python3 tools/measure_tu_sizes.py [output.csv] [bazel_target] + + output.csv : Output CSV (default: tu_sizes.csv) + bazel_target : Target to analyze (default: //src/...) +""" + +import json +import subprocess +import sys +import os +import re + + +def get_execroot(): + result = subprocess.run( + ["bazel", "info", "execution_root"], + capture_output=True, text=True + ) + if result.returncode != 0: + print(f"ERROR: 'bazel info execution_root' failed: {result.stderr}", + file=sys.stderr) + sys.exit(1) + return result.stdout.strip() + + +def get_compile_actions(target): + """Run bazel aquery and return parsed JSON. + We query the target directly (no deps() expansion) so that only + compile actions for OVMS source files are returned, not for + transitive external dependencies (gRPC, protobuf, etc.).""" + cmd = [ + "bazel", "aquery", + f'mnemonic("CppCompile", {target})', + "--output=jsonproto", + "--keep_going", + ] + result = subprocess.run(cmd, capture_output=True, text=True) + if not result.stdout.strip(): + print(f"ERROR: bazel aquery produced no output:\n{result.stderr}", + file=sys.stderr) + sys.exit(1) + if result.returncode != 0: + print(f"WARNING: bazel aquery returned non-zero but produced output, " + f"continuing...", file=sys.stderr) + try: + return json.loads(result.stdout) + except json.JSONDecodeError as e: + print(f"ERROR: Failed to parse aquery JSON: {e}", file=sys.stderr) + sys.exit(1) + + +def make_preprocess_args(arguments): + """ + Modify a CppCompile argument list to preprocess instead of compile. + Returns (source_file, modified_args) or (None, None) on failure. + """ + source = None + new_args = [] + skip_next = False + + for i, arg in enumerate(arguments): + if skip_next: + skip_next = False + continue + + # Replace -c with -E -P (preprocess only, no line markers) + if arg == "-c": + new_args.extend(["-E", "-P"]) + continue + + # Drop -o since we want stdout + if arg == "-o": + skip_next = True + continue + + # Drop -MD / -MF / dependency-file related flags + if arg in ("-MD", "-MMD"): + continue + if arg in ("-MF", "-MQ", "-MT"): + skip_next = True + continue + + new_args.append(arg) + + # Identify source file + if not arg.startswith("-") and re.search(r"\.(cpp|cc|cxx|c)$", arg): + source = arg + + if not source: + return None, None + + return source, new_args + + +def normalize_path(path): + """Normalize to workspace-relative path like src/foo.cpp.""" + # Handle paths like: external/.../src/foo.cpp or just src/foo.cpp + match = re.search(r"(src/.+\.(cpp|cc|cxx|c))$", path) + if match: + return match.group(1) + # Fallback: strip common prefixes + for prefix in ("./", "bazel-out/", "../"): + if path.startswith(prefix): + path = path[len(prefix):] + return path + + +def preprocess_and_measure(args, execroot): + """Run the preprocessor and return (line_count, byte_count).""" + try: + result = subprocess.run( + args, + cwd=execroot, + capture_output=True, + timeout=300, + ) + if result.returncode != 0: + return 0, 0 + pp_lines = result.stdout.count(b"\n") + pp_bytes = len(result.stdout) + return pp_lines, pp_bytes + except (subprocess.TimeoutExpired, OSError) as e: + return 0, 0 + + +def main(): + output = sys.argv[1] if len(sys.argv) > 1 else "tu_sizes.csv" + target = sys.argv[2] if len(sys.argv) > 2 else "//src/..." + + print(f"=== Translation Unit Size Measurement ===") + print(f"Target: {target}") + print(f"Output: {output}") + print() + + execroot = get_execroot() + print(f"Execroot: {execroot}") + + print("Running bazel aquery (analysis only, no build)...") + data = get_compile_actions(target) + + actions = data.get("actions", []) + print(f"Found {len(actions)} total actions") + + # Filter to only CppCompile (aquery mnemonic filter should handle this, + # but double-check in case of format differences) + compile_actions = [ + a for a in actions + if a.get("mnemonic") == "CppCompile" + ] + print(f"CppCompile actions: {len(compile_actions)}") + print() + + results = [] + failures = [] + + for i, action in enumerate(compile_actions): + arguments = action.get("arguments", []) + if not arguments: + continue + + source, pp_args = make_preprocess_args(arguments) + if not source: + continue + + # Skip external dependency sources (safety net) + if "external/" in source: + continue + + src_path = normalize_path(source) + + # Skip test files + if "/test/" in src_path or "test_" in os.path.basename(src_path): + continue + + pp_lines, pp_bytes = preprocess_and_measure(pp_args, execroot) + + if pp_lines == 0: + failures.append(src_path) + else: + results.append((src_path, pp_lines, pp_bytes)) + + done = len(results) + len(failures) + if done % 500 == 0: + print(f" Processed {done} files...", flush=True) + + # Write CSV + with open(output, "w") as f: + f.write("file,pp_lines,pp_bytes\n") + for src, lines, nbytes in sorted(results): + f.write(f"{src},{lines},{nbytes}\n") + + # Summary + if not results: + print("\nWARNING: No files were successfully preprocessed!") + print("Make sure you have done a successful build first.") + if failures: + print(f"Failed files ({len(failures)}):") + for fp in failures[:10]: + print(f" {fp}") + return + + total_lines = sum(r[1] for r in results) + total_bytes = sum(r[2] for r in results) + avg_lines = total_lines // len(results) + lines_sorted = sorted(r[1] for r in results) + median_lines = lines_sorted[len(lines_sorted) // 2] + max_entry = max(results, key=lambda r: r[1]) + + print() + print(f"=== Summary ===") + print(f"Files measured: {len(results)}") + if failures: + print(f"Files failed: {len(failures)}") + print(f"Total PP lines: {total_lines:>12,}") + print(f"Total PP bytes: {total_bytes:>12,} ({total_bytes/1024/1024:.1f} MB)") + print(f"Average PP lines: {avg_lines:>12,}") + print(f"Median PP lines: {median_lines:>12,}") + print(f"Max PP lines: {max_entry[1]:>12,} ({max_entry[0]})") + + print() + print(f"Distribution:") + thresholds = [ + (200000, ">200K"), + (100000, "100K-200K"), + (50000, "50K-100K"), + (20000, "20K-50K"), + (0, "0-20K"), + ] + for thresh, label in thresholds: + if thresh == 0: + count = sum(1 for r in results if r[1] <= 20000) + elif thresh == 200000: + count = sum(1 for r in results if r[1] > 200000) + else: + lo = thresh + hi = thresholds[thresholds.index((thresh, label)) - 1][0] + count = sum(1 for r in results if lo < r[1] <= hi) + print(f" {count:>6} files with {label:>10} lines") + + print() + print("Top 10 largest translation units:") + top = sorted(results, key=lambda r: r[1], reverse=True)[:10] + for src, lines, nbytes in top: + print(f" {src:<55} {lines:>10,} lines {nbytes/1024:>8,.0f} KB") + + print() + print(f"Saved to: {output}") + + +if __name__ == "__main__": + main()