{"id":47406826,"url":"https://github.com/Dingyi-Kang/PageANN","last_synced_at":"2026-07-12T13:00:48.701Z","repository":{"id":320408236,"uuid":"1058993355","full_name":"Dingyi-Kang/PageANN","owner":"Dingyi-Kang","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-03T18:24:48.000Z","size":404,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-06-03T20:10:24.594Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Dingyi-Kang.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE.txt","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-17T20:50:17.000Z","updated_at":"2026-06-03T18:24:52.000Z","dependencies_parsed_at":"2025-10-23T17:34:26.990Z","dependency_job_id":"9691a17d-682d-4828-942b-45a75f36be57","html_url":"https://github.com/Dingyi-Kang/PageANN","commit_stats":null,"previous_names":["dingyi-kang/pageann"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Dingyi-Kang/PageANN","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dingyi-Kang%2FPageANN","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dingyi-Kang%2FPageANN/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dingyi-Kang%2FPageANN/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dingyi-Kang%2FPageANN/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dingyi-Kang","download_url":"https://codeload.github.com/Dingyi-Kang/PageANN/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dingyi-Kang%2FPageANN/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35392296,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-12T02:00:06.386Z","response_time":87,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-20T19:00:20.226Z","updated_at":"2026-07-12T13:00:48.694Z","avatar_url":"https://github.com/Dingyi-Kang.png","language":"C++","funding_links":[],"categories":["Sdks \u0026 Libraries"],"sub_categories":[],"readme":"# PageANN \u0026 LAANN\n\nTwo disk-based approximate nearest neighbor search systems built for high-throughput vector search on SSDs.\n\n## About\n\n### PageANN ([paper](https://arxiv.org/abs/2509.25487))\n\n**PageANN** targets two tightly coupled root causes of scalability bottlenecks in disk-based ANNS:\n\n1. **Granularity mismatch**: prior systems traverse the graph vector-by-vector, but SSD I/O is page-granular. Each page read fetches data for many vectors, yet only the target vector's data is used — resulting in as low as 10% page utilization for DiskANN and PipeANN.\n2. **Memory overhead from compressed vectors**: to avoid reading compressed neighbor values from disk during distance estimation, prior systems keep all PQ-compressed vectors in memory. This overhead scales with dataset size and becomes the binding constraint under tight memory budgets.\n\nPageANN addresses both through a **page-node graph**: nearby vectors are grouped into 4 KB pages, and all cross-page Vamana edges from every vector in the page are merged and deduplicated into a single page-level neighbor list. Search traverses page nodes rather than individual vectors — one I/O delivers one complete graph node, achieving 100% page utilization and eliminating read amplification.\n\nThis page-level design also enables storing compressed neighbor values (PQ codes) directly on disk, which prior systems could not do. The reason prior systems were blocked: vector-level traversal requires high per-vector degree, which inflates the number of compressed values per page until they no longer fit alongside the vector data and neighbor IDs. PageANN breaks this constraint in two ways: (1) page-level traversal achieves the same search quality with fewer edges per vector, since one page read explores all co-located vectors simultaneously; (2) neighbor merging eliminates duplicate compressed values for neighbors shared by multiple vectors in the same page. Together, these free enough space within each page to co-locate PQ codes for uncached neighbors inline.\n\nPageANN then applies a **budget-aware placement strategy**: compressed values for frequently-referenced neighbors are cached in memory (saving page space for each page that references them); all others are stored inline on disk and retrieved for free as part of the page read — zero extra I/O. An in-memory Vamana graph built over sampled page centroids seeds the disk search with high-quality entry points before the first I/O is issued.\n\nSee the Performance section below for benchmark results.\n\n### LAANN ([paper](https://arxiv.org/abs/2606.02784))\n\n**LAANN** extends PageANN with three complementary techniques that make graph search explicitly I/O-aware:\n\n- **Look-ahead search**: Adapts the search strategy across query phases — prioritizing in-memory neighbors in the approach phase to reduce wasted I/Os, and maximizing I/O parallelism in the convergence phase to minimize tail latency.\n- **Priority I/O–CPU pipeline**: Fills CPU idle time during I/O waits with deferred work ordered by relevance to the next I/O decision, supported by a customized candidate pool with an overflow area.\n- **Lightweight in-memory graph index**: A Vamana graph over page centroids, searched using compressed vectors, that seeds the disk graph candidate pool with high-quality candidates before the first I/O is issued.\n\n### Disk Index Format\n\nBoth systems group vectors into 4 KB pages and build a **merged page-level neighbor list** — all cross-page Vamana edges from every vector in the page are unioned and deduplicated into a single list. One I/O read delivers one complete graph node. The two systems differ in what is stored alongside those neighbor IDs on disk:\n\n**PageANN** stores PQ-compressed values for uncached neighbors inline within the page:\n\n```\n[ vectors | num_cached (u16) | num_uncached (u16) | cached IDs | uncached IDs | uncached PQ data ]\n```\n\nNeighbor IDs are split into two groups: those whose PQ codes are cached in memory (ID only on disk), and those whose PQ codes live on disk (ID + PQ data, both within the same page). Two counters at the start of the neighbor region record the size of each group. During search, uncached neighbors' PQ codes are read from the page itself — no extra I/O. The budget-aware placement strategy (described above) determines which neighbors fall into each group based on reference frequency across all pages.\n\nThis inline PQ design is only feasible because page-level traversal needs fewer edges per vector and neighbor merging removes duplicates — together freeing enough page space for the PQ data. Prior vector-level systems such as DiskANN cannot store PQ codes on disk: with per-vector degrees of 23–31, the combined PQ data for all a vector's neighbors exceeds the remaining page space after storing the vector and neighbor IDs.\n\n**LAANN** stores only neighbor IDs — no PQ data on disk:\n\n```\n[ vectors | num_neighbors (u32) | neighbor IDs ]\n```\n\nPQ lookups always go through the separately loaded in-memory compressed vector file. Dropping inline PQ entirely frees the spare page space for more neighbor IDs, removing the coupling between memory budget and page capacity.\n\nBecause the binary sector layout differs, PageANN and LAANN produce separate index files and cannot share a disk index.\n\n---\n\n### Key Differences from Prior Disk-Based ANNS Systems\n\n| Property | DiskANN | Starling / MARGO | PipeANN | PageANN | **LAANN** |\n|---|---|---|---|---|---|\n| Page-aligned disk graph | | | | ✓ | ✓ |\n| Cached graph nodes support | ✓ | ✓ | | ✓ | ✓ |\n| Phase-aware search strategy | | | ✓ | | ✓ |\n| Relevance-ordered CPU pipeline | | | | | ✓ |\n| In-memory graph (full-precision dist.) | | ✓ | ✓ | ✓ | |\n| Lightweight in-memory graph (approx. dist.) | | | | | ✓ |\n\n### Performance\n\n#### PageANN vs. SOTA Disk-Based ANNS\n\nEvaluated against DiskANN, Starling, MARGO, PipeANN, and SPANN across five datasets (up to 1B vectors) and memory budgets ranging from near-zero (0.004%) to 40% of dataset size:\n\n| Metric | Peak | Average |\n|---|---|---|\n| Throughput improvement | 5.4× | 1.94× |\n| Latency reduction | 83% | 66.8% |\n\nResults hold at equal recall without sacrificing accuracy.\n\n#### LAANN vs. PageANN and DiskANN\n\nAt Recall@10 = 0.9 on 100M-scale datasets (memory budget = 0.5× dataset size, T=16 threads):\n\n| Dataset | vs. PageANN (QPS) | vs. DiskANN (QPS) | I/O reduction vs. PageANN |\n|---|---|---|---|\n| SIFT100M | 1.41× | 3.47× | 37% fewer |\n| SPACEV100M | 2.12× | 4.66× | 58% fewer |\n| DEEP100M | 1.96× | 3.36× | 58% fewer |\n\nOn billion-scale datasets the advantage widens further due to longer search paths and higher I/O contention.\n\n## Quick Demo: SIFT1M\n\nTry either system on the SIFT1M benchmark (1M × 128-dim float vectors).\n\n**Download the dataset** (see [sift1M/README.md](sift1M/README.md)):\n```bash\ncd sift1M\nwget https://huggingface.co/datasets/qbo-odp/sift1m/resolve/main/sift_base.fvecs\nwget https://huggingface.co/datasets/qbo-odp/sift1m/resolve/main/sift_query.fvecs\nwget https://huggingface.co/datasets/qbo-odp/sift1m/resolve/main/sift_groundtruth.ivecs\n```\n\n### PageANN Demo\n\n**Build** — data conversion, Vamana graph, PageANN page graph, and nav graph:\n```bash\nbash sift1M/build_pageann_sift1m.sh\n```\n\n**Search** — sweeps multiple L values to produce a recall–latency curve:\n```bash\nbash sift1M/search_pageann_sift1m.sh\n```\n\nSee **[sift1M/build_pageann_sift1m.sh](sift1M/build_pageann_sift1m.sh)** and **[sift1M/search_pageann_sift1m.sh](sift1M/search_pageann_sift1m.sh)** for full parameter details.\n\n### LAANN Demo\n\n**Build** — data conversion, Vamana graph, LAANN page graph, nav graph, and page reordering:\n```bash\nbash sift1M/build_laann_sift1m.sh\n```\n\n**Search** — sweeps multiple L values to produce a recall–latency curve:\n```bash\nbash sift1M/search_laann_sift1m.sh\n```\n\nSee **[sift1M/build_laann_sift1m.sh](sift1M/build_laann_sift1m.sh)** and **[sift1M/search_laann_sift1m.sh](sift1M/search_laann_sift1m.sh)** for full parameter details.\n\n## Papers\n\nIf you use this code, please cite the relevant paper(s):\n\n**PageANN:**\n```bibtex\n@article{kang2025scalable,\n  title={Scalable Disk-Based Approximate Nearest Neighbor Search with Page-Aligned Graph},\n  author={Kang, Dingyi and Jiang, Dongming and Yang, Hanshen and Liu, Hang and Li, Bingzhe},\n  journal={arXiv preprint arXiv:2509.25487},\n  year={2025}\n}\n```\n\n**LAANN:**\n```bibtex\n@article{kang2026laann,\n  title={LAANN: I/O-Aware Look-Ahead Search for Disk-Based Approximate Nearest Neighbor Search},\n  author={Kang, Dingyi and Yang, Juncheng and Li, Bingzhe},\n  journal={arXiv preprint arXiv:2606.02784},\n  year={2026}\n}\n```\n\n## Credits\n\nBoth PageANN and LAANN are built on top of Microsoft Research's DiskANN:\n- DiskANN repository: https://github.com/microsoft/DiskANN\n- Original DiskANN paper: Subramanya et al., \"DiskANN: Fast Accurate Billion-point Nearest Neighbor Search on a Single Node\", NeurIPS 2019\n\n**Original DiskANN**: Copyright (c) Microsoft Corporation  \n**PageANN / LAANN modifications**: Copyright (c) 2025 Dingyi Kang\n\n## Authors\n\n**PageANN** ([arXiv:2509.25487](https://arxiv.org/abs/2509.25487)):  \nDingyi Kang, Dongming Jiang, Hanshen Yang, Hang Liu, Bingzhe Li — University of Texas at Dallas\n\n**LAANN** ([arXiv:2606.02784](https://arxiv.org/abs/2606.02784)):  \nDingyi Kang, Juncheng Yang (Harvard University), Bingzhe Li — University of Texas at Dallas\n\nContact: dingyikangosu@gmail.com\n\n## License\n\nMIT License — see [LICENSE](LICENSE) file for details.\n\nThis project contains:\n- DiskANN components: Copyright (c) Microsoft Corporation\n- PageANN / LAANN modifications: Copyright (c) 2025 Dingyi Kang\n\n## Building\n\n### Prerequisites\n\n**Linux (Ubuntu 20.04+)**:\n```bash\nsudo apt install make cmake g++ libaio-dev libgoogle-perftools-dev clang-format libboost-all-dev\nsudo apt install libmkl-full-dev\n```\n\n**Earlier Ubuntu versions**: Install Intel MKL manually from the [oneAPI MKL installer](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html).\n\n### Build Instructions\n\n```bash\nmkdir build \u0026\u0026 cd build\ncmake -DCMAKE_BUILD_TYPE=Release ..\nmake -j\n```\n\n## Usage\n\n### PageANN\n\n- **[PageANN Usage Guide](workflows/PageANN_usage.md)**: Complete workflow for building and searching PageANN indexes\n- **[PageANN Paper Experiment Parameters](workflows/PageANN_paper_params.md)**: Exact parameters to reproduce PageANN paper results\n\n### LAANN\n\n- **[LAANN Usage Guide](workflows/LAANN_usage.md)**: Complete workflow for building and searching LAANN indexes\n- **[LAANN Paper Experiment Parameters](workflows/LAANN_paper_params.md)**: Exact parameters to reproduce LAANN paper results\n\n## Key Tools\n\n### Main Applications\n\n- `build_vamana_disk_index`: Build Vamana vector-level disk index (first step)\n- `generate_laann_graph`: Convert Vamana index to LAANN page-graph format with nav-graph construction\n- `generate_page_graph`: Convert Vamana index to PageANN page-graph format (baseline)\n- `recommend_vamana_graph_degree`: Recommend optimal graph degree parameters for a given memory budget\n- `search_disk_index`: Search the LAANN or PageANN index\n\n### Utility Tools\n\n- `build_pageann_nav_graph`: Build the in-memory navigation graph for PageANN\n- `build_laann_nav_graph`: Build the lightweight in-memory navigation graph for LAANN\n- `compute_groundtruth`: Compute ground truth nearest neighbors for recall evaluation\n- `generate_reorder_pq`: Regenerate PQ codes with different compression levels\n- `reorder_pages_by_frequency`: Reorder disk pages by access frequency for faster cache warm-up\n\n## Contributing\n\nContributions are welcome. Please feel free to submit issues or pull requests.\n\n## Acknowledgments\n\nSpecial thanks to Microsoft Research for open-sourcing DiskANN, which forms the foundation of this work.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDingyi-Kang%2FPageANN","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDingyi-Kang%2FPageANN","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDingyi-Kang%2FPageANN/lists"}