docling-project / docling-project/docling

Feature request: public API to release ConversionResult backend after convert() returns

Open
#3,491 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
66.4k
Forks
4.8k
Avg merge
3d 4h
Merged PRs (30d)
95

Description

### Problem

After `DocumentConverter.convert(...)` returns, the parsing backend (PyMuPDF for PDF, docling-parse for some image formats) reachable at `ConversionResult.input._backend` continues to hold OS-level file handles and memory-mapped regions until the `ConversionResult` is garbage-collected.

On long-running batch conversions this causes:

- Open file-descriptor accumulation. On macOS the default per-process soft limit is 256 (`ulimit -n`), which is reachable on PDF batches in the 200+ file range before GC pressure resolves it.
- Resident-memory growth from `mmap` regions the OS does not reclaim until the holding Python object is collected.
- Slow tear-down at end-of-batch because GC settles asynchronously on the conversion thread.

The `DoclingDocument` is fully built by the time `convert()` returns — the backend is no longer producing pages — so releasing it immediately is safe.

### Current workaround

```python
backend = conv_res.input._backend # private attribute
if backend is not None:
backend.unload()
```

This reaches into `InputDocument._backend`, which is private; the leading underscore signals the attribute can be renamed or restructured at any minor release.

Verified against `docling==2.95.0`, `docling-core==2.77.0` (via `dir(InputDocument)` / `dir(ConversionResult)`): neither class exposes any `unload` / `release` / `close` / `cleanup` / `discard` method. Only `ConversionResult.load` exists (the opposite direction). `InputDocument._backend` is the only access point to the backend instance.

### Proposed API shapes (any one would resolve)

**1. Method on `ConversionResult`:**

```python
conv_res = converter.convert(source)
# ... process conv_res.document ...
conv_res.release() # or conv_res.unload_input()
```

**2. Context-manager shape:**

```python
with converter.convert(source) as conv_res:
# ... process conv_res.document ...
# backend released on __exit__
```

**3. Method on `InputDocument`:**

```python
conv_res.input.release()
```

Any of these would let downstream batch consumers free backend resources promptly without touching private attributes.

### Context

This is a feature request, not a bug. The implementation is small — one method delegating to the existing backend `.unload()`. Happy to open a PR if a preferred shape is indicated.

Contributor guide

Open the contributing guide

Research direction

Start at DocumentConverter.convert() and the ConversionResult and InputDocument entry points, then trace how InputDocument._backend is created and how its existing unload() is used. Select one public release shape, cover backend cleanup after conversion including the no-backend case, and verify that the completed document remains usable.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.