Skip to content

Commit 4960389

Browse files
committed
Tune queue_size defaults per input type and document recommendations
An unset queue_size now defaults to 1000 for local directories (where the queue holds only file paths, as it historically did) and to 1.2 * n for archive and s3 streaming (where a whole chunk is materialized in memory), keeping 20% headroom over the thread pool. The queue_size entry was dropped from the shipped config.json so these defaults apply out of the box, and the README gains a "Choosing a queue size" section with tuning guidance.
1 parent b010b53 commit 4960389

4 files changed

Lines changed: 42 additions & 10 deletions

File tree

Readme.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,6 @@ settings.
384384
```json
385385
{
386386
"grobid_server": "http://localhost:8070",
387-
"queue_size": 1000,
388387
"sleep_time": 5,
389388
"timeout": 60,
390389
"coordinates": [
@@ -403,7 +402,7 @@ settings.
403402
| Parameter | Description | Default |
404403
|-----------------|------------------------------------------------------------------------------------------------------------------|-------------------------|
405404
| `grobid_server` | GROBID server URL | `http://localhost:8070` |
406-
| `queue_size` | Number of files queued per processing chunk. If not set, it follows the concurrency `n` so the thread pool is never starved. **Tune carefully: a large queue size will result in the data being written less frequently, and on the archive/S3 paths a whole chunk is held in memory at once** | same as `n` |
405+
| `queue_size` | Number of files queued per processing chunk. See [Choosing a queue size](#choosing-a-queue-size). | 1000 for local directories, 1.2 × `n` for archives and S3 |
407406
| `sleep_time` | Wait time when server is busy (seconds) | 5 |
408407
| `timeout` | Client-side timeout (seconds) | 180 |
409408
| `coordinates` | XML elements for coordinate extraction | See above |
@@ -413,6 +412,24 @@ settings.
413412
> Since version 0.0.12, the config file is optional. The client will use default localhost settings if no configuration
414413
> is provided.
415414
415+
### Choosing a queue size
416+
417+
`queue_size` controls how many files are grouped into one processing chunk. It is a memory/durability knob, not a
418+
concurrency one: parallelism toward the GROBID server is set by `-n`, and each chunk is processed `n` files at a time.
419+
When `queue_size` is not set, the client picks a sensible default per input type (see the table above); set it
420+
explicitly only if you need to override that. A few guidelines:
421+
422+
- **Never set it below `n`.** Effective parallelism is `min(n, queue_size)`: a queue smaller than the thread pool
423+
leaves workers idle. A bit of headroom above `n` (the default streaming value is 1.2 × `n`) keeps the pool busy.
424+
- **Results are written per chunk.** Output files land on disk only once a whole chunk has been processed, so a
425+
larger queue means results are written less frequently and an interrupted run loses at most one chunk of work
426+
(already-written results are skipped on re-run unless `--force` is used).
427+
- **Local PDF directories:** the queue holds only file paths, so large values are essentially free — the default is
428+
1000. Lower it if you want results flushed to disk more often on long runs.
429+
- **Archives (zip/tar) and S3:** each chunk is read or downloaded *into memory* before processing starts, so peak RAM
430+
grows with `queue_size × average file size`. Keep it moderate — the 1.2 × `n` default is a safe floor; going up to
431+
a few multiples of `n` (e.g. 2–5 ×) trades memory for slightly better throughput around chunk boundaries.
432+
416433
> [!WARNING]
417434
> **Citation consolidation and the `timeout` setting.** When `--consolidate_citations` (or `consolidate_citations=True`)
418435
> is enabled, GROBID queries external services (e.g. CrossRef) to enrich the extracted references. This is considerably

config.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
{
22
"grobid_server": "http://localhost:8070",
3-
"queue_size": 1000,
43
"timeout": 180,
54
"sleep_time": 5,
65
"coordinates": [

grobid_client/grobid_client.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"""
1717
from __future__ import annotations
1818

19+
import math
1920
import os
2021
import io
2122
import json
@@ -163,13 +164,25 @@ def _set_config_params(self, params: dict) -> None:
163164
if value is not None:
164165
self.config[key] = value
165166

166-
def _effective_queue_size(self, n: int) -> int:
167-
"""Return the configured queue_size, defaulting to the concurrency n.
167+
# Default chunk size when walking a local directory: only file paths are
168+
# queued (nothing is pre-loaded), so a large chunk costs next to nothing.
169+
LOCAL_DIR_QUEUE_SIZE = 1000
170+
171+
def _effective_queue_size(self, n: int, local_files: bool = False) -> int:
172+
"""Return the configured queue_size, or a default derived from n.
168173
169174
A queue smaller than the thread pool leaves workers idle, so when no
170-
explicit value is configured the chunk size follows n.
175+
explicit value is configured the chunk size follows the concurrency n,
176+
with 20% headroom to keep the pool busy around the chunk boundary. For
177+
local directories, where the queue holds only file paths, a large
178+
fixed default is used instead.
171179
"""
172-
return self.config.get("queue_size") or n
180+
configured = self.config.get("queue_size")
181+
if configured:
182+
return configured
183+
if local_files:
184+
return self.LOCAL_DIR_QUEUE_SIZE
185+
return math.ceil(n * 1.2)
173186

174187
def _warn_on_consolidation_timeout(self, consolidate_citations: bool) -> None:
175188
"""Warn when citation consolidation is enabled with a low client timeout.
@@ -869,7 +882,7 @@ def _run_file_batches(
869882
870883
Returns the aggregated (processed, errors, skipped) counts.
871884
"""
872-
queue_size = self._effective_queue_size(n)
885+
queue_size = self._effective_queue_size(n, local_files=True)
873886
processed_files_count = 0
874887
errors_files_count = 0
875888
skipped_files_count = 0

tests/test_grobid_client.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,17 @@ def test_init_default_values(self, mock_configure_logging, mock_test_server):
5252
@patch('grobid_client.grobid_client.GrobidClient._test_server_connection')
5353
@patch('grobid_client.grobid_client.GrobidClient._configure_logging')
5454
def test_effective_queue_size(self, mock_configure_logging, mock_test_server):
55-
"""Test that an unset queue_size defaults to the concurrency n."""
55+
"""Test the queue_size defaults: 1.2 * n for streaming, 1000 for local dirs."""
5656
mock_test_server.return_value = (True, 200)
5757

5858
client = GrobidClient(check_server=False)
59-
assert client._effective_queue_size(40) == 40
59+
assert client._effective_queue_size(40) == 48
60+
assert client._effective_queue_size(10) == 12
61+
assert client._effective_queue_size(40, local_files=True) == 1000
6062

6163
client.config['queue_size'] = 100
6264
assert client._effective_queue_size(40) == 100
65+
assert client._effective_queue_size(40, local_files=True) == 100
6366

6467
@patch('grobid_client.grobid_client.GrobidClient._test_server_connection')
6568
@patch('grobid_client.grobid_client.GrobidClient._configure_logging')

0 commit comments

Comments
 (0)