git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 00/12] reftable: improve ref iteration performance (pt.2)

From
Patrick Steinhardt <ps@pks.im>
Date
Feb 14, 2024, 07:45 UTC
Message-ID
<cover.1707895758.git.ps@pks.im>
Hi,

this is the second part of my patch series that aim to improve raw ref iteration performance with the reftable backend. The target of this series was to get the reftable backend performant enough to match the files backend. This was achieved via two angles:

  - Refactorings of the merged iterators that allow us to skip copying
    and allocating records from the sub-iterators to the caller. This is
    implemented by the first 8 patches.
  - Refactorings of how we decode reftable records so that we reuse
    allocated memory. Like this the number of allocations don't scale
    with the number of iterated records anymore, but instead with the
    number of blocks which we're iterating over.

Combined, these refactorings lead to a sizeable speedup when iterating over 1 million refs:

```
Benchmark 1: show-ref: single matching ref (revision = HEAD~)
  Time (mean ± σ):     146.1 ms ±   4.2 ms    [User: 143.2 ms, System: 2.8 ms]
  Range (min … max):   140.7 ms … 180.2 ms    1000 runs
Benchmark 2: show-ref: single matching ref (revision = HEAD)
  Time (mean ± σ):      97.6 ms ±   3.2 ms    [User: 94.8 ms, System: 2.7 ms]
  Range (min … max):    94.6 ms … 122.1 ms    1000 runs
Summary
  show-ref: single matching ref (revision = HEAD) ran
    1.50 ± 0.07 times faster than show-ref: single matching ref (revision = HEAD~)
```
With this, the reftable backend is now on par with the files backend:
```
Benchmark 1: show-ref: single matching ref (refformat = files)
  Time (mean ± σ):      97.8 ms ±   3.4 ms    [User: 87.6 ms, System: 10.0 ms]
  Range (min … max):    95.0 ms … 121.3 ms    1000 runs
Benchmark 2: show-ref: single matching ref (refformat = reftable)
  Time (mean ± σ):      97.4 ms ±   3.2 ms    [User: 94.5 ms, System: 2.7 ms]
  Range (min … max):    94.1 ms … 126.3 ms    1000 runs
Summary
  show-ref: single matching ref (refformat = reftable) ran
    1.00 ± 0.05 times faster than show-ref: single matching ref (refformat = files)
```

There are still optimization opportunities left, but given that the original target has been fulfilled I decided to stop so that the patch series remains somewhat reasonably sized.

The patch series is based on `master` at 2996f11c1d (Sync with 'maint', 2024-02-12) and depends on ps/reftable-iteration-perf at c68ca7abd3 (reftable/reader: add comments to `table_iter_next()`, 2024-02-12).

Patrick
Patrick Steinhardt (12):
  reftable/pq: use `size_t` to track iterator index
  reftable/merged: make `merged_iter` structure private
  reftable/merged: advance subiter on subsequent iteration
  reftable/merged: make subiters own their records
  reftable/merged: remove unnecessary null check for subiters
  reftable/merged: handle subiter cleanup on close only
  reftable/merged: circumvent pqueue with single subiter
  reftable/merged: avoid duplicate pqueue emptiness check
  reftable/record: reuse refname when decoding
  reftable/record: reuse refname when copying
  reftable/record: decode keys in place
  reftable: allow inlining of a few functions
 reftable/block.c           |  25 +++----
 reftable/block.h           |   2 -
 reftable/iter.c            |   5 --
 reftable/iter.h            |   4 --
 reftable/merged.c          | 139 +++++++++++++++++++------------------
 reftable/merged.h          |   9 ---
 reftable/pq.c              |  18 +----
 reftable/pq.h              |  16 +++--
 reftable/pq_test.c         |  41 +++++------
 reftable/record.c          |  64 +++++++++--------
 reftable/record.h          |  21 ++++--
 reftable/record_test.c     |   3 +-
 reftable/reftable-record.h |   1 +
 13 files changed, 170 insertions(+), 178 deletions(-)
base-commit: 2996f11c1d11ab68823f0939b6469dedc2b9ab90
-- 
2.43.GIT
Next: Patrick Steinhardt
Message 1 of 51 in “reftable: improve ref iteration performance (pt.2)”
  1. 00/12 reftable: improve ref iteration performance (pt.2)Patrick Steinhardt, Feb 14, 2024
  2. 01/12 reftable/pq: use `size_t` to track iterator indexPatrick Steinhardt, Feb 14, 2024
  3. 02/12 reftable/merged: make `merged_iter` structure privatePatrick Steinhardt, Feb 14, 2024
  4. Justin ToblerFeb 20, 2024
  5. Patrick SteinhardtFeb 27, 2024
  6. 03/12 reftable/merged: advance subiter on subsequent iterationPatrick Steinhardt, Feb 14, 2024
  7. Justin ToblerFeb 20, 2024
  8. Patrick SteinhardtFeb 27, 2024
  9. 04/12 reftable/merged: make subiters own their recordsPatrick Steinhardt, Feb 14, 2024
  10. 05/12 reftable/merged: remove unnecessary null check for subitersPatrick Steinhardt, Feb 14, 2024
  11. 06/12 reftable/merged: handle subiter cleanup on close onlyPatrick Steinhardt, Feb 14, 2024
  12. 07/12 reftable/merged: circumvent pqueue with single subiterPatrick Steinhardt, Feb 14, 2024
  13. 08/12 reftable/merged: avoid duplicate pqueue emptiness checkPatrick Steinhardt, Feb 14, 2024
  14. James LiuFeb 27, 2024
  15. 09/12 reftable/record: reuse refname when decodingPatrick Steinhardt, Feb 14, 2024
  16. James LiuFeb 28, 2024
  17. Patrick SteinhardtMar 4, 2024
  18. 10/12 reftable/record: reuse refname when copyingPatrick Steinhardt, Feb 14, 2024
  19. James LiuFeb 28, 2024
  20. 11/12 reftable/record: decode keys in placePatrick Steinhardt, Feb 14, 2024
  21. James LiuFeb 28, 2024
  22. Patrick SteinhardtMar 4, 2024
  23. 12/12 reftable: allow inlining of a few functionsPatrick Steinhardt, Feb 14, 2024
  24. 00/13 reftable: improve ref iteration performance (pt.2)Patrick Steinhardt, Feb 27, 2024
  25. 01/13 reftable/pq: use `size_t` to track iterator indexPatrick Steinhardt, Feb 27, 2024
  26. 02/13 reftable/merged: make `merged_iter` structure privatePatrick Steinhardt, Feb 27, 2024
  27. 03/13 reftable/merged: advance subiter on subsequent iterationPatrick Steinhardt, Feb 27, 2024
  28. 04/13 reftable/merged: make subiters own their recordsPatrick Steinhardt, Feb 27, 2024
  29. 05/13 reftable/merged: remove unnecessary null check for subitersPatrick Steinhardt, Feb 27, 2024
  30. 06/13 reftable/merged: handle subiter cleanup on close onlyPatrick Steinhardt, Feb 27, 2024
  31. 07/13 reftable/merged: circumvent pqueue with single subiterPatrick Steinhardt, Feb 27, 2024
  32. 08/13 reftable/merged: avoid duplicate pqueue emptiness checkPatrick Steinhardt, Feb 27, 2024
  33. 09/13 reftable/record: reuse refname when decodingPatrick Steinhardt, Feb 27, 2024
  34. 10/13 reftable/record: reuse refname when copyingPatrick Steinhardt, Feb 27, 2024
  35. 11/13 reftable/record: decode keys in placePatrick Steinhardt, Feb 27, 2024
  36. 12/13 reftable: allow inlining of a few functionsPatrick Steinhardt, Feb 27, 2024
  37. 13/13 refs/reftable: precompute prefix lengthPatrick Steinhardt, Feb 27, 2024
  38. 00/13 reftable: improve ref iteration performance (pt.2)Patrick Steinhardt, Mar 4, 2024
  39. 01/13 reftable/pq: use `size_t` to track iterator indexPatrick Steinhardt, Mar 4, 2024
  40. 02/13 reftable/merged: make `merged_iter` structure privatePatrick Steinhardt, Mar 4, 2024
  41. 03/13 reftable/merged: advance subiter on subsequent iterationPatrick Steinhardt, Mar 4, 2024
  42. 04/13 reftable/merged: make subiters own their recordsPatrick Steinhardt, Mar 4, 2024
  43. 05/13 reftable/merged: remove unnecessary null check for subitersPatrick Steinhardt, Mar 4, 2024
  44. 06/13 reftable/merged: handle subiter cleanup on close onlyPatrick Steinhardt, Mar 4, 2024
  45. 07/13 reftable/merged: circumvent pqueue with single subiterPatrick Steinhardt, Mar 4, 2024
  46. 08/13 reftable/merged: avoid duplicate pqueue emptiness checkPatrick Steinhardt, Mar 4, 2024
  47. 09/13 reftable/record: reuse refname when decodingPatrick Steinhardt, Mar 4, 2024
  48. 10/13 reftable/record: reuse refname when copyingPatrick Steinhardt, Mar 4, 2024
  49. 11/13 reftable/record: decode keys in placePatrick Steinhardt, Mar 4, 2024
  50. 12/13 reftable: allow inlining of a few functionsPatrick Steinhardt, Mar 4, 2024
  51. 13/13 refs/reftable: precompute prefix lengthPatrick Steinhardt, Mar 4, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.