FlatBuffers Schema中hash字段用途及rehash、resolver设置示例问询
Let's tackle your questions one by one, with clear explanations and a practical example:
1. What's the purpose of the 'hash' marked fields in FlatBuffers Schema?
Fields tagged with hash are designed to enable efficient key-based hash table operations using FlatBuffer objects. When you want to use a FlatBuffer table as a key in a hash map/table, these fields are used to compute the hash value for the object—instead of hashing the entire serialized buffer (which would be slower). This makes lookups, inserts, and deletes in hash structures much more efficient, as it only uses the critical fields you've marked for hashing.
2. What does the hash:"fnv1_32" setting do in a schema like table Person { age: int (hash:"fnv1_32" ); }?
This setting explicitly specifies the hashing algorithm to use for that field when computing the object's hash key. In this case, it's the 32-bit FNV-1 hash (a fast, non-cryptographic hash function).
When you generate code with flatc, the tool will auto-generate hash calculation logic that uses this algorithm on the age field's value. If multiple fields are marked with hash, the generated code will combine their hash values to create a single hash for the entire table object.
3. How to set 'rehash' and 'resolver' in the generated code?
When using --gen-object-api, FlatBuffers generates a HashTable class that supports these features. Here's a step-by-step example:
Step 1: Your Schema (Person_KeyHashTest.fbs)
table Person { age: int (hash:"fnv1_32"); name: string; } root_type Person;
Step 2: Generate C++ Code
Run your command as before:
flatc --cpp --gen-object-api Person_KeyHashTest.fbs
Step 3: Example C++ Code with Rehash & Resolver
#include "Person_KeyHashTest_generated.h" #include "flatbuffers/hash.h" #include <cstdio> #include <string> int main() { flatbuffers::FlatBufferBuilder builder; // Create two Person objects auto alice_name = builder.CreateString("Alice"); auto alice = CreatePerson(builder, 30, alice_name); builder.Finish(alice); const Person* alice_person = GetPerson(builder.GetBufferPointer()); builder.Clear(); auto bob_name = builder.CreateString("Bob"); auto bob = CreatePerson(builder, 25, bob_name); builder.Finish(bob); const Person* bob_person = GetPerson(builder.GetBufferPointer()); // Define a hash table that uses Person pointers as keys, and stores strings as values using PersonHashTable = flatbuffers::HashTable<const Person*, std::string>; // Initialize hash table: initial size = 10, load factor = 0.7 (triggers rehash when 70% full) PersonHashTable hash_table(10, 0.7f); // Set the resolver: handles hash collisions by checking if two Person objects are truly equal hash_table.SetResolver([](const Person* a, const Person* b) { // First check the hashed field (age) for quick rejection if (a->age() != b->age()) return false; // Then check other fields to confirm equality return a->name()->str() == b->name()->str(); }); // Insert entries into the hash table hash_table.Insert(alice_person, "Alice's profile data"); hash_table.Insert(bob_person, "Bob's profile data"); // Look up an entry if (auto* alice_data = hash_table.Find(alice_person)) { printf("Found data for Alice: %s\n", alice_data->c_str()); } // Optional: Manually trigger a rehash to resize the hash table to 20 slots hash_table.Rehash(20); return 0; }
Key Notes:
- Rehash: Controlled by the load factor during initialization (the second parameter to
PersonHashTable). When the number of entries exceedsinitial_size * load_factor, the hash table automatically rehashes and expands. You can also callRehash(new_size)manually to resize. - Resolver: A callback function that defines how to check if two key objects are identical. This is critical for handling hash collisions—two different objects might have the same hash value, so the resolver confirms true equality.
内容的提问来源于stack exchange,提问作者NeoLiu

