Skip to content

Commit 9f3f256

Browse files
anidotnetclaude
andcommitted
Make the sorted-page cost guard survive a slow runner
The v5.1.0 tag build failed on the Windows runner and nowhere else, on this guard: fat 14.5 ms against lean 2.7 ms, a 5.4x ratio through a 4x threshold, with the index-ordered sort in place and working. `release.yml` gates on Build succeeding, so the Maven Central publish was skipped and 5.1.0 never shipped. The threshold was not the problem, the shape was. The guard compares a sorted page over lean documents against one over fat documents at the same row count, so that the index walk - identical in both - cancels and only the decode differs. But a page of 20 fat documents costs more to return than a page of 20 lean ones no matter how the order was decided, and that difference is the floor of the ratio. On this machine it is noise; on the Windows runner it was most of the measurement. Asking for one row instead of twenty shrinks that floor twentyfold while leaving the discarded-row decode at full size. Measured here: 0.56x with the index-ordered sort against 85x without it, so a 3x threshold now sits five times clear of a passing run rather than seven-tenths of the way to a failing one. Test-only. Also dates the 5.1.0 changelog entry correctly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent ab91339 commit 9f3f256

2 files changed

Lines changed: 18 additions & 11 deletions

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
## Release 5.1.0 - Aug 14, 2026
1+
## Release 5.1.0 - Aug 22, 2026
22

33
### Improvements
44

‎nitrite-mvstore-adapter/src/test/java/org/dizitart/no2/integration/collection/CollectionSortedFindCostTest.java‎

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,13 @@
4545
* {@code orderBy(indexed).limit(20)} cost what draining the whole collection cost - and the
4646
* gap grows with document size, not just document count. Taking the sort keys from the index
4747
* removes the decode: over 2000 rows carrying a 150-element array the sorted page went from
48-
* ~37 ms to ~1 ms.
48+
* ~115 ms to ~2 ms.
4949
*
5050
* @author Anindya Chatterjee
5151
*/
5252
public class CollectionSortedFindCostTest {
5353
private static final int ROWS = 2000;
54+
private static final int PAYLOAD = 150;
5455

5556
private final String fileName = getRandomTempDbFile();
5657
private Nitrite db;
@@ -72,22 +73,28 @@ public void tearDown() {
7273

7374
/**
7475
* The same query, the same row count, the same index - only the size of the documents
75-
* differs. A sorted page that decodes every row pays for the payload of every row, so
76-
* the fat collection costs many times the lean one. A sorted page that decodes only the
77-
* rows it returns costs the same either way.
76+
* differs. A sorted page that decodes every row pays for the payload of every row, so the
77+
* fat collection costs many times the lean one. A sorted page that decodes only the row it
78+
* returns costs about the same either way.
7879
* <p>
79-
* Deliberately not "sorted page vs. full drain": both halves here are measured back to
80-
* back under whatever load the machine is under, and the only variable between them is
81-
* the thing that was broken.
80+
* Both halves walk an index of identical size and shape, so that cost cancels; what does
81+
* not cancel is the payload of the rows each one decodes. The page is deliberately one row
82+
* rather than twenty: returning a fat document legitimately costs more than returning a
83+
* lean one, and that difference is the floor of this ratio, so the fewer rows the page
84+
* returns the more of the ratio is the {@link #ROWS} rows it should never have touched.
85+
* <p>
86+
* Deliberately not "sorted page vs. unsorted page", whose halves do not share the index
87+
* walk, nor "sorted page vs. full drain", whose halves share nothing at all. Both halves
88+
* here are measured back to back, under whatever load the machine is under.
8289
*/
8390
@Test
8491
public void testSortedPageCostDoesNotFollowDocumentSize() {
8592
double lean = sortedPageCost("lean", 0);
86-
double fat = sortedPageCost("fat", 150);
93+
double fat = sortedPageCost("fat", PAYLOAD);
8794

8895
assertTrue("a sorted page over fat documents took " + fat + "ms against " + lean
8996
+ "ms over lean ones, same row count - it is still decoding rows it discards",
90-
fat < lean * 4);
97+
fat < lean * 3);
9198
}
9299

93100
private double sortedPageCost(String name, int payloadSize) {
@@ -106,7 +113,7 @@ private double sortedPageCost(String name, int payloadSize) {
106113
collection.insert(document);
107114
}
108115

109-
FindOptions page = FindOptions.orderBy("seq", SortOrder.Descending).limit(20);
116+
FindOptions page = FindOptions.orderBy("seq", SortOrder.Descending).limit(1);
110117
return timeOf(() -> {
111118
for (Document ignored : collection.find(ALL, page)) {
112119
// force the fetch

0 commit comments

Comments
 (0)