Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand Down Expand Up @@ -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/
Expand Down Expand Up @@ -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/
Expand Down Expand Up @@ -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
Expand Down
33 changes: 33 additions & 0 deletions cmake/extlib_blend2d.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,38 @@ 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 $<$<NOT:$<CONFIG:Debug>>:BL_BUILD_RELEASE>
)

# Blend2D defines bl_runtime_assertion_failure() unconditionally in
# 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 "$<AND:$<NOT:$<CONFIG:Debug>>,$<OR:$<PLATFORM_ID:Linux>,$<AND:$<PLATFORM_ID:Windows>,$<CXX_COMPILER_ID:GNU>>>>")
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>"
)

# 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 "$<AND:$<NOT:$<CONFIG:Debug>>,$<PLATFORM_ID:Windows>,$<CXX_COMPILER_ID:GNU>>")
target_link_options(
blend2d
INTERFACE "$<${BLEND2D_MINGW_EXCLUDE_STATIC_EXPORTS}:-Wl,--exclude-libs,ALL>"
)
# FetchContent creates the target "blend2d" (and alias blend2d::blend2d).
endif()
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
<!-- generated by perf/run_scaling.py -->

# 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 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading