Skip to content

Conversation

@illustriousness
Copy link
Contributor

  • 为 KV 头与 struct fdb_kv 补充 name_crc(name CRC32 低 16 位),创建时写入,读取时带出。
  • find_kv 的遍历改为先读头部长度+name_crc,匹配才继续读 name/value 并比对字符串,不匹配直接跳过,减少无缓存扫描Flash 读。
  • kv_iterator 支持可选 search_ctx,兼容未匹配时提前返回;缓存命中/打印/GC 等路径传 NULL 保持旧行为。
  • 补充 <stdint.h> 头,确保类型声明完整。
  • 对旧数据兼容:当头部 name_crc 为擦除态 0xFFFF 时仍继续匹配逻辑。

@illustriousness
Copy link
Contributor Author

#368

@armink
Copy link
Owner

armink commented Nov 26, 2025

请问这部分优化有做一些对比测试吗?方不方便给出一个优化前后的具体数据呢?

@illustriousness
Copy link
Contributor Author

配置文件

/*
 * Copyright (c) 2020, Armink, <armink.ztl@gmail.com>
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @file
 * @brief configuration file
 */

#ifndef _FDB_CFG_H_
#define _FDB_CFG_H_

#define FDB_WRITE_GRAN 1
extern int rt_kprintf(const char *fmt, ...);
/* using KVDB feature */
#define FDB_USING_KVDB

#ifdef FDB_USING_KVDB
/* Auto update KV to latest default when current KVDB version number is changed. @see fdb_kvdb.ver_num */
/* #define FDB_KV_AUTO_UPDATE */
#define FDB_KV_CACHE_TABLE_SIZE 0
#define FDB_SECTOR_CACHE_TABLE_SIZE 0
#endif

/* using TSDB (Time series database) feature */
// #define FDB_USING_TSDB

#define FDB_USING_FAL_MODE
/* Using file storage mode by POSIX file API, like open/read/write/close */
#define FDB_USING_FILE_POSIX_MODE
/* log print macro. default EF_PRINT macro is printf() */
#define FDB_PRINT(...)              rt_kprintf(__VA_ARGS__)

/* print debug information */
// #define FDB_DEBUG_ENABLE

#endif /* _FDB_CFG_H_ */

测试用例

  • 随机写入20个kv 随机大小(max 500) 写入1000次
#define STRESS_TOTAL_OPS               1000
#define STRESS_MAX_KV                  20
#define STRESS_MAX_VALUE_LEN           500

static size_t kv_count(fdb_kvdb_t db)
{
    struct fdb_kv_iterator iterator;
    size_t count = 0;

    fdb_kv_iterator_init(db, &iterator);
    while (fdb_kv_iterate(db, &iterator) == RT_TRUE)
    {
        if (iterator.curr_kv.status == FDB_KV_WRITE && iterator.curr_kv.crc_is_ok)
        {
            count++;
        }
    }

    return count;
}

static void test_fdb_kvdb_count_stress(void)
{
    fdb_kv_set_default(&test_kvdb);

    bool seen[STRESS_MAX_KV] = { 0 };
    size_t unique_cnt = 0;
    char name[16];
    struct fdb_blob blob;
    uint8_t *value_buf = (uint8_t *)rt_malloc(STRESS_MAX_VALUE_LEN);

    uassert_not_null(value_buf);

    srand(rt_tick_get());

    for (int i = 0; i < STRESS_TOTAL_OPS; i++)
    {
        int idx = rand() % STRESS_MAX_KV;
        size_t val_len = (rand() % STRESS_MAX_VALUE_LEN) + 1;

        rt_snprintf(name, sizeof(name), "stress_kv_%02d", idx);
        memset(value_buf, (uint8_t)(idx + i), val_len);
        // rt_kprintf("name:%s len %d\n", name, val_len);
        uassert_true(fdb_kv_set_blob(&test_kvdb, name, fdb_blob_make(&blob, value_buf, val_len)) == FDB_NO_ERR);

        if (!seen[idx])
        {
            seen[idx] = true;
            unique_cnt++;
        }

        if ((i + 1) % 10 == 0)
        {
            uassert_int_equal((int)unique_cnt, (int)kv_count(&test_kvdb));
        }
    }

    rt_free(value_buf);
}

时间对比

  • kv_hdr中加入name_crc 当查询的key匹配才去读取kv信息时 花费用时如下
3f59ed6064372bb16e5eb44be1d647c9
  • 原逻辑花费用时如下
a2e6beaa0d60d1c7605a1fd61b038cd4

@illustriousness
Copy link
Contributor Author

另外原本的工作流测试不完全 只测试了写入粒度为1的情况 而非遍历所有可能取值

@armink
Copy link
Owner

armink commented Dec 1, 2025

看着 感觉提升不太大呢

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.

2 participants