From a94e16b26e346605504b0425c91a58fa02560dc8 Mon Sep 17 00:00:00 2001 From: Peter Staar Date: Fri, 7 Aug 2026 15:31:36 +0200 Subject: [PATCH 1/9] feat: improving performance and robustness Signed-off-by: Peter Staar --- .github/workflows/wheels.yml | 8 + local_build.py | 2 + perf/run_eval.py | 25 +- perf/run_scaling.py | 56 +++ scripts/check_no_blend2d_assertions.py | 71 ++++ src/parse.h | 1 + src/parse/pdf_decoders/stream.h | 9 +- src/parse/pdf_resources/page_font.h | 528 ++++++++++--------------- src/parse/pdf_resources/page_fonts.h | 5 +- src/parse/qpdf/object.h | 203 ++++++++++ 10 files changed, 563 insertions(+), 345 deletions(-) create mode 100644 scripts/check_no_blend2d_assertions.py create mode 100644 src/parse/qpdf/object.h diff --git a/.github/workflows/wheels.yml b/.github/workflows/wheels.yml index 85b7d307..25218f64 100644 --- a/.github/workflows/wheels.yml +++ b/.github/workflows/wheels.yml @@ -147,6 +147,8 @@ jobs: uv run python -m zipfile --list "$file" | grep \\.so echo "Checking if the correct python version is contained in the wheel" uv run python -m zipfile --list "$file" | grep ${PY_CACHE_TAG} + echo "Checking that Blend2D debug assertions are not present" + uv run python scripts/check_no_blend2d_assertions.py "$file" done mkdir -p ./dist cp wheelhouse/*.whl ./dist/ @@ -200,6 +202,8 @@ jobs: uv run python -m zipfile --list "$file" | grep \\.so echo "Checking if the correct python version is contained in the wheel" uv run python -m zipfile --list "$file" | grep ${PY_CACHE_TAG} + echo "Checking that Blend2D debug assertions are not present" + uv run python scripts/check_no_blend2d_assertions.py "$file" done mkdir -p ./dist cp wheelhouse/*.whl ./dist/ @@ -243,6 +247,8 @@ jobs: uv run python -m zipfile --list "$file" | grep \\.so echo "Checking if the correct python version is contained in the wheel" uv run python -m zipfile --list "$file" | grep ${PY_CACHE_TAG} + echo "Checking that Blend2D debug assertions are not present" + uv run python scripts/check_no_blend2d_assertions.py "$file" done mkdir -p ./dist cp wheelhouse/*.whl ./dist/ @@ -348,6 +354,8 @@ jobs: $file = $_.FullName Write-Output "Inspecting $file" uv run python -m zipfile --list "$file" + Write-Output "Checking that Blend2D debug assertions are not present" + uv run python scripts/check_no_blend2d_assertions.py "$file" } if (-not (Test-Path -Path .\dist)) { New-Item -Path .\dist -ItemType Directory diff --git a/local_build.py b/local_build.py index fdbcb5d4..8c3dc5b3 100644 --- a/local_build.py +++ b/local_build.py @@ -92,12 +92,14 @@ def run(cmd: List[str], cwd: str="./"): def build_local(num_threads: int): USE_SYSTEM_DEPS = os.getenv("USE_SYSTEM_DEPS", "OFF") + CMAKE_BUILD_TYPE = os.getenv("CMAKE_BUILD_TYPE", "Release") print("python prefix: ", sys.exec_prefix) print("python executable: ", sys.executable) config_cmd = [ "cmake", "-B", f"{BUILD_DIR}", + f"-DCMAKE_BUILD_TYPE={CMAKE_BUILD_TYPE}", f"-DUSE_SYSTEM_DEPS={USE_SYSTEM_DEPS}", f"-DPYTHON_EXECUTABLE={sys.executable}", ] diff --git a/perf/run_eval.py b/perf/run_eval.py index 332701bc..ea31700d 100644 --- a/perf/run_eval.py +++ b/perf/run_eval.py @@ -324,12 +324,12 @@ def plot_histograms_stacked( def _hex_pairs_to_plot( per_series_rows: Dict[str, List[PageRow]], ) -> List[Tuple[str, str]]: - """docling-parse at one thread against every other package, per task. + """docling-parse against every other package, per task. Pairs never cross tasks --- a `parse` time against a `parse+render` time is - not a like-for-like page. Other docling-parse thread counts are excluded - too: per-page cost is the same quantity at any thread count, so those plots - would just be the diagonal. + not a like-for-like page. Prefer docling-parse at one thread when present; + otherwise fall back to the lowest available docling-parse thread count for + that task. """ by_task: Dict[str, List[str]] = defaultdict(list) for series, rows in per_series_rows.items(): @@ -338,18 +338,27 @@ def _hex_pairs_to_plot( pairs: List[Tuple[str, str]] = [] for task, names in sorted(by_task.items()): - reference = next( + references = sorted( ( s for s in names if per_series_rows[s][0].backend == REFERENCE_BACKEND - and per_series_rows[s][0].threads == 1 ), - None, + key=lambda s: ( + per_series_rows[s][0].threads != 1, + per_series_rows[s][0].threads, + s, + ), ) + reference = references[0] if references else None if reference is None: - print(f" no {REFERENCE_BACKEND} (1t) series for task {task}; no hexbins") + print(f" no {REFERENCE_BACKEND} series for task {task}; no hexbins") continue + if per_series_rows[reference][0].threads != 1: + print( + f" no {REFERENCE_BACKEND} (1t) series for task {task}; " + f"using {reference} for hexbins" + ) pairs.extend( (reference, other) for other in names diff --git a/perf/run_scaling.py b/perf/run_scaling.py index e3bedc9f..2ae2b830 100644 --- a/perf/run_scaling.py +++ b/perf/run_scaling.py @@ -125,6 +125,43 @@ def resolve_pdf_inputs( return find_pdfs(pdf_dir, recursive=True), info +def filter_pdf_selection(pdf_paths: List[Path], selection: str) -> List[Path]: + """Filter PDFs by comma/semicolon-separated filename, stem, or path tokens.""" + tokens = [ + token.strip() + for token in re.split(r"[;,]", selection) + if token.strip() + ] + if not tokens: + return pdf_paths + + selected: List[Path] = [] + selected_set = set() + unmatched = set(tokens) + for pdf_path in pdf_paths: + path = str(pdf_path) + name = pdf_path.name + stem = pdf_path.stem + matched = [ + token + for token in tokens + if token == name or token == stem or token in path + ] + if matched and pdf_path not in selected_set: + selected.append(pdf_path) + selected_set.add(pdf_path) + unmatched.difference_update(matched) + + if unmatched: + print( + "Warning: --pdf-selection did not match: " + + ", ".join(sorted(unmatched)), + file=sys.stderr, + ) + + return selected + + def page_counts(pdf_paths: List[Path]) -> List[Tuple[Path, int]]: """Count pages per PDF using DoclingPdfParser.""" from docling_parse.pdf_parser import DoclingPdfParser @@ -384,6 +421,11 @@ def _add_bool_value_arg( ) +def _arg_was_passed(argv: List[str], name: str) -> bool: + option = f"--{name}" + return any(arg == option or arg.startswith(f"{option}=") for arg in argv) + + def _decode_options_from_args(args: argparse.Namespace) -> dict[str, bool]: return { "keep_char_cells": args.keep_char_cells, @@ -2005,6 +2047,15 @@ def main(argv: List[str]) -> int: default=None, help="Maximum number of pages to process across all input PDFs", ) + ap.add_argument( + "--pdf-selection", + type=str, + default="", + help=( + "Comma/semicolon-separated PDF filename, stem, or path tokens to " + "benchmark after input resolution, e.g. '1235350.pdf;1061589.pdf'" + ), + ) ap.add_argument( "--max-concurrent-results", type=int, @@ -2131,6 +2182,8 @@ def main(argv: List[str]) -> int: ) args = ap.parse_args(argv) + if args.mode == "parse" and not _arg_was_passed(argv, "materialize-bitmaps"): + args.materialize_bitmaps = False # Recorded verbatim in the report so a published number can be traced back # to the invocation that produced it. @@ -2146,6 +2199,8 @@ def main(argv: List[str]) -> int: system_info = collect_system_info() pdfs, dataset_info = resolve_pdf_inputs(args.input, recursive=args.recursive) + if args.pdf_selection: + pdfs = filter_pdf_selection(pdfs, args.pdf_selection) if not pdfs: print(f"No PDFs found for input: {args.input}", file=sys.stderr) return 2 @@ -2165,6 +2220,7 @@ def main(argv: List[str]) -> int: "other backends": other_backends or "(none)", "comparison suite": compare_backends or "(off)", "max pages": args.max_pages if args.max_pages else "(all)", + "pdf selection": args.pdf_selection or "(all)", "bytesio": args.bytesio, } if args.mode in ("render", "both"): diff --git a/scripts/check_no_blend2d_assertions.py b/scripts/check_no_blend2d_assertions.py new file mode 100644 index 00000000..3e8c7ed1 --- /dev/null +++ b/scripts/check_no_blend2d_assertions.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python + +import sys +import zipfile +from pathlib import Path + + +ASSERTION_MARKER = b"ASSERTION FAILURE" +NATIVE_SUFFIXES = {".so", ".pyd", ".dll", ".dylib"} + + +def native_files(path: Path) -> list[Path]: + if path.is_file(): + return [path] + return [ + item + for item in path.rglob("*") + if item.is_file() and item.suffix.lower() in NATIVE_SUFFIXES + ] + + +def scan_file(path: Path) -> list[str]: + if path.suffix.lower() == ".whl": + findings: list[str] = [] + with zipfile.ZipFile(path) as zf: + for name in zf.namelist(): + if Path(name).suffix.lower() not in NATIVE_SUFFIXES: + continue + data = zf.read(name) + if ASSERTION_MARKER in data: + findings.append(f"{path}!{name}") + return findings + + try: + data = path.read_bytes() + except OSError as exc: + print(f"warning: could not read {path}: {exc}", file=sys.stderr) + return [] + + return [str(path)] if ASSERTION_MARKER in data else [] + + +def main(argv: list[str]) -> int: + if not argv: + print( + "usage: check_no_blend2d_assertions.py ...", + file=sys.stderr, + ) + return 2 + + findings: list[str] = [] + for arg in argv: + path = Path(arg) + if not path.exists(): + print(f"warning: path does not exist: {path}", file=sys.stderr) + continue + for item in native_files(path): + findings.extend(scan_file(item)) + + if findings: + print("Blend2D assertion machinery found in release artifact:", file=sys.stderr) + for finding in findings: + print(f" {finding}", file=sys.stderr) + return 1 + + print("No Blend2D assertion machinery found.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) diff --git a/src/parse.h b/src/parse.h index 7d210a92..52ad5cc4 100644 --- a/src/parse.h +++ b/src/parse.h @@ -53,6 +53,7 @@ #include #include +#include #include #include #include diff --git a/src/parse/pdf_decoders/stream.h b/src/parse/pdf_decoders/stream.h index c7e04677..ed8da969 100644 --- a/src/parse/pdf_decoders/stream.h +++ b/src/parse/pdf_decoders/stream.h @@ -500,8 +500,8 @@ namespace pdflib for(size_t i = 0; i + 1 < parameters.size(); i += 2) { - const qpdf_stream_instruction& key_instruction = parameters[i]; - const qpdf_stream_instruction& value_instruction = parameters[i + 1]; + qpdf_stream_instruction key_instruction = parameters[i]; + qpdf_stream_instruction value_instruction = parameters[i + 1]; if(not key_instruction.obj.isName()) { @@ -511,7 +511,7 @@ namespace pdflib } const std::string key = canonical_name(key_instruction.obj.getName()); - const QPDFObjectHandle& value = value_instruction.obj; + QPDFObjectHandle value = value_instruction.obj; if(key == "/Width" and value.isInteger()) { @@ -580,7 +580,8 @@ namespace pdflib return; } - inline_image.data = instruction.obj.getInlineImageValue(); + QPDFObjectHandle obj = instruction.obj; + inline_image.data = obj.getInlineImageValue(); inline_image.has_data = true; } diff --git a/src/parse/pdf_resources/page_font.h b/src/parse/pdf_resources/page_font.h index a7ce6561..3faa58de 100644 --- a/src/parse/pdf_resources/page_font.h +++ b/src/parse/pdf_resources/page_font.h @@ -78,8 +78,7 @@ namespace pdflib // only needed for the cmap-resource files bool numb_is_in_cmap(uint32_t c); - void set(std::string font_key_, - nlohmann::json& json_font_, + void set(std::string font_key_, QPDFObjectHandle qpdf_font_); private: @@ -96,14 +95,11 @@ namespace pdflib void init_font_matrix(); void init_font_program(); bool try_init_font_program_from_descriptor(QPDFObjectHandle font_obj, - nlohmann::json const& font_json, bool from_descendant_font); bool try_init_font_program_direct(QPDFObjectHandle font_obj, - nlohmann::json const& font_json, bool from_descendant_font); void populate_font_program(QPDFObjectHandle descriptor_obj, QPDFObjectHandle stream_obj, - nlohmann::json const& descriptor_json, std::string const& source_path, embedded_font_file_kind kind, bool from_descendant_font); @@ -147,10 +143,9 @@ namespace pdflib pdf_timings& timings; nlohmann::json json_font; - nlohmann::json desc_font; // derived from json_font, only for '/Type-0' QPDFObjectHandle qpdf_font; - //QPDFObjectHandle qpdf_desc_font; // derived from json_font, only for '/Type-0' + QPDFObjectHandle qpdf_desc_font; // derived from qpdf_font, only for '/Type-0' std::string encoding_name; font_encoding_name encoding; @@ -296,6 +291,11 @@ namespace pdflib nlohmann::json pdf_resource::get() { + if(json_font.is_null() and not qpdf_font.isNull()) + { + json_font = to_json(qpdf_font); + } + return json_font; } @@ -680,8 +680,7 @@ namespace pdflib } } - void pdf_resource::set(std::string font_key_, - nlohmann::json& json_font_, + void pdf_resource::set(std::string font_key_, QPDFObjectHandle qpdf_font_) { LOG_S(INFO) << __FUNCTION__ << " font: " << font_key_; @@ -693,7 +692,7 @@ namespace pdflib try { - LOG_S(INFO) << "font [key='" << font_key_ << "']:\n" << json_font_.dump(2); + LOG_S(INFO) << "font [key='" << font_key_ << "']:\n" << qpdf_object::debug(qpdf_font_); } catch(std::exception e) { @@ -707,8 +706,9 @@ namespace pdflib utils::timer font_timer; font_key = font_key_; - json_font = json_font_; + json_font = nullptr; qpdf_font = qpdf_font_; + qpdf_desc_font = QPDFObjectHandle::newNull(); double font_time = font_timer.get_time(); timings.add_timing(pdf_timings::KEY_FONT_INIT_COPY, font_time); @@ -787,26 +787,20 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__; - std::vector keys_0 = {"/Encoding", "/BaseEncoding"}; - std::vector keys_1 = {"/Encoding"}; - std::string name; - if(utils::json::has(keys_0, json_font)) + if(qpdf_object::get_name_or_string(qpdf_font, {"/Encoding", "/BaseEncoding"}, name)) { - name = utils::json::get(keys_0, json_font); encoding = to_encoding_name(name); has_explicit_encoding = true; LOG_S(INFO) << "font-encoding [" << name << "]: " << to_string(encoding); } - else if(utils::json::has(keys_1, json_font)) + else if(qpdf_font.isDictionary() and qpdf_font.hasKey("/Encoding")) { - auto result = utils::json::get(keys_1, json_font); + auto result = qpdf_font.getKey("/Encoding"); - if(result.is_string()) + if(qpdf_object::get_name_or_string(result, encoding_name)) { - encoding_name = result.get(); - if(cids.has(encoding_name)) { encoding = CMAP_RESOURCES; @@ -849,17 +843,10 @@ namespace pdflib LOG_S(INFO) << "font-encoding [" << name << "]: " << to_string(encoding); } - else if(result.is_object() && result.count("/BaseEncoding") == 1 && result["/BaseEncoding"].is_string()) - { - // Extract /BaseEncoding from encoding dictionary - std::string base_enc = result["/BaseEncoding"].get(); - encoding = to_encoding_name(base_enc); - has_explicit_encoding = true; - LOG_S(INFO) << "font-encoding from object /BaseEncoding [" << base_enc << "]: " << to_string(encoding); - } else { - LOG_S(WARNING) << " --> font-encoding falling back to STANDARD with font-encoding [object]: " << result.dump(); + LOG_S(WARNING) << " --> font-encoding falling back to STANDARD with font-encoding [object]: " + << qpdf_object::debug(result); encoding = STANDARD; has_explicit_encoding = false; @@ -877,26 +864,20 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__; - std::vector keys = {"/Subtype"}; - - if(utils::json::has(keys, json_font)) + std::string name; + if(qpdf_object::get_name_or_string(qpdf_font, {"/Subtype"}, name)) { - std::string name = utils::json::get(keys, json_font); subtype = to_subtype_name(name); LOG_S(INFO) << "subtype [" << name << "]: " << to_string(subtype); - std::vector keys_0 = {"/DescendantFonts"}; - if(subtype==TYPE_0 and utils::json::has(keys_0, json_font)) + QPDFObjectHandle desc_fonts = qpdf_object::get_path(qpdf_font, {"/DescendantFonts"}); + if(subtype==TYPE_0 and desc_fonts.isArray()) { - auto desc_fonts = utils::json::get(keys_0, json_font); - - if(desc_fonts.size()==1) + if(desc_fonts.getArrayNItems()==1) { LOG_S(INFO) << "found the descendant font";// << desc_font.dump(2); - desc_font = desc_fonts[0]; - - //qpdf_desc_font = qpdf_font.getKey(keys_0.at(0)).getArrayItem(0); + qpdf_desc_font = desc_fonts.getArrayItem(0); } else { @@ -918,7 +899,7 @@ namespace pdflib else { subtype=NULL_TYPE; - LOG_S(ERROR) << "could not find subtype in font: " << json_font.dump(2); + LOG_S(ERROR) << "could not find subtype in font: " << qpdf_object::debug(qpdf_font); } } @@ -926,17 +907,13 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__; - std::vector keys = {"/BaseFont"}; - base_font = "null"; - if(utils::json::has(keys, json_font)) + if(qpdf_object::get_name_or_string(qpdf_font, {"/BaseFont"}, base_font)) { - base_font = utils::json::get(keys, json_font); LOG_S(INFO) << "base-font: " << base_font; } - else if(utils::json::has(keys, desc_font)) + else if(qpdf_object::get_name_or_string(qpdf_desc_font, {"/BaseFont"}, base_font)) { - base_font = utils::json::get(keys, desc_font); LOG_S(INFO) << "base-font: " << base_font; } else @@ -949,23 +926,17 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__; - std::vector keys_0 = {"/FontDescriptor", "/FontName"}; - std::vector keys_1 = {"/Name"}; - font_name = "null"; - if(utils::json::has(keys_0, json_font)) + if(qpdf_object::get_name_or_string(qpdf_font, {"/FontDescriptor", "/FontName"}, font_name)) { - font_name = utils::json::get(keys_0, json_font); LOG_S(INFO) << "font-name: " << font_name; } - else if(utils::json::has(keys_0, desc_font)) + else if(qpdf_object::get_name_or_string(qpdf_desc_font, {"/FontDescriptor", "/FontName"}, font_name)) { - font_name = utils::json::get(keys_0, desc_font); LOG_S(INFO) << "font-name: " << font_name; } - else if(utils::json::has(keys_1, json_font)) + else if(qpdf_object::get_name_or_string(qpdf_font, {"/Name"}, font_name)) { - font_name = utils::json::get(keys_1, json_font); LOG_S(INFO) << "font-name: " << font_name; } else if(base_font!="null") @@ -983,29 +954,25 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__;// << "\t" << json_font.dump(2); - std::vector keys_0 = {"/FontDescriptor", "/FontBBox"}; - std::vector keys_1 = {"/FontBBox"}; - nlohmann::json json_bbox; + bool found_bbox = false; - if(utils::json::has(keys_0, json_font)) + if(qpdf_object::get_number_array(qpdf_font, {"/FontDescriptor", "/FontBBox"}, font_bbox)) { - json_bbox = utils::json::get(keys_0, json_font); + found_bbox = true; } - else if(utils::json::has(keys_0, desc_font)) + else if(qpdf_object::get_number_array(qpdf_desc_font, {"/FontDescriptor", "/FontBBox"}, font_bbox)) { - json_bbox = utils::json::get(keys_0, desc_font); + found_bbox = true; } - else if(utils::json::has(keys_1, json_font)) + else if(qpdf_object::get_number_array(qpdf_font, {"/FontBBox"}, font_bbox)) { //assert(subtype==TYPE_3); - - json_bbox = utils::json::get(keys_1, json_font); + found_bbox = true; } - else if(utils::json::has(keys_1, desc_font)) + else if(qpdf_object::get_number_array(qpdf_desc_font, {"/FontBBox"}, font_bbox)) { //assert(subtype==TYPE_3); - - json_bbox = utils::json::get(keys_1, desc_font); + found_bbox = true; } else if(bfonts.has(base_font)==1) { @@ -1017,18 +984,16 @@ namespace pdflib LOG_S(WARNING) << "could not find font-bbox"; } - if (json_bbox != nullptr) + if (not found_bbox) { - if (json_bbox.is_array() and json_bbox.size() == 4) - { - for(int d=0; d<4; d++) - { - font_bbox[d] = json_bbox[d].get(); - } - } - else + QPDFObjectHandle bbox = qpdf_object::get_path(qpdf_font, {"/FontDescriptor", "/FontBBox"}); + if(bbox.isNull()) { bbox = qpdf_object::get_path(qpdf_desc_font, {"/FontDescriptor", "/FontBBox"}); } + if(bbox.isNull()) { bbox = qpdf_object::get_path(qpdf_font, {"/FontBBox"}); } + if(bbox.isNull()) { bbox = qpdf_object::get_path(qpdf_desc_font, {"/FontBBox"}); } + if(not bbox.isNull()) { - LOG_S(ERROR) << "expected 4 elements in font-bbox, got: " << json_bbox; + LOG_S(ERROR) << "expected 4 numeric elements in font-bbox, got: " + << qpdf_object::debug(bbox); } } @@ -1044,26 +1009,11 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__;// << "\t" << json_font.dump(2); - std::vector keys_0 = {"/FontMatrix"}; - - if(utils::json::has(keys_0, json_font)) + if(qpdf_object::get_number_array(qpdf_font, {"/FontMatrix"}, font_matrix)) { //assert(subtype==TYPE_3); - auto json_matrix = utils::json::get(keys_0, json_font); - - if (json_matrix.is_array() and json_matrix.size() == 6) - { - for(int d=0; d<6; d++) - { - font_matrix[d] = json_matrix[d].get(); - } - type3_xscale = font_matrix[0] * 1000.0; - type3_yscale = font_matrix[3] * 1000.0; - } - else - { - LOG_S(ERROR) << "expected 6 elements in font-matrix, got: " << json_matrix; - } + type3_xscale = font_matrix[0] * 1000.0; + type3_yscale = font_matrix[3] * 1000.0; } else { @@ -1094,43 +1044,29 @@ namespace pdflib bool found = false; LOG_S(INFO) << __FUNCTION__ << ": probing primary font descriptor"; - found = try_init_font_program_from_descriptor(qpdf_font, json_font, false); + found = try_init_font_program_from_descriptor(qpdf_font, false); - if(not found and subtype==TYPE_0 and qpdf_font.hasKey("/DescendantFonts")) + if(not found and subtype==TYPE_0 and not qpdf_desc_font.isNull()) { LOG_S(INFO) << __FUNCTION__ << ": probing descendant font descriptor"; - auto desc_fonts = qpdf_font.getKey("/DescendantFonts"); - if(desc_fonts.isArray() and desc_fonts.getArrayNItems() > 0) + found = try_init_font_program_from_descriptor(qpdf_desc_font, true); + if(not found) { - auto qpdf_desc_font = desc_fonts.getArrayItem(0); - found = try_init_font_program_from_descriptor(qpdf_desc_font, desc_font, true); - if(not found) - { - LOG_S(INFO) << __FUNCTION__ << ": probing descendant font directly"; - found = try_init_font_program_direct(qpdf_desc_font, desc_font, true); - } - } - else - { - LOG_S(INFO) << __FUNCTION__ << ": /DescendantFonts missing or empty at qpdf level"; + LOG_S(INFO) << __FUNCTION__ << ": probing descendant font directly"; + found = try_init_font_program_direct(qpdf_desc_font, true); } } if(not found) { LOG_S(INFO) << __FUNCTION__ << ": probing primary font object directly"; - found = try_init_font_program_direct(qpdf_font, json_font, false); + found = try_init_font_program_direct(qpdf_font, false); } - if(not found and subtype==TYPE_0 and qpdf_font.hasKey("/DescendantFonts")) + if(not found and subtype==TYPE_0 and not qpdf_desc_font.isNull()) { - auto desc_fonts = qpdf_font.getKey("/DescendantFonts"); - if(desc_fonts.isArray() and desc_fonts.getArrayNItems() > 0) - { - LOG_S(INFO) << __FUNCTION__ << ": probing descendant font directly as final fallback"; - auto qpdf_desc_font = desc_fonts.getArrayItem(0); - found = try_init_font_program_direct(qpdf_desc_font, desc_font, true); - } + LOG_S(INFO) << __FUNCTION__ << ": probing descendant font directly as final fallback"; + found = try_init_font_program_direct(qpdf_desc_font, true); } if(found) @@ -1155,7 +1091,6 @@ namespace pdflib bool pdf_resource::try_init_font_program_from_descriptor( QPDFObjectHandle font_obj, - nlohmann::json const& font_json, bool from_descendant_font) { LOG_S(INFO) << __FUNCTION__ @@ -1180,12 +1115,6 @@ namespace pdflib return false; } - nlohmann::json descriptor_json = nullptr; - if(font_json.is_object() and font_json.count("/FontDescriptor") == 1) - { - descriptor_json = font_json["/FontDescriptor"]; - } - struct candidate_spec { const char* key; @@ -1215,7 +1144,6 @@ namespace pdflib populate_font_program(descriptor_obj, stream_obj, - descriptor_json, std::string("/FontDescriptor") + spec.key, spec.kind, from_descendant_font); @@ -1228,7 +1156,6 @@ namespace pdflib bool pdf_resource::try_init_font_program_direct( QPDFObjectHandle font_obj, - nlohmann::json const& font_json, bool from_descendant_font) { LOG_S(INFO) << __FUNCTION__ @@ -1269,7 +1196,6 @@ namespace pdflib populate_font_program(font_obj, stream_obj, - font_json, spec.key, spec.kind, from_descendant_font); @@ -1283,7 +1209,6 @@ namespace pdflib void pdf_resource::populate_font_program( QPDFObjectHandle descriptor_obj, QPDFObjectHandle stream_obj, - nlohmann::json const& descriptor_json, std::string const& source_path, embedded_font_file_kind kind, bool from_descendant_font) @@ -1300,7 +1225,7 @@ namespace pdflib font_program.base_font = base_font; font_program.font_name = font_name; font_program.from_descendant_font = from_descendant_font; - font_program.descriptor_json = descriptor_json; + font_program.descriptor_json = to_json(descriptor_obj, {}, 0, 2); font_program.stream_dict_json = to_json(stream_obj, {}, 0, 2); // Disabled: dumping the full stream dictionary per font floods the logs. // LOG_S(INFO) << __FUNCTION__ @@ -1453,14 +1378,14 @@ namespace pdflib // PDF spec: /CIDToGIDMap defaults to /Identity when absent. Any stream // value means an explicit map that we do not resolve here. - std::vector keys = {"/CIDToGIDMap"}; - if(not utils::json::has(keys, desc_font)) + QPDFObjectHandle value = qpdf_object::get_path(qpdf_desc_font, {"/CIDToGIDMap"}); + if(value.isNull()) { return true; } - nlohmann::json value = utils::json::get(keys, desc_font); - return value.is_string() and value.get() == "/Identity"; + std::string name; + return qpdf_object::get_name_or_string(value, name) and name == "/Identity"; } void pdf_resource::build_embedded_font_blob() @@ -1491,17 +1416,12 @@ namespace pdflib const int FLAG_SYMBOLIC = 1 << 2; // /Flags bit 3 int flags = 0; - std::vector keys = {"/FontDescriptor", "/Flags"}; - if(utils::json::has(keys, json_font)) - { - flags = utils::json::get(keys, json_font); - } - else if(utils::json::has(keys, desc_font)) + if(not qpdf_object::get_int(qpdf_font, {"/FontDescriptor", "/Flags"}, flags)) { - flags = utils::json::get(keys, desc_font); + qpdf_object::get_int(qpdf_desc_font, {"/FontDescriptor", "/Flags"}, flags); } - const bool has_encoding = utils::json::has({"/Encoding"}, json_font); + const bool has_encoding = qpdf_object::has_path(qpdf_font, {"/Encoding"}); uses_builtin_encoding = (subtype != TYPE_0) and ((flags & FLAG_SYMBOLIC) != 0) and (not has_encoding); @@ -1536,19 +1456,15 @@ namespace pdflib ascent=0; { - std::vector keys = {"/FontDescriptor", "/Ascent"}; - bool ascent_defined=false; - if(utils::json::has(keys, json_font)) + if(qpdf_object::get_number(qpdf_font, {"/FontDescriptor", "/Ascent"}, ascent)) { - ascent = utils::json::get(keys, json_font); ascent_defined=true; LOG_S(INFO) << "ascent: " << ascent; } - else if(utils::json::has(keys, desc_font)) + else if(qpdf_object::get_number(qpdf_desc_font, {"/FontDescriptor", "/Ascent"}, ascent)) { - ascent = utils::json::get(keys, desc_font); ascent_defined=true; LOG_S(INFO) << "ascent: " << ascent; @@ -1581,19 +1497,15 @@ namespace pdflib descent=0; { - std::vector keys = {"/FontDescriptor", "/Descent"}; - bool descent_defined=false; - if(utils::json::has(keys, json_font)) + if(qpdf_object::get_number(qpdf_font, {"/FontDescriptor", "/Descent"}, descent)) { - descent = utils::json::get(keys, json_font); descent_defined=true; LOG_S(INFO) << "descent: " << descent; } - else if(utils::json::has(keys, desc_font)) + else if(qpdf_object::get_number(qpdf_desc_font, {"/FontDescriptor", "/Descent"}, descent)) { - descent = utils::json::get(keys, desc_font); descent_defined=true; LOG_S(INFO) << "descent: " << descent; @@ -1645,19 +1557,15 @@ namespace pdflib capheight=0; { - std::vector keys = {"/FontDescriptor", "/CapHeight"}; - //bool capheight_defined=false; - if(utils::json::has(keys, json_font)) + if(qpdf_object::get_number(qpdf_font, {"/FontDescriptor", "/CapHeight"}, capheight)) { - capheight = utils::json::get(keys, json_font); //capheight_defined=true; LOG_S(INFO) << "capheight: " << capheight; } - else if(utils::json::has(keys, desc_font)) + else if(qpdf_object::get_number(qpdf_desc_font, {"/FontDescriptor", "/CapHeight"}, capheight)) { - capheight = utils::json::get(keys, desc_font); //capheight_defined=true; LOG_S(INFO) << "capheight: " << capheight; @@ -1680,19 +1588,15 @@ namespace pdflib xheight=0; { - std::vector keys = {"/FontDescriptor", "/XHeight"}; - //bool xheight_defined=false; - if(utils::json::has(keys, json_font)) + if(qpdf_object::get_number(qpdf_font, {"/FontDescriptor", "/XHeight"}, xheight)) { - xheight = utils::json::get(keys, json_font); //xheight_defined=true; LOG_S(INFO) << "xheight: " << xheight; } - else if(utils::json::has(keys, desc_font)) + else if(qpdf_object::get_number(qpdf_desc_font, {"/FontDescriptor", "/XHeight"}, xheight)) { - xheight = utils::json::get(keys, desc_font); //xheight_defined=true; LOG_S(INFO) << "xheight: " << xheight; @@ -1723,19 +1627,15 @@ namespace pdflib has_default_width=false; - std::vector f_keys = {"/DW"}; - - if(utils::json::has(f_keys, json_font)) + if(qpdf_object::get_number(qpdf_font, {"/DW"}, default_width)) { has_default_width = true; - default_width = utils::json::get(f_keys, json_font).get(); LOG_S(INFO) << "default-width: " << default_width; } - else if(utils::json::has(f_keys, desc_font)) + else if(qpdf_object::get_number(qpdf_desc_font, {"/DW"}, default_width)) { has_default_width = true; - default_width = utils::json::get(f_keys, desc_font).get(); LOG_S(INFO) << "default-width: " << default_width; } @@ -1768,17 +1668,21 @@ namespace pdflib LOG_S(INFO) << "vertical writing mode from encoding " << encoding_name; { - std::vector keys = {"/DW2"}; - - nlohmann::json dw2; - if(utils::json::has(keys, json_font)) { dw2 = utils::json::get(keys, json_font); } - else if(utils::json::has(keys, desc_font)) { dw2 = utils::json::get(keys, desc_font); } + QPDFObjectHandle dw2 = qpdf_object::get_path(qpdf_font, {"/DW2"}); + if(dw2.isNull()) { dw2 = qpdf_object::get_path(qpdf_desc_font, {"/DW2"}); } - if(dw2.is_array() and dw2.size() >= 2 and - dw2[0].is_number() and dw2[1].is_number()) + if(dw2.isArray() and dw2.getArrayNItems() >= 2) { - vertical_origin_y = dw2[0].get() / 1000.0; - default_vertical_displacement = dw2[1].get() / 1000.0; + double origin_y = 0.0; + double displacement = 0.0; + QPDFObjectHandle origin_obj = dw2.getArrayItem(0); + QPDFObjectHandle displacement_obj = dw2.getArrayItem(1); + if(qpdf_object::get_number(origin_obj, origin_y) and + qpdf_object::get_number(displacement_obj, displacement)) + { + vertical_origin_y = origin_y / 1000.0; + default_vertical_displacement = displacement / 1000.0; + } } LOG_S(INFO) << "vertical metrics: origin-y " << vertical_origin_y @@ -1788,31 +1692,30 @@ namespace pdflib // /W2 entries come as `c [w1 v_x v_y ...]` or `c_first c_last w1 v_x v_y`; // only w1 is read, since the horizontal half of v is taken as w0/2 either // way and its vertical half rarely differs from /DW2. - std::vector keys = {"/W2"}; - - nlohmann::json w2; - if(utils::json::has(keys, json_font)) { w2 = utils::json::get(keys, json_font); } - else if(utils::json::has(keys, desc_font)) { w2 = utils::json::get(keys, desc_font); } + QPDFObjectHandle w2 = qpdf_object::get_path(qpdf_font, {"/W2"}); + if(w2.isNull()) { w2 = qpdf_object::get_path(qpdf_desc_font, {"/W2"}); } - if(not w2.is_array()) + if(not w2.isArray()) { return; } - for(std::size_t l = 0; l + 1 < w2.size(); ) + for(int l = 0; l + 1 < w2.getArrayNItems(); ) { - if(not w2[l].is_number()) + QPDFObjectHandle beg_obj = w2.getArrayItem(l); + if(not beg_obj.isNumber()) { LOG_S(WARNING) << "/W2 entry " << l << " is not a CID"; break; } - const int beg = w2[l].get(); + const int beg = static_cast(utils::numeric::locale_safe_numeric_value(beg_obj)); l += 1; - if(w2[l].is_array()) + QPDFObjectHandle value_obj = w2.getArrayItem(l); + if(value_obj.isArray()) { - std::vector triples = w2[l].get>(); + std::vector triples = qpdf_object::get_number_array(value_obj); l += 1; for(std::size_t k = 0; k + 2 < triples.size(); k += 3) @@ -1821,10 +1724,18 @@ namespace pdflib triples[k] / 1000.0; } } - else if(l + 3 < w2.size()) + else if(l + 3 < w2.getArrayNItems()) { - const int end = w2[l].get(); - const double w1 = w2[l + 1].get() / 1000.0; + QPDFObjectHandle end_obj = w2.getArrayItem(l); + QPDFObjectHandle w1_obj = w2.getArrayItem(l + 1); + if(not end_obj.isNumber() or not w1_obj.isNumber()) + { + LOG_S(WARNING) << "/W2 range contains non-numeric values"; + break; + } + + const int end = static_cast(utils::numeric::locale_safe_numeric_value(end_obj)); + const double w1 = utils::numeric::locale_safe_numeric_value(w1_obj) / 1000.0; l += 4; // c_last, w1, v_x, v_y for(int id = beg; id <= end; id++) @@ -1868,15 +1779,12 @@ namespace pdflib fchar=-1; - std::vector f_keys = {"/FirstChar"}; - if(utils::json::has(f_keys, json_font)) + if(qpdf_object::get_int(qpdf_font, {"/FirstChar"}, fchar)) { - fchar = utils::json::get(f_keys, json_font).get(); LOG_S(INFO) << "fchar: " << fchar; } - else if(utils::json::has(f_keys, desc_font)) + else if(qpdf_object::get_int(qpdf_desc_font, {"/FirstChar"}, fchar)) { - fchar = utils::json::get(f_keys, desc_font).get(); LOG_S(INFO) << "fchar: " << fchar; } else @@ -1891,15 +1799,12 @@ namespace pdflib lchar=-1; - std::vector l_keys = {"/LastChar"}; - if(utils::json::has(l_keys, json_font)) + if(qpdf_object::get_int(qpdf_font, {"/LastChar"}, lchar)) { - lchar = utils::json::get(l_keys, json_font).get(); LOG_S(INFO) << "lchar: " << lchar; } - else if(utils::json::has(l_keys, desc_font)) + else if(qpdf_object::get_int(qpdf_desc_font, {"/LastChar"}, lchar)) { - lchar = utils::json::get(l_keys, desc_font).get(); LOG_S(INFO) << "lchar: " << lchar; } else @@ -1914,32 +1819,17 @@ namespace pdflib std::vector values={}; { - std::vector keys = {"/Widths"}; - bool found_widths = false; - if(utils::json::has(keys, json_font) and (not found_widths)) - { - auto result = utils::json::get(keys, json_font); - LOG_S(INFO) << "widths: " << result.dump(); + QPDFObjectHandle widths = qpdf_object::get_path(qpdf_font, {"/Widths"}); + if(widths.isNull()) { widths = qpdf_object::get_path(qpdf_desc_font, {"/Widths"}); } - if(result.is_array()) - { - values = result.get >(); - found_widths = true; - } - } - else if(utils::json::has(keys, desc_font) and (not found_widths)) + if(widths.isArray() and (not found_widths)) { - auto result = utils::json::get(keys, desc_font); - LOG_S(INFO) << "widths: " << result.dump(); - - if(result.is_array()) - { - values = result.get >(); - found_widths = true; - } + LOG_S(INFO) << "widths: " << qpdf_object::debug(widths); + values = qpdf_object::get_number_array(widths); + found_widths = true; } - else if(not found_widths) + if(not found_widths) { LOG_S(WARNING) << "could not find widths"; } @@ -1975,20 +1865,13 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__; - nlohmann::json ws; + QPDFObjectHandle ws; { - std::vector keys = {"/W"}; + ws = qpdf_object::get_path(qpdf_font, {"/W"}); + if(ws.isNull()) { ws = qpdf_object::get_path(qpdf_desc_font, {"/W"}); } - if(utils::json::has(keys, json_font)) - { - ws = utils::json::get(keys, json_font); - } - else if(utils::json::has(keys, desc_font)) - { - ws = utils::json::get(keys, desc_font); - } - else + if(not ws.isArray()) { LOG_S(WARNING) << "could not find '/W'"; return; @@ -2000,13 +1883,20 @@ namespace pdflib int beg=-1; int end=-1; - for(int l=0; l(); + if(not beg_obj.isNumber()) + { + LOG_S(WARNING) << "/W entry " << l << " is not a CID"; + break; + } + + beg = static_cast(utils::numeric::locale_safe_numeric_value(beg_obj)); l += 1; if(l==0) @@ -2014,31 +1904,32 @@ namespace pdflib fchar=beg; } - if(ws[l].is_number()) + if(l>=ws.getArrayNItems()) { - //LOG_S(INFO) << l << "\t" << ws[l].is_number() << "\t end: " << ws[l].dump(); + LOG_S(WARNING) << "index " << l << " is out of bounds " << ws.getArrayNItems(); + continue; + } - //assert(l(utils::numeric::locale_safe_numeric_value(value_obj)); + l += 1; - if(l>=ws.size()) + if(l>=ws.getArrayNItems()) { - LOG_S(WARNING) << "index " << l << " is out of bounds " << ws.size(); + LOG_S(WARNING) << "index " << l << " is out of bounds " << ws.getArrayNItems(); continue; } - - end = ws[l].get(); - l += 1; - //LOG_S(INFO) << l << "\t" << ws[l].is_number() << "\t w: " << ws[l].dump(); + QPDFObjectHandle width_obj = ws.getArrayItem(l); + if(not width_obj.isNumber()) + { + LOG_S(WARNING) << "/W range width is not numeric: " << qpdf_object::debug(width_obj); + break; + } - //assert(l=ws.size()) - { - LOG_S(WARNING) << "index " << l << " is out of bounds " << ws.size(); - continue; - } - - double w = ws[l].get(); + double w = utils::numeric::locale_safe_numeric_value(width_obj); l += 1; for(int id=beg; id<=end; id++) @@ -2047,18 +1938,9 @@ namespace pdflib numb_to_widths[id] = w * type3_xscale; } } - else if(ws[l].is_array()) + else if(value_obj.isArray()) { - //LOG_S(INFO) << l << "\t" << ws[l].is_number() << "\t widths: " << ws[l].dump(); - - //assert(l=ws.size()) - { - LOG_S(WARNING) << "index " << l << " is out of bounds " << ws.size(); - continue; - } - - std::vector w = ws[l].get >(); + std::vector w = qpdf_object::get_number_array(value_obj); l += 1; for(int k=0; k keys = { "/ToUnicode" }; + QPDFObjectHandle qpdf_obj = qpdf_object::get_path(qpdf_font, {"/ToUnicode"}); - if(utils::json::has(keys, json_font)) + if(not qpdf_obj.isNull()) { LOG_S(INFO) << "found a /ToUnicode cmap: starting to decode ..."; - if(not qpdf_font.hasKey("/ToUnicode")) - { - auto tmp = to_json(qpdf_font); - - std::stringstream ss; - ss << "qpdf-font: " << tmp.dump(); - - LOG_S(ERROR) << ss.str(); - throw std::logic_error(ss.str()); - } - - auto qpdf_obj = qpdf_font.getKey("/ToUnicode"); - if(qpdf_obj.isStream()) { std::vector stream; @@ -2140,24 +2009,21 @@ namespace pdflib } else if(qpdf_obj.isString()) { - auto _ = to_json(qpdf_obj); - std::string message = "qpdf_obj.isString(): " + _.dump(2); + std::string message = "qpdf_obj.isString(): " + qpdf_object::debug(qpdf_obj); LOG_S(ERROR) << message; throw std::logic_error(message); } else if(qpdf_obj.isName()) { - auto _ = to_json(qpdf_obj); - std::string message = "qpdf_obj.isName(): " + _.dump(2); + std::string message = "qpdf_obj.isName(): " + qpdf_object::debug(qpdf_obj); LOG_S(ERROR) << message; //throw std::logic_error(message); } else { - auto _ = to_json(qpdf_obj); - std::string message = "qpdf_obj is unknown: " + _.dump(2); + std::string message = "qpdf_obj is unknown: " + qpdf_object::debug(qpdf_obj); LOG_S(ERROR) << message; throw std::logic_error(message); @@ -2191,12 +2057,12 @@ namespace pdflib } //else - if(subtype==TYPE_0 and desc_font!=NULL and + if(subtype==TYPE_0 and not qpdf_desc_font.isNull() and cids.has(encoding_name) ) { try { - LOG_S(INFO) << "descendant-font: " << desc_font.dump(2); + LOG_S(INFO) << "descendant-font: " << qpdf_object::debug(qpdf_desc_font); } catch(const std::exception& exc) { @@ -2221,11 +2087,11 @@ namespace pdflib cmap_initialized = false; } } - else if(subtype==TYPE_0 and desc_font!=NULL) + else if(subtype==TYPE_0 and not qpdf_desc_font.isNull()) { try { - LOG_S(INFO) << "descendant-font: " << desc_font.dump(2); + LOG_S(INFO) << "descendant-font: " << qpdf_object::debug(qpdf_desc_font); } catch(const std::exception& exc) { @@ -2236,13 +2102,17 @@ namespace pdflib LOG_S(INFO) << "encoding-type: " << to_string(encoding); LOG_S(INFO) << "encoding-name: " << encoding_name; - std::vector key_registry = {"/CIDSystemInfo", "/Registry"}; - std::vector key_ordering = {"/CIDSystemInfo", "/Ordering"}; - std::vector key_supplement = {"/CIDSystemInfo", "/Supplement"}; - - std::string registry_ = utils::json::get(key_registry, desc_font).get(); - std::string ordering_ = utils::json::get(key_ordering, desc_font).get(); - int supplement_ = utils::json::get(key_supplement, desc_font).get(); + std::string registry_; + std::string ordering_; + int supplement_ = 0; + if(not qpdf_object::get_name_or_string(qpdf_desc_font, {"/CIDSystemInfo", "/Registry"}, registry_) or + not qpdf_object::get_name_or_string(qpdf_desc_font, {"/CIDSystemInfo", "/Ordering"}, ordering_) or + not qpdf_object::get_int(qpdf_desc_font, {"/CIDSystemInfo", "/Supplement"}, supplement_)) + { + LOG_S(ERROR) << "incomplete /CIDSystemInfo in descendant font"; + cmap_initialized = false; + return; + } LOG_S(INFO) << "found descendant-font without /ToUnicode"; LOG_S(INFO) << " --> registry: " << registry_; @@ -2320,7 +2190,7 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__; - std::vector keys = { "/Encoding", "/Differences" }; + QPDFObjectHandle diffs = qpdf_object::get_path(qpdf_font, {"/Encoding", "/Differences"}); // Create a regex object std::regex re_01(R"(\/(.+)\.(.+))"); @@ -2362,26 +2232,24 @@ namespace pdflib return result; }; - if(utils::json::has(keys, json_font)) + if(not diffs.isNull()) { - auto diffs = utils::json::get(keys, json_font); //LOG_S(INFO) << "diffs: " << diffs.dump(2); - if(diffs.is_array()) + if(diffs.isArray()) { int numb=-1; std::string name="null"; - for(int l=0; l(); + numb = static_cast(utils::numeric::locale_safe_numeric_value(diff)); } - else if(diffs[l].is_string()) + else if(qpdf_object::get_name_or_string(diff, name)) { - name = diffs[l].get(); - // Object to hold the match results std::smatch match; @@ -2545,14 +2413,15 @@ namespace pdflib } else { - LOG_S(WARNING) << "item [" << diffs[l].dump(2) - << "] is not a string nor a number in the difference-vector: " << diffs.dump(2); + LOG_S(WARNING) << "item [" << qpdf_object::debug(diff) + << "] is not a string nor a number in the difference-vector: " + << qpdf_object::debug(diffs); } } } else { - LOG_S(WARNING) << "/Differences is not a vector: " << diffs.dump(2); + LOG_S(WARNING) << "/Differences is not a vector: " << qpdf_object::debug(diffs); } diff_initialized = true; @@ -2568,21 +2437,22 @@ namespace pdflib { LOG_S(INFO) << __FUNCTION__; - std::vector keys = { "/CharProcs" }; + QPDFObjectHandle qpdf_char_procs = qpdf_object::get_path(qpdf_font, {"/CharProcs"}); - if(utils::json::has(keys, json_font)) + if(not qpdf_char_procs.isNull()) { //assert(subtype==TYPE_3); - QPDFObjectHandle qpdf_char_procs = qpdf_font.getKey(keys.front()); LOG_S(WARNING) << "found CharProcs: " << qpdf_char_procs.getTypeName(); - - auto json_char_procs = utils::json::get(keys, json_font); - - for(auto& pair : json_char_procs.items()) + + if(not qpdf_char_procs.isDictionary()) { - std::string key = pair.key(); + LOG_S(WARNING) << "/CharProcs is not a dictionary"; + return; + } + for(auto& key : qpdf_char_procs.getKeys()) + { if(qpdf_char_procs.hasKey(key)) { QPDFObjectHandle qpdf_char_proc = qpdf_char_procs.getKey(key); diff --git a/src/parse/pdf_resources/page_fonts.h b/src/parse/pdf_resources/page_fonts.h index d65f6170..3f2ae143 100644 --- a/src/parse/pdf_resources/page_fonts.h +++ b/src/parse/pdf_resources/page_fonts.h @@ -140,12 +140,9 @@ namespace pdflib utils::timer font_timer; QPDFObjectHandle qpdf_font = qpdf_fonts.getKey(key); - nlohmann::json json_font = to_json(qpdf_font); - - LOG_S(INFO) << json_font.dump(2); pdf_resource page_font(timings); - page_font.set(key, json_font, qpdf_font); + page_font.set(key, qpdf_font); if(page_fonts.count(key)==1) { diff --git a/src/parse/qpdf/object.h b/src/parse/qpdf/object.h new file mode 100644 index 00000000..4b0907ea --- /dev/null +++ b/src/parse/qpdf/object.h @@ -0,0 +1,203 @@ +//-*-C++-*- + +#ifndef QPDF_OBJECT_ACCESS_H +#define QPDF_OBJECT_ACCESS_H + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace pdflib +{ + namespace qpdf_object + { + + inline QPDFObjectHandle get_path(QPDFObjectHandle obj, + const std::vector& keys) + { + for(const auto& key : keys) + { + if(obj.isStream()) + { + obj = obj.getDict(); + } + + if(not obj.isDictionary() or not obj.hasKey(key)) + { + return QPDFObjectHandle::newNull(); + } + + obj = obj.getKey(key); + } + + return obj; + } + + inline bool has_path(QPDFObjectHandle obj, + const std::vector& keys) + { + return not get_path(obj, keys).isNull(); + } + + inline std::string debug(QPDFObjectHandle obj) + { + if(obj.isNull()) + { + return "null"; + } + + try + { + std::string result = obj.unparse(); + constexpr std::size_t max_size = 512; + if(result.size() > max_size) + { + result.resize(max_size); + result += "..."; + } + return result; + } + catch(const std::exception& exc) + { + return std::string("<") + obj.getTypeName() + ": " + exc.what() + ">"; + } + } + + inline std::string sanitize_utf8(const std::string& val) + { + if(utf8::is_valid(val.begin(), val.end())) + { + return val; + } + + std::string result; + utf8::replace_invalid(val.begin(), val.end(), std::back_inserter(result)); + return result; + } + + inline bool get_name_or_string(QPDFObjectHandle obj, std::string& result) + { + if(obj.isName()) + { + result = sanitize_utf8(obj.getName()); + return true; + } + if(obj.isString()) + { + result = sanitize_utf8(obj.getUTF8Value()); + return true; + } + + return false; + } + + inline bool get_name_or_string(QPDFObjectHandle obj, + const std::vector& keys, + std::string& result) + { + return get_name_or_string(get_path(obj, keys), result); + } + + inline bool get_int(QPDFObjectHandle obj, int& result) + { + if(obj.isInteger()) + { + result = obj.getIntValue(); + return true; + } + + return false; + } + + inline bool get_int(QPDFObjectHandle obj, + const std::vector& keys, + int& result) + { + return get_int(get_path(obj, keys), result); + } + + inline bool get_number(QPDFObjectHandle obj, double& result) + { + if(obj.isNumber()) + { + result = utils::numeric::locale_safe_numeric_value(obj); + return true; + } + + return false; + } + + inline bool get_number(QPDFObjectHandle obj, + const std::vector& keys, + double& result) + { + return get_number(get_path(obj, keys), result); + } + + inline std::vector get_number_array(QPDFObjectHandle obj) + { + std::vector result; + if(not obj.isArray()) + { + return result; + } + + for(int i=0; i get_number_array(QPDFObjectHandle obj, + const std::vector& keys) + { + return get_number_array(get_path(obj, keys)); + } + + template + inline bool get_number_array(QPDFObjectHandle obj, + std::array& result) + { + if(not obj.isArray() or obj.getArrayNItems() != static_cast(N)) + { + return false; + } + + for(std::size_t i=0; i(i)); + if(not get_number(item, result[i])) + { + return false; + } + } + + return true; + } + + template + inline bool get_number_array(QPDFObjectHandle obj, + const std::vector& keys, + std::array& result) + { + return get_number_array(get_path(obj, keys), result); + } + + } +} + +#endif From 2c4efdbbdca960567cdfdd8a36dfbf74617bc1c8 Mon Sep 17 00:00:00 2001 From: Peter Staar Date: Fri, 7 Aug 2026 16:22:40 +0200 Subject: [PATCH 2/9] fixed the check_no_blend2d_assertions script Signed-off-by: Peter Staar --- scripts/check_no_blend2d_assertions.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/scripts/check_no_blend2d_assertions.py b/scripts/check_no_blend2d_assertions.py index 3e8c7ed1..6f4b4d8d 100644 --- a/scripts/check_no_blend2d_assertions.py +++ b/scripts/check_no_blend2d_assertions.py @@ -5,13 +5,18 @@ from pathlib import Path -ASSERTION_MARKER = b"ASSERTION FAILURE" +BLEND2D_ASSERTION_MARKERS = ( + b"[Blend2D] ASSERTION FAILURE", + b"bl_runtime_assertion_failure", +) NATIVE_SUFFIXES = {".so", ".pyd", ".dll", ".dylib"} def native_files(path: Path) -> list[Path]: if path.is_file(): - return [path] + if path.suffix.lower() == ".whl" or path.suffix.lower() in NATIVE_SUFFIXES: + return [path] + return [] return [ item for item in path.rglob("*") @@ -27,7 +32,7 @@ def scan_file(path: Path) -> list[str]: if Path(name).suffix.lower() not in NATIVE_SUFFIXES: continue data = zf.read(name) - if ASSERTION_MARKER in data: + if has_blend2d_assertion_marker(data): findings.append(f"{path}!{name}") return findings @@ -37,7 +42,11 @@ def scan_file(path: Path) -> list[str]: print(f"warning: could not read {path}: {exc}", file=sys.stderr) return [] - return [str(path)] if ASSERTION_MARKER in data else [] + return [str(path)] if has_blend2d_assertion_marker(data) else [] + + +def has_blend2d_assertion_marker(data: bytes) -> bool: + return any(marker in data for marker in BLEND2D_ASSERTION_MARKERS) def main(argv: list[str]) -> int: From e6d87ecaae59484bd747198b2e5ccf8047e7d543 Mon Sep 17 00:00:00 2001 From: Peter Staar Date: Fri, 7 Aug 2026 17:15:06 +0200 Subject: [PATCH 3/9] updating the cmake for extlib_blend2d Signed-off-by: Peter Staar --- cmake/extlib_blend2d.cmake | 24 +++ perf/run_analysis.py | 364 +++++++++++++++++++++++++++++++++++-- 2 files changed, 370 insertions(+), 18 deletions(-) diff --git a/cmake/extlib_blend2d.cmake b/cmake/extlib_blend2d.cmake index e337d3bb..44ba7e14 100644 --- a/cmake/extlib_blend2d.cmake +++ b/cmake/extlib_blend2d.cmake @@ -54,5 +54,29 @@ else() GIT_TAG 6dbc2cefbc996379e07104e34519a440b49b15d7 ) FetchContent_MakeAvailable(blend2d) + # Release wheels must not contain Blend2D's debug assertion path. Blend2D + # normally infers BL_BUILD_RELEASE from NDEBUG, but make that mode explicit + # for non-Debug builds so embedded builds do not depend on generator-specific + # CMAKE_BUILD_TYPE propagation. + target_compile_definitions( + blend2d + PUBLIC $<$>:BL_BUILD_RELEASE> + ) + + # Blend2D defines bl_runtime_assertion_failure() unconditionally in + # runtime.cpp. When linking the static archive with GNU-like linkers, that + # object can be pulled into pdf_parsers even when no release code references + # it. Compile with per-symbol sections and let Linux/MinGW linkers discard + # the unreferenced assertion helper. MSVC Release already uses /OPT:REF and + # macOS arm64 is passing, so keep this scoped to the failing toolchains. + set(BLEND2D_GNU_GC_SECTIONS "$>,$,$,$>>>") + target_compile_options( + blend2d + PRIVATE "$<${BLEND2D_GNU_GC_SECTIONS}:-ffunction-sections;-fdata-sections>" + ) + target_link_options( + blend2d + INTERFACE "$<${BLEND2D_GNU_GC_SECTIONS}:-Wl,--gc-sections>" + ) # FetchContent creates the target "blend2d" (and alias blend2d::blend2d). endif() diff --git a/perf/run_analysis.py b/perf/run_analysis.py index f351dd41..37e8929e 100644 --- a/perf/run_analysis.py +++ b/perf/run_analysis.py @@ -38,6 +38,9 @@ from tabulate import tabulate from docling_parse.pdf_parser import ( + ContentConfig, + ContentLevel, + DecodeConfig, DoclingPdfParser, Timings, get_decode_page_timing_keys, @@ -56,6 +59,61 @@ class PageTimings: timings: Timings = field(default_factory=lambda: Timings()) +DECODE_PAGE_CHILDREN = [ + "to_json_page", + "extract_annots_json", + "decode_dimensions", + "decode_resources", + "decode_contents", + "decode_annots", + "rotate_contents", + "sanitize_orientation", + "sanitize_cells", + "sanitise_contents", +] + +TIMING_CHILDREN = { + "pipeline": [ + "decode_page", + "create_word_cells", + "create_line_cells", + ], + "decode_page": DECODE_PAGE_CHILDREN, + "decode_contents": [ + "content_decode_total", + "interprete_ops_total", + "decode_xobjects_total", + "decode_grphs_total", + "decode_fonts_total", + "parse_stream_total", + "do_form_machinery_total", + "do_image_total", + ], + "decode_fonts_total": [ + "font: init-copy", + "font: init-metrics", + "font: font-cmap", + "font: font-cmap-stream-decode", + "font: font-cmap-resources", + "font: font-chars", + ], + "font: font-cmap": ["cmap-parse-total"], + "cmap-parse-total": [ + "cmap-parse-endbfchar", + "cmap-parse-endbfrange", + "cmap-parse-endcodespacerange", + ], +} + +TOP_LEVEL_TIMING_KEYS = set(TIMING_CHILDREN["pipeline"]) +NESTED_TIMING_KEYS = { + child + for parent, children in TIMING_CHILDREN.items() + if parent != "pipeline" + for child in children +} + + # -------------- IO helpers -------------- @@ -90,6 +148,115 @@ def timestamped_out_path(prefix: str = "analysis") -> Path: return Path("perf") / "results" / f"{prefix}_{ts}.csv" +# -------------- Config helpers -------------- + + +def _add_bool_value_arg( + parser: argparse.ArgumentParser, + name: str, + *, + default: bool, + help: str, +) -> None: + parser.add_argument( + f"--{name}", + choices=["true", "false"], + default="true" if default else "false", + help=f"{help} (default: {str(default).lower()})", + ) + + +def _arg_was_passed(argv: List[str], name: str) -> bool: + option = f"--{name}" + return any(arg == option or arg.startswith(f"{option}=") for arg in argv) + + +def _parse_bool_arg(value: str) -> bool: + return value.lower() == "true" + + +def _decode_options_from_args(args: argparse.Namespace) -> dict[str, bool]: + return { + "keep_char_cells": _parse_bool_arg(args.keep_char_cells), + "keep_shapes": _parse_bool_arg(args.keep_shapes), + "keep_bitmaps": _parse_bool_arg(args.keep_bitmaps), + "create_word_cells": _parse_bool_arg(args.create_word_cells), + "create_line_cells": _parse_bool_arg(args.create_line_cells), + } + + +def _materialization_options_from_args(args: argparse.Namespace) -> dict[str, bool]: + return { + "materialize_char_cells": _parse_bool_arg(args.materialize_char_cells), + "materialize_word_cells": _parse_bool_arg(args.materialize_word_cells), + "materialize_line_cells": _parse_bool_arg(args.materialize_line_cells), + "materialize_shapes": _parse_bool_arg(args.materialize_shapes), + "materialize_bitmaps": _parse_bool_arg(args.materialize_bitmaps), + "materialize_bitmap_bytes": _parse_bool_arg(args.materialize_bitmap_bytes), + } + + +def _content_config( + decode_options: dict[str, bool], materialization_options: dict[str, bool] +) -> ContentConfig: + def _level(keep: bool, materialize: bool) -> ContentLevel: + if materialize: + return ContentLevel.COMPUTE_AND_MATERIALIZE + if keep: + return ContentLevel.COMPUTE + return ContentLevel.SKIP + + return ContentConfig( + char_cells_content_level=_level( + decode_options["keep_char_cells"], + materialization_options["materialize_char_cells"], + ), + word_cells_content_level=_level( + decode_options["create_word_cells"], + materialization_options["materialize_word_cells"], + ), + line_cells_content_level=_level( + decode_options["create_line_cells"], + materialization_options["materialize_line_cells"], + ), + shapes_content_level=_level( + decode_options["keep_shapes"], + materialization_options["materialize_shapes"], + ), + bitmaps_content_level=_level( + decode_options["keep_bitmaps"], + materialization_options["materialize_bitmaps"], + ), + include_bitmap_bytes=materialization_options["materialize_bitmap_bytes"], + ) + + +def _content_level_name(value: object) -> object: + if isinstance(value, ContentLevel): + return value.name + if isinstance(value, bool): + return str(value).lower() + return value + + +def print_effective_config( + decode_config: DecodeConfig, + content_config: ContentConfig, +) -> None: + decode_rows = [ + [key, _content_level_name(value)] + for key, value in sorted(decode_config.model_dump().items()) + ] + content_rows = [ + [key, _content_level_name(value)] + for key, value in content_config.model_dump().items() + ] + print("\nEffective decode config:") + print(tabulate(decode_rows, headers=["field", "value"])) + print("\nEffective content config:") + print(tabulate(content_rows, headers=["field", "value"])) + + # -------------- Timing extraction -------------- @@ -108,6 +275,8 @@ def extract_timings_for_page( def analyze_pages( csv_path: Path, top_n: int | None, + decode_config: DecodeConfig, + content_config: ContentConfig, min_sec: float | None = None, *, nth: int | None = None, @@ -150,7 +319,11 @@ def analyze_pages( pages.sort(key=lambda r: r.elapsed_s, reverse=True) try: doc = parser.load( - filename, lazy=True, boundary_type=PdfPageBoundaryType.CROP_BOX + filename, + lazy=True, + boundary_type=PdfPageBoundaryType.CROP_BOX, + decode_config=decode_config, + content_config=content_config, ) except Exception: # Unable to load document; record empty timings for its pages @@ -190,21 +363,35 @@ def analyze_pages( # -------------- Output: --top mode (CSV with static timings) -------------- +def ordered_static_timing_keys() -> List[str]: + ordered: List[str] = [] + + def add_children(parent: str) -> None: + for key in TIMING_CHILDREN.get(parent, []): + if key not in ordered: + ordered.append(key) + add_children(key) + + add_children("pipeline") + for key in sorted(set(get_static_timing_keys()) - set(ordered)): + ordered.append(key) + return ordered + + def write_static_timings_csv(out_path: Path, pages: List[PageTimings]) -> None: - """Write CSV with decode_page timing keys only, one row per page.""" + """Write CSV with static timing keys, one row per page.""" ensure_parent_dir(out_path) - # Get decode_page keys in order (excludes the global decode_page timer) - decode_page_keys = get_decode_page_timing_keys() + timing_keys = ordered_static_timing_keys() - header = ["filename", "page_number", "elapsed_original_sec", *decode_page_keys] + header = ["filename", "page_number", "elapsed_original_sec", *timing_keys] with out_path.open("w", newline="") as f: w = csv.writer(f) w.writerow(header) for p in pages: row = [p.filename, p.page_number, f"{p.elapsed_original:.9f}"] - for k in decode_page_keys: + for k in timing_keys: v = p.timings.get(k, 0.0) row.append(f"{v:.9f}" if v else "") w.writerow(row) @@ -221,36 +408,93 @@ def print_top_summary(pages: List[PageTimings]) -> None: def print_aggregate_breakdown(pages: List[PageTimings]) -> None: - """Average cost and share of each static timing key across the selection. + """Average cost and share of each timing bucket across the selection. - This is the whole-selection view; `--nth` gives the same breakdown for one - page. + Percentages are branch-local to avoid double-counting nested timers. The + `% original` column keeps the link to the per-page cost from run_scaling.py. """ analysed = [p for p in pages if p.timings.data] if not analysed: return total_elapsed = sum(p.elapsed_original for p in analysed) + totals = { + key: sum(p.timings.get(key, 0.0) for p in analysed) + for key in get_static_timing_keys() + } + + root_total = sum(totals.get(key, 0.0) for key in TIMING_CHILDREN["pipeline"]) rows = [] - for key in sorted(get_static_timing_keys()): - key_total = sum(p.timings.get(key, 0.0) for p in analysed) + seen: set[str] = set() + + def add_scope(parent: str) -> None: + children = TIMING_CHILDREN.get(parent, []) + sibling_total = sum(totals.get(key, 0.0) for key in children) + for key in children: + key_total = totals.get(key, 0.0) + if key_total <= 0.0: + continue + seen.add(key) + parent_pct = ( + key_total / sibling_total * 100.0 if sibling_total > 0.0 else 0.0 + ) + original_pct = ( + key_total / total_elapsed * 100.0 if total_elapsed > 0.0 else 0.0 + ) + pipeline_pct = key_total / root_total * 100.0 if root_total > 0.0 else 0.0 + rows.append( + [ + parent, + key, + f"{key_total:.6f}", + f"{key_total / len(analysed):.6f}", + f"{parent_pct:.2f}%", + f"{pipeline_pct:.2f}%", + f"{original_pct:.2f}%", + ] + ) + + for scope in TIMING_CHILDREN: + add_scope(scope) + + for key in sorted(set(get_static_timing_keys()) - seen - NESTED_TIMING_KEYS): + key_total = totals.get(key, 0.0) if key_total <= 0.0: continue - share = (key_total / total_elapsed * 100.0) if total_elapsed > 0 else 0.0 + original_pct = (key_total / total_elapsed * 100.0) if total_elapsed > 0 else 0.0 rows.append( [ + "(unmapped)", key, f"{key_total:.6f}", f"{key_total / len(analysed):.6f}", - f"{share:.2f}%", + "", + "", + f"{original_pct:.2f}%", ] ) if not rows: return - rows.sort(key=lambda r: float(r[1]), reverse=True) print(f"\nTiming breakdown across {len(analysed)} analysed pages:") - print(tabulate(rows, headers=["timing_key", "total_sec", "avg_sec", "avg_%"])) + print( + tabulate( + rows, + headers=[ + "scope", + "timing_key", + "total_sec", + "avg_sec", + "% parent", + "% pipeline", + "% original", + ], + ) + ) + print( + "\nPercentages are not meant to sum down the whole table: nested rows are " + "shown as a share of their parent branch." + ) # -------------- Output: --nth mode (table with all timings) -------------- @@ -315,9 +559,15 @@ def add_timing_row(key: str, is_static: bool): print(tabulate(table_data, headers=headers, tablefmt="grid")) # Print totals - print(f"\nTotal static time: {sum(timings.get_static_timings().values()):.6f} sec") - print(f"Total dynamic time: {sum(timings.get_dynamic_timings().values()):.6f} sec") - print(f"Total all timings: {timings.total():.6f} sec") + print( + "\nSum of reported static timings " + f"(nested; not wall time): {sum(timings.get_static_timings().values()):.6f} sec" + ) + print( + "Sum of reported dynamic timings " + f"(nested; not wall time): {sum(timings.get_dynamic_timings().values()):.6f} sec" + ) + print(f"decode_page timer: {timings.get('decode_page', 0.0):.6f} sec") # -------------- Main -------------- @@ -363,8 +613,82 @@ def main(argv: List[str]) -> int: ap.add_argument( "--threads", type=int, default=None, help="Keep only this thread count" ) + _add_bool_value_arg( + ap, + "keep-char-cells", + default=True, + help="Populate character cells and emit text render instructions", + ) + _add_bool_value_arg( + ap, + "create-word-cells", + default=False, + help="Create word cells during decoding", + ) + _add_bool_value_arg( + ap, + "create-line-cells", + default=False, + help="Create line cells during decoding", + ) + _add_bool_value_arg( + ap, + "keep-shapes", + default=False, + help="Keep vector shape cells", + ) + _add_bool_value_arg( + ap, + "keep-bitmaps", + default=False, + help="Keep bitmap resources/cells", + ) + _add_bool_value_arg( + ap, + "materialize-char-cells", + default=False, + help="Materialize character cells into SegmentedPdfPage", + ) + _add_bool_value_arg( + ap, + "materialize-word-cells", + default=False, + help="Materialize word cells into SegmentedPdfPage", + ) + _add_bool_value_arg( + ap, + "materialize-line-cells", + default=True, + help="Materialize line cells into SegmentedPdfPage", + ) + _add_bool_value_arg( + ap, + "materialize-shapes", + default=False, + help="Materialize vector shapes into SegmentedPdfPage", + ) + _add_bool_value_arg( + ap, + "materialize-bitmaps", + default=True, + help="Materialize bitmap locations into SegmentedPdfPage", + ) + _add_bool_value_arg( + ap, + "materialize-bitmap-bytes", + default=False, + help="Materialize bitmap image bytes when bitmap locations are materialized", + ) args = ap.parse_args(argv) + if args.task == "parse" and not _arg_was_passed(argv, "materialize-bitmaps"): + args.materialize_bitmaps = "false" + + decode_config = DecodeConfig() + content_config = _content_config( + _decode_options_from_args(args), + _materialization_options_from_args(args), + ) # Validate arguments if args.top is None and args.nth is None: @@ -384,6 +708,8 @@ def main(argv: List[str]) -> int: pages = analyze_pages( csv_path, top_n=args.top, + decode_config=decode_config, + content_config=content_config, min_sec=args.min_sec, nth=args.nth, loglevel=args.loglevel, @@ -402,6 +728,7 @@ def main(argv: List[str]) -> int: # Output based on mode if args.nth is not None: # --nth mode: print detailed table + print_effective_config(decode_config, content_config) print_nth_table(pages[0]) else: # --top mode: write CSV with static timings @@ -410,6 +737,7 @@ def main(argv: List[str]) -> int: ) write_static_timings_csv(out_path, pages) print_top_summary(pages) + print_effective_config(decode_config, content_config) print_aggregate_breakdown(pages) print(f"\nWrote static timings CSV: {out_path}") From f08f2d4ce090a1f669f4cdcda6c2e39e5b3c6867 Mon Sep 17 00:00:00 2001 From: Peter Staar Date: Fri, 7 Aug 2026 17:39:05 +0200 Subject: [PATCH 4/9] updating the cmake for extlib_blend2d (2) Signed-off-by: Peter Staar --- cmake/extlib_blend2d.cmake | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/cmake/extlib_blend2d.cmake b/cmake/extlib_blend2d.cmake index 44ba7e14..42aba91f 100644 --- a/cmake/extlib_blend2d.cmake +++ b/cmake/extlib_blend2d.cmake @@ -64,11 +64,9 @@ else() ) # Blend2D defines bl_runtime_assertion_failure() unconditionally in - # runtime.cpp. When linking the static archive with GNU-like linkers, that - # object can be pulled into pdf_parsers even when no release code references - # it. Compile with per-symbol sections and let Linux/MinGW linkers discard - # the unreferenced assertion helper. MSVC Release already uses /OPT:REF and - # macOS arm64 is passing, so keep this scoped to the failing toolchains. + # runtime.cpp. BL_BUILD_RELEASE removes assertion call sites, but the helper + # can still be retained from the static archive unless the final extension + # link can discard unused sections. set(BLEND2D_GNU_GC_SECTIONS "$>,$,$,$>>>") target_compile_options( blend2d @@ -78,5 +76,16 @@ else() blend2d INTERFACE "$<${BLEND2D_GNU_GC_SECTIONS}:-Wl,--gc-sections>" ) + + # MinGW auto-exports global symbols from DLL/PYD links. If symbols from the + # static Blend2D archive are exported, they become linker roots and section + # GC cannot remove bl_runtime_assertion_failure(). Hide static-archive + # symbols from the final Windows GNU extension export table while preserving + # explicitly exported symbols such as the pybind module initializer. + set(BLEND2D_MINGW_EXCLUDE_STATIC_EXPORTS "$>,$,$>") + target_link_options( + blend2d + INTERFACE "$<${BLEND2D_MINGW_EXCLUDE_STATIC_EXPORTS}:-Wl,--exclude-libs,ALL>" + ) # FetchContent creates the target "blend2d" (and alias blend2d::blend2d). endif() From d035c413f181af3925de82fdc46cf4d548728de9 Mon Sep 17 00:00:00 2001 From: Peter Staar Date: Sat, 8 Aug 2026 07:34:45 +0200 Subject: [PATCH 5/9] added more timing keys Signed-off-by: Peter Staar --- perf/run_analysis.py | 13 ++++++++ src/parse/pdf_decoders/page.h | 60 +++++++++++++++++++++++++++++------ src/parse/utils/pdf_timings.h | 28 ++++++++++++++++ 3 files changed, 92 insertions(+), 9 deletions(-) diff --git a/perf/run_analysis.py b/perf/run_analysis.py index 37e8929e..fc5582e8 100644 --- a/perf/run_analysis.py +++ b/perf/run_analysis.py @@ -79,6 +79,19 @@ class PageTimings: "create_line_cells", ], "decode_page": DECODE_PAGE_CHILDREN, + "sanitize_cells": [ + "sanitize_cells.remove_duplicate_cells", + "sanitize_cells.sanitize_text", + ], + "sanitise_contents": [ + "sanitise_contents.copy_cells", + "sanitise_contents.sanitize_bbox", + ], + "create_line_cells": [ + "create_line_cells.copy_cells", + "create_line_cells.sanitize_bbox", + "create_line_cells.remove_duplicate_cells", + ], "decode_contents": [ "content_decode_total", "interprete_ops_total", diff --git a/src/parse/pdf_decoders/page.h b/src/parse/pdf_decoders/page.h index d0e9f38d..bbb6d6b2 100644 --- a/src/parse/pdf_decoders/page.h +++ b/src/parse/pdf_decoders/page.h @@ -882,11 +882,17 @@ namespace pdflib page_item_sanitator sanitator; { + utils::timer step_timer; sanitator.remove_duplicate_cells(page_cells, 0.5, true); + timings.add_timing(pdf_timings::KEY_SANITIZE_CELLS_REMOVE_DUPLICATE_CELLS, + step_timer.get_time()); } { + utils::timer step_timer; sanitator.sanitize_text(page_cells); + timings.add_timing(pdf_timings::KEY_SANITIZE_CELLS_SANITIZE_TEXT, + step_timer.get_time()); } timings.add_timing(pdf_timings::KEY_SANITIZE_CELLS, local.get_time()); } @@ -1847,7 +1853,12 @@ namespace pdflib //sanitator.remove_duplicate_chars(page_cells, 0.5); //sanitator.sanitize_text(page_cells); - cells = page_cells; + { + utils::timer step_timer; + cells = page_cells; + timings.add_timing(pdf_timings::KEY_SANITISE_CONTENTS_COPY_CELLS, + step_timer.get_time()); + } double horizontal_cell_tolerance=1.0; bool enforce_same_font=true; @@ -1855,12 +1866,17 @@ namespace pdflib double space_width_factor_for_merge=1.0; double space_width_factor_for_merge_with_space=0.33; - sanitator.sanitize_bbox(cells, - horizontal_cell_tolerance, - enforce_same_font, - space_width_factor_for_merge, - space_width_factor_for_merge_with_space, - false); + { + utils::timer step_timer; + sanitator.sanitize_bbox(cells, + horizontal_cell_tolerance, + enforce_same_font, + space_width_factor_for_merge, + space_width_factor_for_merge_with_space, + false); + timings.add_timing(pdf_timings::KEY_SANITISE_CONTENTS_SANITIZE_BBOX, + step_timer.get_time()); + } //sanitator.sanitize_text(cells); @@ -1894,10 +1910,36 @@ namespace pdflib page_item_sanitator sanitizer; - line_cells = sanitizer.create_line_cells(page_cells, config); + { + utils::timer step_timer; + line_cells = page_cells; + timings.add_timing(pdf_timings::KEY_CREATE_LINE_CELLS_COPY_CELLS, + step_timer.get_time()); + } + + LOG_S(INFO) << "# char-cells: " << line_cells.size(); + + { + utils::timer step_timer; + sanitizer.sanitize_bbox(line_cells, + config.horizontal_cell_tolerance, + config.enforce_same_font, + config.line_space_width_factor_for_merge, + config.line_space_width_factor_for_merge_with_space, + false); + timings.add_timing(pdf_timings::KEY_CREATE_LINE_CELLS_SANITIZE_BBOX, + step_timer.get_time()); + } + + LOG_S(INFO) << "# line-cells: " << line_cells.size(); // Remove duplicates (quadratic but necessary) - sanitizer.remove_duplicate_cells(line_cells, 0.5, true); + { + utils::timer step_timer; + sanitizer.remove_duplicate_cells(line_cells, 0.5, true); + timings.add_timing(pdf_timings::KEY_CREATE_LINE_CELLS_REMOVE_DUPLICATE_CELLS, + step_timer.get_time()); + } line_cells_created = true; diff --git a/src/parse/utils/pdf_timings.h b/src/parse/utils/pdf_timings.h index 065e528b..7a448424 100644 --- a/src/parse/utils/pdf_timings.h +++ b/src/parse/utils/pdf_timings.h @@ -40,6 +40,11 @@ namespace pdflib static const std::string KEY_SANITISE_CONTENTS; static const std::string KEY_CREATE_WORD_CELLS; static const std::string KEY_CREATE_LINE_CELLS; + static const std::string KEY_SANITISE_CONTENTS_COPY_CELLS; + static const std::string KEY_SANITISE_CONTENTS_SANITIZE_BBOX; + static const std::string KEY_CREATE_LINE_CELLS_COPY_CELLS; + static const std::string KEY_CREATE_LINE_CELLS_SANITIZE_BBOX; + static const std::string KEY_CREATE_LINE_CELLS_REMOVE_DUPLICATE_CELLS; // Additional decode_page step keys static const std::string KEY_TO_JSON_PAGE; @@ -47,6 +52,8 @@ namespace pdflib static const std::string KEY_ROTATE_CONTENTS; static const std::string KEY_SANITIZE_ORIENTATION; static const std::string KEY_SANITIZE_CELLS; + static const std::string KEY_SANITIZE_CELLS_REMOVE_DUPLICATE_CELLS; + static const std::string KEY_SANITIZE_CELLS_SANITIZE_TEXT; // Font timing keys static const std::string KEY_DECODE_FONTS_TOTAL; @@ -419,6 +426,11 @@ namespace pdflib const std::string pdf_timings::KEY_SANITISE_CONTENTS = "sanitise_contents"; const std::string pdf_timings::KEY_CREATE_WORD_CELLS = "create_word_cells"; const std::string pdf_timings::KEY_CREATE_LINE_CELLS = "create_line_cells"; + const std::string pdf_timings::KEY_SANITISE_CONTENTS_COPY_CELLS = "sanitise_contents.copy_cells"; + const std::string pdf_timings::KEY_SANITISE_CONTENTS_SANITIZE_BBOX = "sanitise_contents.sanitize_bbox"; + const std::string pdf_timings::KEY_CREATE_LINE_CELLS_COPY_CELLS = "create_line_cells.copy_cells"; + const std::string pdf_timings::KEY_CREATE_LINE_CELLS_SANITIZE_BBOX = "create_line_cells.sanitize_bbox"; + const std::string pdf_timings::KEY_CREATE_LINE_CELLS_REMOVE_DUPLICATE_CELLS = "create_line_cells.remove_duplicate_cells"; const std::string pdf_timings::KEY_DECODE_FONTS_TOTAL = "decode_fonts_total"; const std::string pdf_timings::KEY_FONT_INIT_COPY = "font: init-copy"; @@ -441,6 +453,8 @@ namespace pdflib const std::string pdf_timings::KEY_ROTATE_CONTENTS = "rotate_contents"; const std::string pdf_timings::KEY_SANITIZE_ORIENTATION = "sanitize_orientation"; const std::string pdf_timings::KEY_SANITIZE_CELLS = "sanitize_cells"; + const std::string pdf_timings::KEY_SANITIZE_CELLS_REMOVE_DUPLICATE_CELLS = "sanitize_cells.remove_duplicate_cells"; + const std::string pdf_timings::KEY_SANITIZE_CELLS_SANITIZE_TEXT = "sanitize_cells.sanitize_text"; const std::string pdf_timings::KEY_PROCESS_DOCUMENT_FROM_FILE = "process_document_from_file"; const std::string pdf_timings::KEY_PROCESS_DOCUMENT_FROM_BYTESIO = "process_document_from_bytesio"; @@ -476,6 +490,11 @@ namespace pdflib KEY_SANITISE_CONTENTS, KEY_CREATE_WORD_CELLS, KEY_CREATE_LINE_CELLS, + KEY_SANITISE_CONTENTS_COPY_CELLS, + KEY_SANITISE_CONTENTS_SANITIZE_BBOX, + KEY_CREATE_LINE_CELLS_COPY_CELLS, + KEY_CREATE_LINE_CELLS_SANITIZE_BBOX, + KEY_CREATE_LINE_CELLS_REMOVE_DUPLICATE_CELLS, KEY_DECODE_FONTS_TOTAL, KEY_FONT_INIT_COPY, KEY_FONT_INIT_METRICS, @@ -499,6 +518,8 @@ namespace pdflib KEY_ROTATE_CONTENTS, KEY_SANITIZE_ORIENTATION, KEY_SANITIZE_CELLS, + KEY_SANITIZE_CELLS_REMOVE_DUPLICATE_CELLS, + KEY_SANITIZE_CELLS_SANITIZE_TEXT, KEY_PROCESS_DOCUMENT_FROM_FILE, KEY_PROCESS_DOCUMENT_FROM_BYTESIO, KEY_QPDF_PROCESS, @@ -564,6 +585,8 @@ namespace pdflib {KEY_SANITIZE_ORIENTATION, KEY_DECODE_PAGE}, {KEY_SANITIZE_CELLS, KEY_DECODE_PAGE}, {KEY_SANITISE_CONTENTS, KEY_DECODE_PAGE}, + {KEY_SANITIZE_CELLS_REMOVE_DUPLICATE_CELLS, KEY_SANITIZE_CELLS}, + {KEY_SANITIZE_CELLS_SANITIZE_TEXT, KEY_SANITIZE_CELLS}, // --- decode_contents sub-timings --- {KEY_CONTENT_DECODE_TOTAL, KEY_DECODE_CONTENTS}, @@ -576,8 +599,13 @@ namespace pdflib {KEY_DO_IMAGE_TOTAL, KEY_DECODE_CONTENTS}, // --- sanitise_contents sub-timings --- + {KEY_SANITISE_CONTENTS_COPY_CELLS, KEY_SANITISE_CONTENTS}, + {KEY_SANITISE_CONTENTS_SANITIZE_BBOX, KEY_SANITISE_CONTENTS}, {KEY_CREATE_WORD_CELLS, KEY_SANITISE_CONTENTS}, {KEY_CREATE_LINE_CELLS, KEY_SANITISE_CONTENTS}, + {KEY_CREATE_LINE_CELLS_COPY_CELLS, KEY_CREATE_LINE_CELLS}, + {KEY_CREATE_LINE_CELLS_SANITIZE_BBOX, KEY_CREATE_LINE_CELLS}, + {KEY_CREATE_LINE_CELLS_REMOVE_DUPLICATE_CELLS, KEY_CREATE_LINE_CELLS}, // --- font sub-timings (aggregated across fonts) --- {KEY_FONT_INIT_COPY, KEY_DECODE_FONTS_TOTAL}, From ce9596600e3f5ab6b3c0fe27a7dd79f9c340d8ff Mon Sep 17 00:00:00 2001 From: Peter Staar Date: Sat, 8 Aug 2026 08:25:20 +0200 Subject: [PATCH 6/9] fixed the scripts check_no_blend2d_assertions.py Signed-off-by: Peter Staar --- scripts/check_no_blend2d_assertions.py | 45 ++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/scripts/check_no_blend2d_assertions.py b/scripts/check_no_blend2d_assertions.py index 6f4b4d8d..340be5b8 100644 --- a/scripts/check_no_blend2d_assertions.py +++ b/scripts/check_no_blend2d_assertions.py @@ -5,10 +5,39 @@ from pathlib import Path -BLEND2D_ASSERTION_MARKERS = ( - b"[Blend2D] ASSERTION FAILURE", - b"bl_runtime_assertion_failure", -) +# Guards that release wheels do not ship Blend2D's debug assertion path, i.e. +# that Blend2D was compiled with BL_BUILD_RELEASE (see cmake/extlib_blend2d.cmake). +# +# Do NOT scan for "[Blend2D] ASSERTION FAILURE" or "bl_runtime_assertion_failure". +# Blend2D compiles bl_runtime_assertion_failure() unconditionally in +# blend2d/core/runtime.cpp -- there is no #ifdef around it -- and its object file +# is always pulled out of libblend2d.a because other symbols in it are needed. +# BL_BUILD_RELEASE only removes the *call sites* (BL_ASSERT in blend2d/core/api.h, +# BL_NOT_REACHED in blend2d/core/api-internal_p.h). So the function and its message +# string enter the link on every platform, and whether they survive into the final +# artifact depends purely on how well the linker dead-strips: +# +# macOS ld64 drops unreferenced cstring literal atoms, plus pybind11's +# POST_BUILD `strip -x`. +# manylinux -ffunction-sections + -Wl,--gc-sections; the literal lives in a +# SHF_MERGE|SHF_STRINGS .rodata.str1.1 and is dropped along with it. +# win_arm64 MSVC: /O2 implies /Gy, the linker's /OPT:REF drops the COMDAT, and +# symbol names go to the PDB rather than into the image. +# win_amd64 MinGW GCC targeting PE/COFF: nothing removes it. --gc-sections for +# COFF/PE is experimental, and COFF has no SHF_MERGE/SHF_STRINGS +# equivalent -- mingw GCC emits all of a translation unit's string +# literals into one shared .rdata, and -fdata-sections does not split +# anonymous string constants. The rest of runtime.cpp.obj keeps that +# .rdata alive, so section-granularity GC can never reach the string. +# +# Those markers therefore produced a false positive on win_amd64 (the only GNU-on-PE +# job in the matrix) for a correctly configured Release build. +# +# BL_NOT_REACHED()'s expression string is a marker that is impossible in a release +# build: only the BL_BUILD_DEBUG expansion emits it as a string literal, while the +# GCC/Clang release expansion is __builtin_unreachable(). With ~100 call sites across +# the library, at least one lands in any linked debug build. +BLEND2D_ASSERTION_MARKERS = (b"BL_NOT_REACHED()",) NATIVE_SUFFIXES = {".so", ".pyd", ".dll", ".dylib"} @@ -67,12 +96,16 @@ def main(argv: list[str]) -> int: findings.extend(scan_file(item)) if findings: - print("Blend2D assertion machinery found in release artifact:", file=sys.stderr) + print( + "Blend2D debug assertion code found in release artifact " + "(Blend2D was not compiled with BL_BUILD_RELEASE):", + file=sys.stderr, + ) for finding in findings: print(f" {finding}", file=sys.stderr) return 1 - print("No Blend2D assertion machinery found.") + print("No Blend2D debug assertion code found.") return 0 From 904a5594175d29c6cc43308cd41ec384f0ccce61 Mon Sep 17 00:00:00 2001 From: Peter Staar Date: Mon, 10 Aug 2026 10:09:26 +0200 Subject: [PATCH 7/9] removed double compute of cells Signed-off-by: Peter Staar --- src/parse/config.h | 13 ++++++--- src/parse/pdf_decoders/page.h | 55 +++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/parse/config.h b/src/parse/config.h index aed5628b..ad0111a4 100644 --- a/src/parse/config.h +++ b/src/parse/config.h @@ -8,6 +8,10 @@ namespace pdflib struct decode_config { + static constexpr double DEFAULT_HORIZONTAL_CELL_TOLERANCE = 1.0; + static constexpr double DEFAULT_WORD_SPACE_WIDTH_FACTOR_FOR_MERGE = 0.33; + static constexpr double DEFAULT_LINE_SPACE_WIDTH_FACTOR_FOR_MERGE = 1.0; + static constexpr double DEFAULT_LINE_SPACE_WIDTH_FACTOR_FOR_MERGE_WITH_SPACE = 0.33; static constexpr double DEFAULT_MIN_VISIBLE_CLIP_EXTENT = 1e-3; std::string page_boundary = "crop_box"; @@ -27,14 +31,15 @@ namespace pdflib bool enforce_same_font = true; // word & line cell creation // word & line cell creation parameters - double horizontal_cell_tolerance = 1.0; + double horizontal_cell_tolerance = DEFAULT_HORIZONTAL_CELL_TOLERANCE; // word cell creation - double word_space_width_factor_for_merge = 0.33; + double word_space_width_factor_for_merge = DEFAULT_WORD_SPACE_WIDTH_FACTOR_FOR_MERGE; // line cell creation - double line_space_width_factor_for_merge = 1.0; - double line_space_width_factor_for_merge_with_space = 0.33; + double line_space_width_factor_for_merge = DEFAULT_LINE_SPACE_WIDTH_FACTOR_FOR_MERGE; + double line_space_width_factor_for_merge_with_space = + DEFAULT_LINE_SPACE_WIDTH_FACTOR_FOR_MERGE_WITH_SPACE; bool populate_json_objects = false; diff --git a/src/parse/pdf_decoders/page.h b/src/parse/pdf_decoders/page.h index bbb6d6b2..4dc14c5a 100644 --- a/src/parse/pdf_decoders/page.h +++ b/src/parse/pdf_decoders/page.h @@ -130,6 +130,8 @@ namespace pdflib void rotate_contents(); + bool can_reuse_sanitised_cells_for_line_cells(const decode_config& config) const; + void sanitise_contents(std::string page_boundary); private: @@ -173,6 +175,7 @@ namespace pdflib // Computed cell aggregations page_item word_cells; page_item line_cells; + bool sanitised_cells_created = false; bool word_cells_created = false; bool line_cells_created = false; @@ -809,6 +812,7 @@ namespace pdflib void pdf_decoder::decode_page(const decode_config& config) { page_config = config; + sanitised_cells_created = false; if(owned_qpdf_document != nullptr) { @@ -1834,6 +1838,19 @@ namespace pdflib page_hyperlinks.rotate(angle, delta); } + bool pdf_decoder::can_reuse_sanitised_cells_for_line_cells(const decode_config& config) const + { + return (sanitised_cells_created and + config.do_sanitization and + config.enforce_same_font and + ((config.horizontal_cell_tolerance - + config.DEFAULT_HORIZONTAL_CELL_TOLERANCE) < 1.e-6) and + ((config.line_space_width_factor_for_merge - + config.DEFAULT_LINE_SPACE_WIDTH_FACTOR_FOR_MERGE) < 1.e-6) and + ((config.line_space_width_factor_for_merge_with_space - + config.DEFAULT_LINE_SPACE_WIDTH_FACTOR_FOR_MERGE_WITH_SPACE) < 1.e-6)); + } + void pdf_decoder::sanitise_contents(std::string page_boundary) { LOG_S(INFO) << __FUNCTION__; @@ -1860,11 +1877,14 @@ namespace pdflib step_timer.get_time()); } - double horizontal_cell_tolerance=1.0; + double horizontal_cell_tolerance = + decode_config::DEFAULT_HORIZONTAL_CELL_TOLERANCE; bool enforce_same_font=true; //double space_width_factor_for_merge=1.5; - double space_width_factor_for_merge=1.0; - double space_width_factor_for_merge_with_space=0.33; + double space_width_factor_for_merge = + decode_config::DEFAULT_LINE_SPACE_WIDTH_FACTOR_FOR_MERGE; + double space_width_factor_for_merge_with_space = + decode_config::DEFAULT_LINE_SPACE_WIDTH_FACTOR_FOR_MERGE_WITH_SPACE; { utils::timer step_timer; @@ -1878,6 +1898,8 @@ namespace pdflib step_timer.get_time()); } + sanitised_cells_created = true; + //sanitator.sanitize_text(cells); LOG_S(INFO) << "#-page-cells: " << page_cells.size(); @@ -1909,27 +1931,30 @@ namespace pdflib utils::timer timer; page_item_sanitator sanitizer; + const bool reuse_sanitised_cells = + can_reuse_sanitised_cells_for_line_cells(config); { utils::timer step_timer; - line_cells = page_cells; + line_cells = reuse_sanitised_cells ? cells : page_cells; timings.add_timing(pdf_timings::KEY_CREATE_LINE_CELLS_COPY_CELLS, step_timer.get_time()); } LOG_S(INFO) << "# char-cells: " << line_cells.size(); - { - utils::timer step_timer; - sanitizer.sanitize_bbox(line_cells, - config.horizontal_cell_tolerance, - config.enforce_same_font, - config.line_space_width_factor_for_merge, - config.line_space_width_factor_for_merge_with_space, - false); - timings.add_timing(pdf_timings::KEY_CREATE_LINE_CELLS_SANITIZE_BBOX, - step_timer.get_time()); - } + if(!reuse_sanitised_cells) + { + utils::timer step_timer; + sanitizer.sanitize_bbox(line_cells, + config.horizontal_cell_tolerance, + config.enforce_same_font, + config.line_space_width_factor_for_merge, + config.line_space_width_factor_for_merge_with_space, + false); + timings.add_timing(pdf_timings::KEY_CREATE_LINE_CELLS_SANITIZE_BBOX, + step_timer.get_time()); + } LOG_S(INFO) << "# line-cells: " << line_cells.size(); From 80ed8ef28f89f892a602661f651cd7b179497150 Mon Sep 17 00:00:00 2001 From: Peter Staar Date: Mon, 10 Aug 2026 17:30:30 +0200 Subject: [PATCH 8/9] updated the docs after the latest optimizations Signed-off-by: Peter Staar --- ..._m3_max_performance-dataset-bo767_parse.md | 114 +++++++++++++ ...ng-parse-parse-_vs_pdfminer.six-parse-.png | Bin 0 -> 151543 bytes ...ling-parse-parse-_vs_pdfplumber-parse-.png | Bin 0 -> 153603 bytes ...docling-parse-parse-_vs_pymupdf-parse-.png | Bin 0 -> 206826 bytes ...g_docling-parse-parse-_vs_pypdf-parse-.png | Bin 0 -> 165009 bytes ...cling-parse-parse-_vs_pypdfium2-parse-.png | Bin 0 -> 173837 bytes .../hist_pages_per_document.png | Bin 0 -> 31888 bytes .../hist_stacked.png | Bin 0 -> 254755 bytes .../scaling_parse.png | Bin 0 -> 64555 bytes ...m3_max_performance-dataset-bo767_render.md | 51 +++--- ...se-render-_vs_pdfplumber-parse-render-.png | Bin 151334 -> 157951 bytes ...parse-render-_vs_pymupdf-parse-render-.png | Bin 179592 -> 174795 bytes ...rse-render-_vs_pypdfium2-parse-render-.png | Bin 164729 -> 161536 bytes .../hist_stacked.png | Bin 202451 -> 229219 bytes .../scaling_parse-render.png | Bin 69779 -> 77950 bytes perf/run_scaling.py | 159 +++++++++++++++++- src/parse/page_item_sanitators/cells.h | 12 +- src/parse/pdf_decoders/document.h | 12 ++ src/parse/pdf_decoders/page.h | 61 ++++++- src/parse/utils/pdf_timings.h | 16 ++ 20 files changed, 392 insertions(+), 33 deletions(-) create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse.md create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pdfminer.six-parse-.png create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pdfplumber-parse-.png create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pymupdf-parse-.png create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pypdf-parse-.png create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pypdfium2-parse-.png create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hist_pages_per_document.png create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hist_stacked.png create mode 100644 docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/scaling_parse.png diff --git a/docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse.md b/docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse.md new file mode 100644 index 00000000..085ba13a --- /dev/null +++ b/docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse.md @@ -0,0 +1,114 @@ + + +# Benchmark — docling-project/performance-dataset-bo767 on Apple M3 Max + +Generated: 2026-08-10T14:11:21 + +## Command + +```sh +python ./perf/run_scaling.py --threads 1,2,4,8,12 --compare all --mode parse --output-dir ./scratch8 --materialize-bitmaps=false +``` + +## Benchmark + +| parameter | value | +|------------------------|----------------------------------------------------------------------------------| +| dataset | docling-project/performance-dataset-bo767 | +| dataset source | huggingface | +| dataset revision | c684df54de2081a6de1192cee12713b54759c6bb | +| documents | 753 | +| pages | 54584 | +| mode | parse | +| thread counts | [1, 2, 4, 8, 12] | +| max concurrent results | 64 | +| other backends | ['pypdfium2'] | +| comparison suite | ['docling-parse', 'pymupdf', 'pypdfium2', 'pdfplumber', 'pdfminer.six', 'pypdf'] | +| max pages | (all) | +| pdf selection | (all) | +| bytesio | False | + +## System + +| parameter | value | +|----------------|---------------| +| cpu | Apple M3 Max | +| physical cores | 16 | +| logical cores | 16 | +| memory (GB) | 64.0 | +| platform | Darwin 25.2.0 | +| arch | arm64 | +| python | 3.12.11 | +| docling-parse | 7.11.0 | +| pymupdf | 1.27.1 | +| pypdfium2 | 5.4.0 | +| pdfplumber | 0.11.9 | +| pdfminer.six | 20251230 | +| pypdf | 6.14.2 | +| pillow | 12.2.0 | + +## Decode config + +| parameter | value | +|----------------------------------------------|---------| +| do_sanitization | 1 | +| enforce_same_font | 1 | +| horizontal_cell_tolerance | 1 | +| word_space_width_factor_for_merge | 0.33 | +| line_space_width_factor_for_merge | 1 | +| line_space_width_factor_for_merge_with_space | 0.33 | +| max_num_lines | -1 | +| max_num_bitmaps | -1 | +| do_thread_safe | 1 | +| release_native_memory_every_n_pages | 0 | +| keep_glyphs | 0 | +| keep_qpdf_warnings | 0 | + +## Content config + +| parameter | value | +|--------------------------|---------| +| char\_cells\_content\_level | 1 | +| word_cells_content_level | 0 | +| line_cells_content_level | 2 | +| shapes_content_level | 0 | +| bitmaps_content_level | 0 | +| include_bitmap_bytes | 0 | + +## Render config + +| parameter | value | +|-------------|---------| +| enabled | False | + +## Parsing and rendering performance + +| System hardware | dataset | Python package | Task | threads | total time (s) | average time/page | median time/page | 95 quantile time/page | 99 quantile time/page | +|--------------------------------------------------|---------------------------------------------------------------------------|------------------|---------|-----------|------------------|---------------------|--------------------|-------------------------|-------------------------| +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | docling-parse | `parse` | 1 | 601.31 | 11.0 ms | 8.0 ms | 29.8 ms | 52.8 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | docling-parse | `parse` | 2 | 314.2 | 11.4 ms | 8.2 ms | 31.1 ms | 54.9 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | docling-parse | `parse` | 4 | 167 | 12.0 ms | 8.6 ms | 32.6 ms | 58.8 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | docling-parse | `parse` | 8 | 85.42 | 12.4 ms | 8.9 ms | 33.3 ms | 60.2 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | docling-parse | `parse` | 12 | 71.61 | 14.2 ms | 10.3 ms | 38.7 ms | 70.3 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | pymupdf | `parse` | 1 | 1370.85 | 25.1 ms | 6.0 ms | 109.8 ms | 212.8 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | pypdfium2 | `parse` | 1 | 255.23 | 4.7 ms | 1.6 ms | 17.5 ms | 42.9 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | pdfplumber | `parse` | 1 | 2028.03 | 37.2 ms | 20.1 ms | 102.9 ms | 220.4 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | pdfminer.six | `parse` | 1 | 2230.88 | 40.9 ms | 13.6 ms | 79.4 ms | 315.9 ms | +| Apple M3 Max, 16 cores, 64 GB RAM, Darwin 25.2.0 | docling-project/performance-dataset-bo767@c684df5 (753 docs, 54584 pages) | pypdf | `parse` | 1 | 747.7 | 13.7 ms | 4.1 ms | 37.6 ms | 181.0 ms | + +## Thread scaling and speedup + +Task: `parse` + +| python package | threads | total time (s) | pages/sec | vs docling-parse (1t) | vs pymupdf (1t) | vs pypdfium2 (1t) | vs pdfplumber (1t) | vs pdfminer.six (1t) | vs pypdf (1t) | +|------------------|-----------|------------------|-------------|-------------------------|-------------------|---------------------|----------------------|------------------------|-----------------| +| docling-parse | 1 | 601.31 | 90.8 | 1.00x | 2.28x | 0.42x | 3.37x | 3.71x | 1.24x | +| docling-parse | 2 | 314.2 | 173.7 | 1.91x | 4.36x | 0.81x | 6.45x | 7.10x | 2.38x | +| docling-parse | 4 | 167 | 326.9 | 3.60x | 8.21x | 1.53x | 12.14x | 13.36x | 4.48x | +| docling-parse | 8 | 85.42 | 639 | 7.04x | 16.05x | 2.99x | 23.74x | 26.12x | 8.75x | +| docling-parse | 12 | 71.61 | 762.2 | 8.40x | 19.14x | 3.56x | 28.32x | 31.15x | 10.44x | +| pymupdf | 1 | 1370.85 | 39.8 | 0.44x | 1.00x | 0.19x | 1.48x | 1.63x | 0.55x | +| pypdfium2 | 1 | 255.23 | 213.9 | 2.36x | 5.37x | 1.00x | 7.95x | 8.74x | 2.93x | +| pdfplumber | 1 | 2028.03 | 26.9 | 0.30x | 0.68x | 0.13x | 1.00x | 1.10x | 0.37x | +| pdfminer.six | 1 | 2230.88 | 24.5 | 0.27x | 0.61x | 0.11x | 0.91x | 1.00x | 0.34x | +| pypdf | 1 | 747.7 | 73 | 0.80x | 1.83x | 0.34x | 2.71x | 2.98x | 1.00x | diff --git a/docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pdfminer.six-parse-.png b/docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pdfminer.six-parse-.png new file mode 100644 index 0000000000000000000000000000000000000000..7a98f3db85927a5fa013ad32c53add7b93863835 GIT binary patch literal 151543 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 z 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%0D^rPMIG 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 literal 0 HcmV?d00001 diff --git a/docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pdfplumber-parse-.png b/docs/performance_benchmarks/apple_m3_max_performance-dataset-bo767_parse/hex_loglog_docling-parse-parse-_vs_pdfplumber-parse-.png new file mode 100644 index 0000000000000000000000000000000000000000..b9aba5211a5ae529d8a9778b44436b316263466d GIT binary patch literal 153603 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\{i4JykggLe|Hu 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
>j_<2rwE%-nSr z&3{YSm5Ksxb29Ra(WIRdZ!>n;fhXTnDsno~E@4licL*brd2c_zNN+->BOHkw2!Itp zzxIC9{ztoXEeY=G;dYl3DS2mwm2qL}mJ1teT{0CqOa_SRM9!z)CGkzV>nmn@0qBw& znC!Jz`Uc#YOxpOKvR51u)o?f|NkGU`TY8srUhAKA-Trns=C@)ta*nd^U~&9!PlLG@ z@B`TyChFqd)l>J7sJM_e%SfWVTbNMIYyqn3!_i>txb+xXFg}6}`AeU%mxdSnyU$c| zUq_<$H-b+{65}6&Wi-6}0>BMDl-3tvo7OCJhgkK&fe#GpZIBUQC%(hS68y)AQc^Q) z!ay6{@AO&a|3w9i7HAWDj!Z5+e7f%3~5Sn2|G5^(^T{_gTdvMzS?zeBCt5H(Q$-9;haYwF|pRI zFG>Gg3V(~2Gp#-I8VC0L{l|0t0pnBwd|7tEW@P!T5!!S?LRzL;CZD*TW$w%}XAL&Z zR{d%Ub^o5?yE$gga93^CdEMe^q6UOp)=W`+hpxK3H