plugin-system

NVE 插件系统

一、总体架构

NVE 的插件系统是一套 C 符号约定 + 抽象工厂 + 动态加载 的架构,用于提供多种宿主表(HostTable)存储后端。整体分三层:

        ┌──────────────────────────────────┐
        │      build_host_database()       │  ← 顶层编排函数
        └────┬─────────────┬───────────────┘
             │             │
┌────────────▼──┐   ┌──────▼──────────────┐
│  load_plugin()│   │  resolve_factory()   │
│  dlopen .so   │   │  htf_impls[] map     │
└────┬──────────┘   └──────┬──────────────┘
     │                      │
┌────▼──────────────────────▼──────────────────┐
│         静态注册的内置实现                     │
│   "stl_map" / "map" / "umap" / "unordered_map"│
│   → STLMapTableFactory                        │
└───────────────────────────────────────────────┘

二、插件接口定义

插件 API 是一组 C 链接函数指针类型定义,而非 C++ 虚基类:

namespace nve {

using plugin_info_t = const char* (*)();                                          // 插件元信息
using enum_implementations_t = void (*)(void*, void (*)(void*, const char*));    // 枚举实现
using create_host_table_factory_t = host_table_factory_ptr_t (*)(const nlohmann::json&);  // 工厂创建

}  // namespace nve

每个插件 .so 必须导出以下 3 个 C 链接函数:

导出的 C 符号 签名 作用
plugin_ident() extern "C" const char*() 返回插件人类可读名称
plugin_developer() extern "C" const char*() 返回开发者名称
enum_host_table_implementations() extern "C" void(void*, void(*)(void*,const char*)) 遍历注册插件内所有实现
create_{name}_table_factory() extern "C" host_table_factory_ptr_t(const nlohmann::json&) 每个实现一个,创建工厂对象

这不是 C++ 虚基类,而是纯 C 符号约定——任何遵守这个符号约定的 .so 都可以被 dlopen + dlsym 动态加载。


三、运行时加载机制

加载流程在 src/host_table.cpp 中实现,共 4 步:

Step 1 — dlopen 加载 .so

void load_host_table_plugin(const std::string_view& plugin_name) {
    void* dll = dlopen(plugin_path.c_str(), RTLD_NOW | RTLD_GLOBAL);
    // 如果给定路径失败,回退到相对于当前 .so 的路径
}

Step 2 — dlsym 解析 3 个必需符号

plugin_info_t plugin_ident = dlsym(dll, "plugin_ident");
plugin_info_t plugin_dev   = dlsym(dll, "plugin_developer");
enum_implementations_t enum_ht = dlsym(dll, "enum_host_table_implementations");

Step 3 — 枚举注册实现

enum_ht(dll, register_implementation);

register_implementation 回调函数构造 "create_{name}_table_factory" 字符串,再次 dlsym 解析工厂构造函数,存入全局 std::unordered_map<string, create_host_table_factory_t>

static std::unordered_map<std::string, create_host_table_factory_t> htf_impls;

Step 4 — 按 JSON 配置生产表

host_table_factory_ptr_t create_host_table_factory(const nlohmann::json& json);
host_table_ptr_t factory->produce(table_id_t id, const nlohmann::json& config);

四、类继承体系

┌──────────────────────────────────────────────────────────────┐
│                       nve::Table (abstract)                   │
│  virtual clear() / erase() / find() / insert() / update()    │
└──────────────────────────────────────────────────────────────┘
                           ▲
        ┌──────────────────┴──────────────────┐
        │                                     │
┌───────┴─────────────────────────┐  ┌────────┴────────────────┐
│   nve::HostTableLike             │  │   GPU 端表 (抽象)       │
│  + size() / config() 等          │  │   (gpu_table.hpp)       │
└──────────────────────────────────┘  └─────────────────────────┘
        ▲
┌───────┴─────────────────────────┐
│   nve::HostTable<ConfigType>     │  ← CRTP 基类,存储 config
└──────────────────────────────────┘
        ▲
        ├───────────────────────────────────┬───────────────────┐
        │                                   │                   │
┌───────┴──────────┐  ┌─────────────────────┴──┐  ┌─────────────┴──────────┐
│ STLContainerTable│  │ NvhmMapTable            │  │ RedisClusterTable      │
│ (umap / map)     │  │ (GPU nvhashmap 后端)     │  │ (远程 Redis 集群)      │
└──────────────────┘  └────────────────────────┘  └────────────────────────┘
        ▲                        ▲
    AbseilFlatMapTable           │
    PHMapFlatMapTable            │
    (继承 STLContainerTable)     │
                                 │
                        ┌────────┴──────────┐
                        │ RocksDBTable       │
                        │ (磁盘 LSM-Tree)    │
                        └───────────────────┘

关键区别:NVHM 插件直接继承 HostTable<NvhmMapTableConfig>,不走 STL 层。Abseil 和 PHMAP 继承 STLContainerTable,复用其分片、超额淘汰、内存管理等基础设施。Redis 和 RocksDB 各自独立继承 HostTable,因为它们操作的是远程网络连接或本地磁盘。

工厂类层次

HostTableLikeFactory  (抽象工厂基类)
  └── HostTableFactory<FactoryConfig, TableConfig>  (模板工厂)
        ├── STLMapTableFactory        → 内置(非插件)
        ├── NvhmMapTableFactory       → NVHM 插件
        ├── AbseilFlatMapTableFactory → Abseil 插件
        ├── PHMapFlatMapTableFactory  → PHMAP 插件
        ├── RedisClusterTableFactory  → Redis 插件
        └── RocksDBTableFactory       → RocksDB 插件

五、5 个插件详解

5.1 NVHM 插件(libnve-plugin-nvhm.so

属性 内容
注册名 nvhm_map
底层库 NVIDIA nvhashmap — GPU 端开放寻址哈希表
存储位置 GPU device memory
数据持久化 ❌ 不持久

核心配置

字段 默认值 说明
num_partitions 1 独立分片数(必须为 2 的幂)
kernel_size nvhashmap 默认 内核大小 (1-1024)
key_fetch_queue_length 8 软件预取管道长度 {0,1,2,4,8}
prefetch_values true 是否发出软件预取指令
minimize_psl false 是否缩短 probe search length
auto_shrink false 大量淘汰后是否自动缩容
overflow_policy 淘汰策略(EvictRandom / EvictLRU / EvictLFU)

模板分发produce() 在多维 switch 上分发:mask_size × key_size × overflow_handler × kernel_size × minimize_psl × auto_shrink × partitioner~6144 种编译时类型组合。


5.2 Abseil 插件(libnve-plugin-abseil.so

属性 内容
注册名 abseil_flat_map
底层库 Google absl::flat_hash_map<KeyType, char*>(Swiss Table)
存储位置 CPU 端内存
数据持久化 ❌ 不持久

实现方式:继承 STLContainerTable,复用全部分片、内存槽管理、超额淘汰逻辑,底层哈希表替换为 absl::flat_hash_map

链接依赖absl_raw_logging_internal + absl_hash + absl_raw_hash_set


5.3 PHMAP 插件(libnve-plugin-phmap.so

属性 内容
注册名 phmap_flat_map
底层库 greg7mdp parallel-hashmap phmap::flat_hash_map
存储位置 CPU 端内存
数据持久化 ❌ 不持久

实现方式:与 Abseil 插件完全对称——继承 STLContainerTable,底层替换为 phmap::flat_hash_map。模板分发维度:mask_size × key_size × overflow_handler × partitioner~192 种类型组合。


5.4 Redis 插件(libnve-plugin-redis.so

属性 内容
注册名 redis_cluster
底层库 hiredis + redis++ — TCP 连接 Redis Cluster
存储位置 远程 Redis 集群
数据持久化 持久化

核心配置

字段 默认值 说明
address localhost:6379 Redis 集群任意节点地址
user_name default Redis 用户名
password Redis 用户密码
connections_per_node 5 与每个 Redis 节点的最大并行连接数
connection_lifetime 180 秒 连接生命周期
max_batch_size 16384 批量查询的最大 batch size

链接依赖hiredis + hiredis_ssl + redis++_static + ssl + crypto


5.5 RocksDB 插件(libnve-plugin-rocksdb.so

属性 内容
注册名 rocksdb
底层库 Facebook RocksDB(LSM-Tree)
存储位置 本地磁盘
数据持久化 持久化

核心配置

字段 默认值 说明
column_family default RocksDB Column Family 名称
max_batch_size 16384 批量操作的最大 batch size
verify_checksums true 是否校验 checksum
path /tmp/rocksdb 数据库文件系统路径
read_only false 只读模式(允许多客户端并发读取)
num_threads 16 RocksDB 实例可用线程数

六、内置降级实现(无插件)

即使不加载任何插件,也有 6 个别名指向同一个内置实现:

static std::unordered_map<std::string, create_host_table_factory_t> htf_impls{
    {"stl_map", create_stl_map_table_factory},
    {"map", create_stl_map_table_factory},
    {"stl_unordered_map", create_stl_map_table_factory},
    {"unordered_map", create_stl_map_table_factory},
    {"stl_umap", create_stl_map_table_factory},
    {"umap", create_stl_map_table_factory}
};

底层使用 std::unordered_map<KeyType, char*> + 手动管理的内存槽(slot buffer),带分片(shared_mutex)、inline meta(LRU/LFU 标记)、超额淘汰逻辑。


七、编译时特征控制

CMakeLists.txt 中定义:

set(NVE_AVAILABLE_FEATURES "")
list(APPEND NVE_AVAILABLE_FEATURES
  "abseil_plugin" "nvhm_plugin" "phmap_plugin"
  "redis_plugin" "rocksdb_plugin"
)
  • 默认NVE_DEFAULT_FEATURES):启用全部 5 个插件 + ht_key_32 + ht_kernel_128
  • 最小NVE_MINIMAL_FEATURES):仅 ht_mask_64 + ht_key_64 + ht_part_fnv1a + ht_kernel_64,无插件
  • 可通过 -DNVE_DISABLE_PLUGINS=1-DNVE_FEATURES="nvhm_plugin redis_plugin" 定制

每个启用的 feature 转换为 C++ 编译宏 -DNVE_FEATURE_{NAME}=1,用于模板分发的条件编译。


八、JSON 运行时配置示例

{
  "plugins": ["libnve-plugin-redis.so"],
  "table_factories": {
    "my_redis_factory": {
      "implementation": "redis_cluster",
      "address": "my-redis-cluster:6379",
      "password": "****",
      "connections_per_node": 10
    },
    "my_nvhm_factory": {
      "implementation": "nvhm_map",
      "key_size": 8,
      "mask_size": 64,
      "max_value_size": 8192,
      "value_dtype": "float32",
      "num_partitions": 4,
      "overflow_policy": {
        "handler": "EvictLRU",
        "overflow_margin": 512,
        "resolution_margin": 0.2
      }
    }
  },
  "tables": {
    "0": "my_redis_factory",
    "1": "my_nvhm_factory"
  }
}

代码调用:

auto db = nve::build_host_database(json);
auto& table0 = db.at(0);  // Redis 集群表
auto& table1 = db.at(1);  // NVHM GPU 哈希表

九、总结

维度 说明
架构风格 C 符号约定 + dlopen/dlsym 动态加载 + 抽象工厂模式
不是 C++ 虚基类插件,而是 extern “C” 符号 + dlsym 解析
5 种存储后端 GPU 端(NVHM)、CPU 端内存(Abseil/PHMAP)、远程(Redis)、持久化磁盘(RocksDB)
内置降级 std::unordered_map 实现无需任何插件即可运行
模板分发 多维 switch 分发到编译时特化模板类,最多 6144 种组合
构建/运行时解耦 编译时通过 NVE_FEATURES 选择构建内容,运行时通过 dlopen 按需加载