Skip to content

perf(bigquery): [T2-1] add bounded 1-page lookahead prefetching to TableResult.iterateAll() - #25

Open
lqiu96 wants to merge 1 commit into
mainfrom
perf/bq-t2-01-tableresult-page-prefetch
Open

lqiu96 wants to merge 1 commit into
mainfrom
perf/bq-t2-01-tableresult-page-prefetch

Conversation

@lqiu96

@lqiu96 lqiu96 commented Oct 13, 2026

Copy link
Copy Markdown
Owner

Summary & Bottleneck

In java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/TableResult.java, TableResult.iterateAll() delegates to getPageNoSchema().iterateAll(), which uses PageImpl.PageIterator.

  1. Synchronous page-boundary stalls:
    • PageImpl.PageIterator only calls currentPage.getNextPage() synchronously after the caller has exhausted all rows of the current page (!currentPageIterator.hasNext()).
    • While the caller processes the rows of Page $k$, no network or deserialization work occurs for Page $k+1$. When the caller reaches the end of Page $k$, iteration stalls for the full round-trip latency and deserialization time of getNextPage().

Changes

  • java-bigquery/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/TableResult.java:
    • Introduce PrefetchingPageIterator in TableResult.iterateAll() backed by a shared daemon thread pool (PREFETCH_EXECUTOR).
    • When iteration begins on a page where currentPage.hasNextPage() is true, submit currentPage.getNextPage() asynchronously so the next page is fetched and deserialized in parallel with the caller consuming the current page.
    • Bound lookahead strictly to at most 1 in-flight page per iterator, and never submit background tasks for single-page results (hasNextPage() == false) or for TableResult.getValues().
    • Preserve exact exception propagation semantics at page boundaries by unwrapping ExecutionException causes when advancing to the prefetched page.

Expected Impact

  • Overlaps the network round-trip and row deserialization latency of Page $k+1$ with application processing of Page $k$ during TableResult.iterateAll() across both REST (tabledata.list) and Storage Read API (ArrowQueryPageFetcher) pagination paths.
  • Keeps memory bounded to at most 1 lookahead page and adds zero thread overhead to single-page queries.

Verification

  • Added unit tests in java-bigquery/google-cloud-bigquery/src/test/java/com/google/cloud/bigquery/TableResultTest.java verifying asynchronous background prefetch during Page 0 iteration, 1-page lookahead bounding across a 3-page chain, and exception propagation at the page boundary.
  • Ran mvn test -pl java-bigquery/google-cloud-bigquery -Dtest=TableResultTest,ArrowQueryPageFetcherTest,JobTest,BigQueryImplTest (191 tests run, 0 failures).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant