This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 39b2c06ed fix(rust): stabilize meta string dynamic cache (#3822)
39b2c06ed is described below
commit 39b2c06ed7aab4b36fe5b50f17592a8ff02c00e9
Author: Shawn Yang <[email protected]>
AuthorDate: Tue Jul 7 22:34:11 2026 +0530
fix(rust): stabilize meta string dynamic cache (#3822)
## Why?
## What does this PR do?
## Related issues
## AI Contribution Checklist
- [ ] Substantial AI assistance was used in this PR: `yes` / `no`
- [ ] If `yes`, I included a completed [AI Contribution
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
in this PR description and the required `AI Usage Disclosure`.
- [ ] If `yes`, my PR description includes the required `ai_review`
summary and screenshot evidence or equivalent persisted links of the
final clean AI review results from both fresh reviewers described in
`AI_POLICY.md`, the Fory-guided reviewer and the independent general
reviewer, on the current PR diff or current HEAD after the latest code
changes.
## Does this PR introduce any user-facing change?
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
---
.../fory-core/src/resolver/meta_string_resolver.rs | 14 ++---
rust/tests/tests/test_meta_string_resolver.rs | 60 ++++++++++++++++++++++
2 files changed, 68 insertions(+), 6 deletions(-)
diff --git a/rust/fory-core/src/resolver/meta_string_resolver.rs
b/rust/fory-core/src/resolver/meta_string_resolver.rs
index f8593e4e4..154695909 100644
--- a/rust/fory-core/src/resolver/meta_string_resolver.rs
+++ b/rust/fory-core/src/resolver/meta_string_resolver.rs
@@ -185,8 +185,10 @@ impl MetaStringWriterResolver {
pub struct MetaStringReaderResolver {
meta_string_bytes_to_string: HashMap<*const MetaStringBytes, MetaString>,
- hash_to_meta_string_bytes: HashMap<i64, MetaStringBytes>,
- long_long_byte_map: HashMap<(u64, u64, u8), MetaStringBytes>,
+ // `dynamic_read` stores raw pointers into these values. Keep the bytes
behind
+ // a stable heap owner so HashMap rehashes cannot move the pointee.
+ hash_to_meta_string_bytes: HashMap<i64, Box<MetaStringBytes>>,
+ long_long_byte_map: HashMap<(u64, u64, u8), Box<MetaStringBytes>>,
dynamic_read: Vec<Option<*const MetaStringBytes>>,
dynamic_read_id: usize,
}
@@ -270,12 +272,12 @@ impl MetaStringReaderResolver {
let mb_ref: &mut MetaStringBytes = match
self.hash_to_meta_string_bytes.entry(hash_code) {
Entry::Occupied(entry) => {
reader.skip(len)?;
- entry.into_mut()
+ entry.into_mut().as_mut()
}
Entry::Vacant(entry) => {
let bytes = reader.read_bytes(len)?.to_vec();
let mb = MetaStringBytes::new(bytes, hash_code)?;
- entry.insert(mb)
+ entry.insert(Box::new(mb)).as_mut()
}
};
@@ -318,7 +320,7 @@ impl MetaStringReaderResolver {
let key = (v1, v2, encoding_val);
let mb_ref = match self.long_long_byte_map.entry(key) {
- Entry::Occupied(entry) => entry.into_mut(),
+ Entry::Occupied(entry) => entry.into_mut().as_mut(),
Entry::Vacant(entry) => {
let mut data = vec![0u8; 16];
data[0..8].copy_from_slice(&v1.to_le_bytes());
@@ -329,7 +331,7 @@ impl MetaStringReaderResolver {
let hash_code =
(hash_code as u64 & 0xffffffffffffff00_u64) as i64 |
(encoding_val as i64);
let mb = MetaStringBytes::new(data, hash_code)?;
- entry.insert(mb)
+ entry.insert(Box::new(mb)).as_mut()
}
};
// update dynamic_read
diff --git a/rust/tests/tests/test_meta_string_resolver.rs
b/rust/tests/tests/test_meta_string_resolver.rs
index d083ae658..468c869d3 100644
--- a/rust/tests/tests/test_meta_string_resolver.rs
+++ b/rust/tests/tests/test_meta_string_resolver.rs
@@ -133,3 +133,63 @@ pub fn big_ms() {
meta_string_reader.reset();
}
}
+
+#[test]
+pub fn big_dynamic_survives_growth() {
+ let mut meta_string_writer = MetaStringWriterResolver::default();
+ let data: Vec<_> = (0..20)
+ .map(|i| {
+ Rc::from(
+ NAMESPACE_ENCODER
+
.encode(&format!("long_meta_string_name_{i:02}_after_growth"))
+ .unwrap(),
+ )
+ })
+ .collect();
+
+ let mut buffer = vec![];
+ let mut writer = Writer::from_buffer(&mut buffer);
+ for meta_string in data.iter() {
+ meta_string_writer
+ .write_meta_string_bytes(&mut writer, meta_string.clone())
+ .unwrap();
+ }
+ writer.write_var_u32(3);
+
+ let binding = writer.dump();
+ let mut reader = Reader::new(binding.as_slice());
+ let mut meta_string_reader = MetaStringReaderResolver::default();
+ for meta_string in data.iter() {
+ let read = meta_string_reader.read_meta_string(&mut reader).unwrap();
+ assert_eq!(&**meta_string, read);
+ }
+ let read = meta_string_reader.read_meta_string(&mut reader).unwrap();
+ assert_eq!(&*data[0], read);
+}
+
+#[test]
+pub fn small_dynamic_survives_growth() {
+ let mut meta_string_writer = MetaStringWriterResolver::default();
+ let data: Vec<_> = (0..20)
+ .map(|i|
Rc::from(NAMESPACE_ENCODER.encode(&format!("s{i:014}")).unwrap()))
+ .collect();
+
+ let mut buffer = vec![];
+ let mut writer = Writer::from_buffer(&mut buffer);
+ for meta_string in data.iter() {
+ meta_string_writer
+ .write_meta_string_bytes(&mut writer, meta_string.clone())
+ .unwrap();
+ }
+ writer.write_var_u32(3);
+
+ let binding = writer.dump();
+ let mut reader = Reader::new(binding.as_slice());
+ let mut meta_string_reader = MetaStringReaderResolver::default();
+ for meta_string in data.iter() {
+ let read = meta_string_reader.read_meta_string(&mut reader).unwrap();
+ assert_eq!(&**meta_string, read);
+ }
+ let read = meta_string_reader.read_meta_string(&mut reader).unwrap();
+ assert_eq!(&*data[0], read);
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]