Skip to content

refactor(diskann): decouple from libaio via dlopen#532

Open
richyreachy wants to merge 51 commits into
alibaba:mainfrom
richyreachy:refactor/diskann_dlopen
Open

refactor(diskann): decouple from libaio via dlopen#532
richyreachy wants to merge 51 commits into
alibaba:mainfrom
richyreachy:refactor/diskann_dlopen

Conversation

@richyreachy

@richyreachy richyreachy commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Currently, DiskAnn ships as a separate runtime-loaded .so (libzvec_diskann_plugin.so) file which requires a hard build-time dependency on libaio-dev.

This PR improves with a simpler, more robust design. Probing libaio.so file, a thread-safe singleton dlopens it and caches the syscall pointers. If libaio is absent, it will fall back to degrade to synchronous pread() with a warning.

The following shows the performance comparison on Cohere 1M between pread w/ and w/o AIO enabled. (Aliyun g9i, PL0, 10000 IOPS)

Pread w/ AIO Enabled

Result FP32-100 FP32-300 FP32-500 FP16-100 FP16-300 FP16-500
Search Mem(4 thread) 503M 503M 503M 486M 486M 486M
Recall@1 96.1% 98.9% 99% 95.3% 97.8% 98.4%
Recall@10 96.14% 98.6% 98.94% 95.86% 98.1% 98.63%
Recall@50 93.394% 97.782% 98.598% 93.452% 97.354% 98.188%
QPS(1 thread) 32.6 11.2 6.7 32.3 11.1 6.7
QPS(2 thread) 65.2 22.3 13.5 64.5 22.4 13.4
QPS(4 thread) 106.4 36.6 22.1 106.4 36.6 22.1

Pread w/o AIO Enabled

Result FP32-100 FP32-300 FP32-500 FP16-100 FP16-300 FP16-500
Search Mem(4 thread) 503M 503M 503M 486M 486M 486M
Recall@1 96.1% 98.9% 99% 95.3% 97.8% 98.4%
Recall@10 96.14% 98.6% 98.94% 95.86% 98.1% 98.63%
Recall@50 93.394% 97.782% 98.598% 93.452% 97.354% 98.188%
QPS(1 thread) 18.4 6.3 3.8 18.3 6.3 3.8
QPS(2 thread) 36.8 12.6 7.5 36.5 12.6 7.6
QPS(4 thread) 73.1 25.2 15.2 72.5 25.1 15.2

@richyreachy richyreachy requested a review from egolearner June 30, 2026 08:54
@iaojnh

iaojnh commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

可以把workflow里,打包相关的libaio-devel依赖,在这个PR里移除

Comment thread python/tests/test_collection_diskann.py Outdated
Comment thread src/binding/python/exports.map Outdated
Comment thread src/include/zvec/core/interface/diskann_runtime.h Outdated
Comment thread .github/workflows/03-macos-linux-build.yml
Comment thread tools/core/bench_original.cc
Comment thread tools/core/recall_original.cc
Comment thread thirdparty/arrow/CMakeLists.txt Outdated
if: matrix.platform == 'linux-x64'
run: |
cd "$GITHUB_WORKSPACE/build"
cmake --build . --target unittest --parallel $NPROC

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

有必要全量运行吗?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated. only run diskann related tests.

@feihongxu0824 feihongxu0824 Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以多放一个非diskann的测试吧,验证安装libaio后对已有其他单测不会有影响

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

放了hnsw的测试

Comment thread .github/workflows/nightly_coverage.yml Outdated
Comment thread src/ailego/io/io_backend.h Outdated
@zhourrr

zhourrr commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

DiskANN 以及本 PR 新增的 IO backend API 在运行时绑定和 type hints 之间存在多处不一致,建议合入前一起补齐。

1. Python stubs 没有声明 DiskANN 参数

运行时已经导出了:

  • DiskAnnIndexParam
  • DiskAnnQueryParam

对应绑定位于:

  • src/binding/python/model/param/python_param.cc
  • python/zvec/model/param/__init__.py

python/zvec/model/param/__init__.pyi 中既没有这两个 class 的定义,__all__ 中也没有它们。

与此同时,顶层 python/zvec/__init__.pyi 又尝试从 .model.param 导入这两个类型。这会导致 stub 自身不完整,IDE、mypy/pyright 无法获得 DiskANN 参数提示,部分类型检查器也可能直接报告 imported symbol 不存在。

建议在 python/zvec/model/param/__init__.pyi 中补充完整声明,包括:

class DiskAnnIndexParam(IndexParam):
    metric_type: MetricType
    max_degree: int
    list_size: int
    pq_chunk_num: int
    quantize_type: QuantizeType
    quantizer_param: QuantizerParam


class DiskAnnQueryParam(QueryParam):
    list_size: int

构造函数签名和默认值需要与 pybind 保持一致:

DiskAnnIndexParam(
    metric_type=MetricType.IP,
    max_degree=100,
    list_size=50,
    pq_chunk_num=0,
    quantize_type=QuantizeType.UNDEFINED,
    quantizer_param=QuantizerParam(),
)

DiskAnnQueryParam(list_size=300)

2. IndexType.DISKANN 没有暴露到 Python

C++ 的 IndexType 已经定义了:

DISKANN = 5

src/binding/python/typing/python_type.cc 中注册 Python enum 时跳过了 DISKANN。因此即使已经有 DiskAnnIndexParam,Python 用户仍然无法使用:

IndexType.DISKANN

建议在 pybind 中增加:

.value("DISKANN", IndexType::DISKANN)

同时更新 python/zvec/typing/__init__.pyi 中的 IndexType 声明和文档。现在该 stub 里的 enum 列表本身也比较旧,像 HNSW_RABITQVAMANA 等成员似乎也没有完全同步,最好一并检查。

3. 本 PR 新增的 IO backend API 也没有进入 type hints

本 PR 新增并在运行时导出了:

  • IOBackendType
  • io_backend_type()
  • io_backend_description()
  • _Collection._debug_io_backend_type()
  • _Collection._debug_io_backend_description()

但是相关 .pyi 文件没有变化:

  • python/zvec/typing/__init__.pyi 缺少 IOBackendType
  • python/zvec/__init__.pyi 缺少顶层函数及 enum 导出
  • _Collection stub 缺少两个 debug 方法

这会造成新 API 在运行时可用,但 IDE 和静态类型检查完全不可见。建议同步更新或重新生成所有受影响的 stub,并增加一个测试,保证 Python runtime exports 与 .pyi 不再漂移。

4. DiskANN 平台检查和实际编译条件不一致

schema.cc 中的错误信息是:

DiskAnn is not supported on this platform (Linux x86_64 only)

但当前条件只检查是否为 Linux:

#if !defined(__linux__) && !defined(__linux)

这意味着 Linux ARM/aarch64 会通过 schema 校验,而 CMake 中真正支持 DiskANN 的平台范围是 Linux x86_64/i686/i386。最终可能表现为 schema 创建成功,但索引创建或算法注册阶段才失败。

建议不要在 schema 层重复维护平台判断,而是复用与 CMake/编译配置一致的 DISKANN_SUPPORTED feature macro,确保编译、注册和 schema validation 使用同一个判断来源。

建议本 PR 至少补齐

  • DiskAnnIndexParamDiskAnnQueryParam.pyi
  • Python runtime 中的 IndexType.DISKANN
  • IndexType.DISKANN 的 stub 声明
  • IOBackendType 及两个顶层 IO backend 函数的 stub
  • _Collection 新增 debug 方法的 stub
  • Linux 非 x86 平台的 DiskANN validation
  • 一条 runtime API 与 type hints 的一致性测试

其中 DiskANN 参数 stub 和 IndexType.DISKANN 的缺失可能是已有问题,但本 PR 正在调整 DiskANN 的运行时能力,并新增 Python 可见 API,我倾向于在这里一起补齐。否则用户实际使用时仍然会遇到“功能存在,但 Python SDK 不可发现或无法通过类型检查”的问题。

@richyreachy

richyreachy commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

DiskANN 以及本 PR 新增的 IO backend API 在运行时绑定和 type hints 之间存在多处不一致,建议合入前一起补齐。

1. Python stubs 没有声明 DiskANN 参数

运行时已经导出了:

  • DiskAnnIndexParam
  • DiskAnnQueryParam

对应绑定位于:

  • src/binding/python/model/param/python_param.cc
  • python/zvec/model/param/__init__.py

python/zvec/model/param/__init__.pyi 中既没有这两个 class 的定义,__all__ 中也没有它们。

与此同时,顶层 python/zvec/__init__.pyi 又尝试从 .model.param 导入这两个类型。这会导致 stub 自身不完整,IDE、mypy/pyright 无法获得 DiskANN 参数提示,部分类型检查器也可能直接报告 imported symbol 不存在。

建议在 python/zvec/model/param/__init__.pyi 中补充完整声明,包括:

class DiskAnnIndexParam(IndexParam):
    metric_type: MetricType
    max_degree: int
    list_size: int
    pq_chunk_num: int
    quantize_type: QuantizeType
    quantizer_param: QuantizerParam


class DiskAnnQueryParam(QueryParam):
    list_size: int

构造函数签名和默认值需要与 pybind 保持一致:

DiskAnnIndexParam(
    metric_type=MetricType.IP,
    max_degree=100,
    list_size=50,
    pq_chunk_num=0,
    quantize_type=QuantizeType.UNDEFINED,
    quantizer_param=QuantizerParam(),
)

DiskAnnQueryParam(list_size=300)

2. IndexType.DISKANN 没有暴露到 Python

C++ 的 IndexType 已经定义了:

DISKANN = 5

src/binding/python/typing/python_type.cc 中注册 Python enum 时跳过了 DISKANN。因此即使已经有 DiskAnnIndexParam,Python 用户仍然无法使用:

IndexType.DISKANN

建议在 pybind 中增加:

.value("DISKANN", IndexType::DISKANN)

同时更新 python/zvec/typing/__init__.pyi 中的 IndexType 声明和文档。现在该 stub 里的 enum 列表本身也比较旧,像 HNSW_RABITQVAMANA 等成员似乎也没有完全同步,最好一并检查。

3. 本 PR 新增的 IO backend API 也没有进入 type hints

本 PR 新增并在运行时导出了:

  • IOBackendType
  • io_backend_type()
  • io_backend_description()
  • _Collection._debug_io_backend_type()
  • _Collection._debug_io_backend_description()

但是相关 .pyi 文件没有变化:

  • python/zvec/typing/__init__.pyi 缺少 IOBackendType
  • python/zvec/__init__.pyi 缺少顶层函数及 enum 导出
  • _Collection stub 缺少两个 debug 方法

这会造成新 API 在运行时可用,但 IDE 和静态类型检查完全不可见。建议同步更新或重新生成所有受影响的 stub,并增加一个测试,保证 Python runtime exports 与 .pyi 不再漂移。

4. DiskANN 平台检查和实际编译条件不一致

schema.cc 中的错误信息是:

DiskAnn is not supported on this platform (Linux x86_64 only)

但当前条件只检查是否为 Linux:

#if !defined(__linux__) && !defined(__linux)

这意味着 Linux ARM/aarch64 会通过 schema 校验,而 CMake 中真正支持 DiskANN 的平台范围是 Linux x86_64/i686/i386。最终可能表现为 schema 创建成功,但索引创建或算法注册阶段才失败。

建议不要在 schema 层重复维护平台判断,而是复用与 CMake/编译配置一致的 DISKANN_SUPPORTED feature macro,确保编译、注册和 schema validation 使用同一个判断来源。

建议本 PR 至少补齐

  • DiskAnnIndexParamDiskAnnQueryParam.pyi
  • Python runtime 中的 IndexType.DISKANN
  • IndexType.DISKANN 的 stub 声明
  • IOBackendType 及两个顶层 IO backend 函数的 stub
  • _Collection 新增 debug 方法的 stub
  • Linux 非 x86 平台的 DiskANN validation
  • 一条 runtime API 与 type hints 的一致性测试

其中 DiskANN 参数 stub 和 IndexType.DISKANN 的缺失可能是已有问题,但本 PR 正在调整 DiskANN 的运行时能力,并新增 Python 可见 API,我倾向于在这里一起补齐。否则用户实际使用时仍然会遇到“功能存在,但 Python SDK 不可发现或无法通过类型检查”的问题。

fixed. add missing hints, stub, etc. and also changed the macro guard.

@@ -0,0 +1,242 @@
# Copyright 2025-present the zvec project
#
# Licensed under the Apache License, Version 2.0 (the "License");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个文件的作用是啥?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

一条 runtime API 与 type hints 的一致性测试,详情见zhourrr的comment。

iaojnh added a commit to iaojnh/zvec that referenced this pull request Jul 13, 2026
Re-express the ARM64 DiskANN enablement on top of PR alibaba#532's dlopen-based
libaio decoupling (the plugin architecture is gone, so the old
plugin/EnsureDiskAnnRuntimeReady error-message tweaks no longer apply).

- CMakeLists.txt: widen DISKANN_SUPPORTED gate to
  x86_64|i686|i386|aarch64|arm64|riscv64.
- cmake/option.cmake: _setup_armv8_march now tries "armv8-a" before the
  bare "armv8" (GCC/Clang on aarch64 reject the bare form).
- src/core/algorithm/diskann/CMakeLists.txt: widen the ${CMAKE_DL_LIBS}
  (dlopen) link gate to match the supported-platform set.
- src/db/index/common/schema.cc: update the unsupported-platform message
  to reflect the widened platform list.

libaio_def.h already provides aarch64 ABI struct layouts; libaio is loaded
at runtime via dlopen with a synchronous pread() fallback when absent.
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.#pragma once

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#pragma once 换行

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment thread src/db/index/common/schema.cc Outdated

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这个support提示过时了,现在支持DISKANN了

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done,补上了vamana

Comment thread src/binding/c/c_api.cc
// =============================================================================

zvec_io_backend_type_t zvec_get_io_backend_type(void) {
auto type = zvec::ailego::IOBackend::Instance().available();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

把switch换成static_cast ?
// C++ -> C
return static_cast<zvec_io_backend_type_t>(static_cast<uint32_t>(type));
// C -> C++
auto cpp_type = static_castzvec::IOBackendType(type);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment thread src/binding/c/c_api.cc Outdated
}

const char *zvec_get_io_backend_type_name(zvec_io_backend_type_t type) {
thread_local std::string cached;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里没有必要用cached, IOBackendTypeName返回的全是字符串字面量, 字面量是静态存储期,指针永远有效。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment thread src/binding/c/c_api.cc Outdated
}

const char *zvec_get_io_backend_description(void) {
thread_local std::string cached;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

同上,cached这里没有必要

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

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.

7 participants