Revert to v2 format, fix CHD with more displacement tries

Spare slots (1.23x) doubled binary size → reverted to v2 (no spare
slots, entry_count == slot_count). CHD now uses entry_count/4
buckets and 1M displacement tries instead of 65K. No trimming.
This commit is contained in:
afiqzudinhadi 2026-07-02 15:47:23 +08:00
parent ab0e90b84b
commit 1d5bef3129
3 changed files with 36 additions and 45 deletions

View file

@ -158,15 +158,15 @@ int dict_mphf_init(struct dict_mphf *dict, const void *data, size_t len)
dict->disp_section_len = align4((disp_bits_total + 7) / 8);
offset += dict->disp_section_len;
/* Values (slot_count slots, not entry_count) */
/* Values */
dict->values = base + offset;
uint32_t val_bits_total = (uint32_t)hdr->slot_count * hdr->value_bits;
uint32_t val_bits_total = (uint32_t)hdr->entry_count * hdr->value_bits;
dict->val_section_len = align4((val_bits_total + 7) / 8);
offset += dict->val_section_len;
/* Fingerprints (one per slot) */
/* Fingerprints */
dict->fingerprints = base + offset;
dict->fp_section_len = align4(hdr->slot_count);
dict->fp_section_len = align4(hdr->entry_count);
offset += dict->fp_section_len;
/* String offsets (u24 LE, 3 bytes each) */
@ -285,7 +285,7 @@ const char *dict_mphf_lookup(const struct dict_mphf *dict,
uint32_t d = read_bits(dict->displacements,
bucket * (uint32_t)hdr->disp_bits,
hdr->disp_bits);
uint32_t slot = hash_key(key_buf, key_len, d + 1) % hdr->slot_count;
uint32_t slot = hash_key(key_buf, key_len, d + 1) % hdr->entry_count;
uint8_t expected_fp = (uint8_t)(fnv1a_32(key_buf, key_len) & 0xFF);
if (dict->fingerprints[slot] != expected_fp) {

View file

@ -1,9 +1,8 @@
/**
* MPHF (Minimal Perfect Hash Function) dictionary lookup engine.
*
* Binary format v3: CHD MPHF with spare slots + bit-packed
* displacements/values + fingerprinted verification +
* block-compressed string table.
* Binary format v2: CHD MPHF + bit-packed displacements/values +
* fingerprinted verification + block-compressed string table.
*
* SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
*/
@ -16,7 +15,7 @@
#include <stddef.h>
#define DICT_MPHF_MAGIC 0x4F4E5453 /* "STNO" */
#define DICT_MPHF_VERSION 3
#define DICT_MPHF_VERSION 2
#define DICT_MPHF_FLAG_COMPRESSED 0x0001
@ -24,14 +23,14 @@ struct dict_mphf_header {
uint32_t magic;
uint16_t version;
uint16_t flags;
uint32_t slot_count;
uint32_t entry_count;
uint32_t bucket_count;
uint32_t unique_count;
uint8_t value_bits;
uint8_t disp_bits;
uint16_t prefix_count;
uint32_t block_size;
uint32_t entry_count;
uint32_t reserved1;
} __attribute__((packed));
_Static_assert(sizeof(struct dict_mphf_header) == 32, "header must be 32 bytes");
@ -42,16 +41,16 @@ struct dict_mphf {
const uint8_t *values;
const uint8_t *fingerprints;
const uint8_t *string_offsets;
const uint8_t *str_data_start; /* start of string data section */
const uint8_t *str_data_start;
const uint32_t *prefix_table;
uint32_t disp_section_len;
uint32_t val_section_len;
uint32_t fp_section_len;
uint16_t block_count;
const uint32_t *block_dir; /* block offset directory */
const uint8_t *blocks_start; /* start of compressed blocks */
uint32_t str_data_len; /* total string data section length */
uint32_t blk_size; /* actual block size from header */
const uint32_t *block_dir;
const uint8_t *blocks_start;
uint32_t str_data_len;
uint32_t blk_size;
};
int dict_mphf_init(struct dict_mphf *dict, const void *data, size_t len);
@ -66,9 +65,4 @@ static inline uint32_t dict_mphf_count(const struct dict_mphf *dict)
return dict->header->entry_count;
}
static inline uint32_t dict_mphf_slot_count(const struct dict_mphf *dict)
{
return dict->header->slot_count;
}
#endif /* DICT_MPHF_H */