4.3 KiB
3. What gridSize actually controls
← Previous | README | Next: The writer and the beanMapped trap →
Every tutorial on partitioning, including the reference documentation, describes gridSize as
"the number of partitions." That is true for the two built-in Partitioner implementations that
actually consult it (a custom range-based partitioner is expected to divide its input into
gridSize pieces). It is not true for MultiResourcePartitioner, the one this module uses, and
the gap between the two is easy to fall into.
Decompiling the claim
unzip -o spring-batch-core-6.0.5.jar org/springframework/batch/core/partition/support/MultiResourcePartitioner.class,
then javap -c on it, shows partition(int) looping over the configured resources array and
never once loading its int parameter. The bytecode has no iload_1 on the gridSize slot inside
the loop at all — only on the array-bounds check iload; iload; if_icmpge, which compares
the loop counter against resources.length, not against gridSize.
Proving it by running it, not just reading it
PartitionerGridSizeTest
asserts this directly: three real temp files, partition(10), three partitions back:
$ mvn test -Dtest=PartitionerGridSizeTest
Full transcript: docs/output/02-gridsize-ignored.txt.
And the same thing at the level of a real job: three shard files on disk, --partition.grid-size=10,
--partition.pool-core-size=10:
2026-09-14T09:10:38.720Z ... Executing step: [ordersWorkerStep:partition0]
2026-09-14T09:10:38.728Z ... Executing step: [ordersWorkerStep:partition2]
2026-09-14T09:10:38.732Z ... Executing step: [ordersWorkerStep:partition1]
JOB FINISHED: id=1 status=COMPLETED exitCode=COMPLETED
Three "Executing step" lines. Never a fourth, never a tenth, regardless of what gridSize says.
So what does gridSize control?
Two things, both real, neither of them "how many partitions run" when your Partitioner ignores
the argument:
- What gets passed to
Partitioner.partition(int). A partitioner that does read its argument (a hand-written range partitioner dividing one large table intogridSizekey ranges, for instance) is controlled by this value directly.MultiResourcePartitionersimply happens not to be one of those. - The
PartitionHandler's own accounting, if you build one yourself with.partitionHandler(...)instead of lettingPartitionStepBuilderconstruct a defaultTaskExecutorPartitionHandlerfrom.taskExecutor(...)and.gridSize(...). This module uses the builder's default wiring, so itsgridSizeandTaskExecutorPartitionHandler's internal grid size are the same number by construction — but nothing stops them from diverging if you wire aPartitionHandlerbean explicitly with its ownsetGridSize(...).
The number of partitions that actually run is decided entirely by what
Partitioner.partition(gridSize) returns — a Map — not by the int it was
handed. For MultiResourcePartitioner, that means: however many files are in
partition.shards-dir. Full stop. Sizing gridSize to match core count (chapter 6) only works if
you also size the number of shard files to match, which this module's benchmarking scripts do
deliberately (see scripts/generate-shards.py).
Going deeper
Partitionerand the other built-in implementation,SimplePartitioner(one partition, no data division at all — used internally when no explicit partitioner is set): Spring Batch reference — the Partitioner interface (rel="nofollow").- Writing a partitioner that does use gridSize (a key-range partitioner over a database table):
Spring Batch samples — ColumnRangePartitioner (
rel="nofollow").