Skip to content

Conversation

@urlyy
Copy link
Contributor

@urlyy urlyy commented Oct 9, 2025

What does this PR do?

  1. Remove the lifetime annotations from WriteContext and ReadContext because managing their lifetimes was too troublesome. The trade-off is that, previously, MetaWriterResolver held references to the corresponding TypeDef obtained from TypeResolver, and both contexts also fetched references to Harness objects managed by TypeResolver. Now, all these references have been replaced with clone() to simplify lifetime management. This may introduce a non-negligible performance overhead, but it was the only practical solution I could implement.🥲

  2. Remove &fory from the member variables of Context. Instead, &fory is now passed in as a function parameter rather than being retrieved via context.get_fory(). This change modified many API signatures.

  3. Add two pools to Fory’s member variables to allow reuse of both types of contexts. Tests confirmed that the same context addresses were reused multiple times. However, since automatic recycling would require Arc<Fory>, only manual recycling has been implemented so far — this operation is handled internally(within serialize()/deserialize()), and users don’t need to recycle contexts manually. Also, for the de/serialize_with_context(context) functions, if users call them directly, the user's manually managed contexts will not be returned to the pool.

  4. Add reset() methods to be executed on Context objects before recycling.

  5. Modified TypeResolver::sorted_field_names_map from RefCell<...> to RwLock<...>, and changed MetaReaderResolver::reading_type_defs from Vec<Rc<TypeMeta>> to Vec<Arc<TypeMeta>>. Split Fory::MetaStringResolver to ReadContext::MetaStringResolver and WriteContext::MetaStringResolver. In addition, RefReader was unsafely marked as Send and Sync. These changes allow Fory to support serialization across multiple threads. A concrete example can be found in rust/tests/tests/test_multi_thread.rs. However, I’m not sure whether using Lock and Arc will impact single-thread performance. But it may be troublesome to write another ThreadSafeFory.

  6. The reason why I unsafe impl Send/Sync for RefReader {}, is that , RefReader contains Box<dyn Any>, which by default is not Send/Sync. But In our usage, each ref_reader is only accessed within a context, by one thread at a time, so it is safe to implement Send/Sync manually using unsafe.

Related issues

Does this PR introduce any user-facing change?

yes, like implementing in EXT, need to pass a extra parameter fory.

@urlyy urlyy changed the title Context pool feat(Rust): support context_pool to reduce context allocation && support se/de in multi-thread Oct 9, 2025
@urlyy
Copy link
Contributor Author

urlyy commented Oct 9, 2025

Btw, unsafe impl Send/Sync for RefReader {} is the solution I got from large language model. Although there are other safe approaches, they are more complicated to implement, and I think this solution is quite suitable for the current situation.

@urlyy
Copy link
Contributor Author

urlyy commented Oct 9, 2025

When in reset, will call functions named reset() or clear(). You may consider whether to unify the naming convention to either clear or reset. @chaokunyang

@urlyy
Copy link
Contributor Author

urlyy commented Oct 9, 2025

maybe I can set Fory::metastring_resolver to Arc<rwlock>
,i forgot this.

@chaokunyang
Copy link
Collaborator

rwlock

Split into read and write, Then hold it on Read Write context

@chaokunyang
Copy link
Collaborator

When in reset, will call functions named reset() or clear(). You may consider whether to unify the naming convention to either clear or reset. @chaokunyang

use reset instead, it used in java/python

@chaokunyang
Copy link
Collaborator

chaokunyang commented Oct 10, 2025

@urlyy Nice work! Could you run fory-benchmarks and compare the performance with previous version?

@urlyy

This comment was marked as outdated.

@urlyy

This comment was marked as outdated.

@urlyy

This comment has been minimized.

impl Reader {
pub fn new(bf: &[u8]) -> Reader {
Reader {
bf: bf.to_vec(),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will this introduce a copy?

Copy link
Contributor Author

@urlyy urlyy Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, but only when enter a deserialize will do such a clone.

@urlyy
Copy link
Contributor Author

urlyy commented Oct 10, 2025

@chaokunyang Handling these clones requires dealing with lifetimes. I spent quite a while on it but couldn’t get it to work, so I left it as is for now. However, optimizing it after this PR shouldn’t be too difficult — using Arc should be enough to solve the reference issue, right?

@chaokunyang
Copy link
Collaborator

@chaokunyang Handling these clones requires dealing with lifetimes. I spent quite a while on it but couldn’t get it to work, so I left it as is for now. However, optimizing it after this PR shouldn’t be too difficult — using Arc should be enough to solve the reference issue, right?

@urlyy You can create a new struct to manage read state:

pub struct ReadState {
    pub meta_resolver: MetaReaderResolver,
    meta_string_resolver: MetaStringReaderResolver,
    pub ref_reader: RefReader,
}

And pooling this class:

struct Fory {
  ...,
  read_context_pool: Pool<ReadState>,
}

For deserialize, just create ReadContext everytime from ReadState, and use lifetime for buffer

@urlyy
Copy link
Contributor Author

urlyy commented Oct 10, 2025

Here is the output after replace type of Reader.bf from Vec<u8> to *const u8 and remote clone().

simple_struct/fory_serialize/small
                        time:   [105.24 ns 105.39 ns 105.53 ns]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild
simple_struct/fory_serialize/medium
                        time:   [137.50 ns 137.63 ns 137.76 ns]
Found 7 outliers among 100 measurements (7.00%)
  5 (5.00%) high mild
  2 (2.00%) high severe
simple_struct/fory_serialize/large
                        time:   [248.31 ns 248.46 ns 248.62 ns]
Found 5 outliers among 100 measurements (5.00%)
  2 (2.00%) high mild
  3 (3.00%) high severe
simple_struct/fory_deserialize/small
                        time:   [102.19 ns 102.37 ns 102.66 ns]
Found 14 outliers among 100 measurements (14.00%)
  8 (8.00%) high mild
  6 (6.00%) high severe
simple_struct/fory_deserialize/medium
                        time:   [109.70 ns 109.77 ns 109.84 ns]
Found 13 outliers among 100 measurements (13.00%)
  1 (1.00%) low mild
  4 (4.00%) high mild
  8 (8.00%) high severe
simple_struct/fory_deserialize/large
                        time:   [117.12 ns 117.22 ns 117.32 ns]
Found 9 outliers among 100 measurements (9.00%)
  6 (6.00%) high mild
  3 (3.00%) high severe
simple_struct/protobuf_serialize/small
                        time:   [93.527 ns 93.581 ns 93.639 ns]
Found 9 outliers among 100 measurements (9.00%)
  5 (5.00%) high mild
  4 (4.00%) high severe
simple_struct/protobuf_serialize/medium
                        time:   [112.40 ns 112.81 ns 113.66 ns]
Found 7 outliers among 100 measurements (7.00%)
  4 (4.00%) high mild
  3 (3.00%) high severe
simple_struct/protobuf_serialize/large
                        time:   [136.30 ns 136.38 ns 136.46 ns]
Found 3 outliers among 100 measurements (3.00%)
  1 (1.00%) high mild
  2 (2.00%) high severe
simple_struct/protobuf_deserialize/small
                        time:   [41.959 ns 41.989 ns 42.020 ns]
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) low mild
  1 (1.00%) high mild
  2 (2.00%) high severe
simple_struct/protobuf_deserialize/medium
                        time:   [45.115 ns 45.149 ns 45.185 ns]
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high severe
simple_struct/protobuf_deserialize/large
                        time:   [57.344 ns 57.566 ns 57.881 ns]
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe
simple_struct/json_serialize/small
                        time:   [120.66 ns 120.87 ns 121.26 ns]
Found 5 outliers among 100 measurements (5.00%)
  5 (5.00%) high severe
simple_struct/json_serialize/medium
                        time:   [120.46 ns 120.53 ns 120.61 ns]
Found 13 outliers among 100 measurements (13.00%)
  7 (7.00%) high mild
  6 (6.00%) high severe
simple_struct/json_serialize/large
                        time:   [272.19 ns 273.43 ns 274.75 ns]
Found 11 outliers among 100 measurements (11.00%)
  8 (8.00%) high mild
  3 (3.00%) high severe
simple_struct/json_deserialize/small
                        time:   [103.92 ns 103.97 ns 104.02 ns]
Found 11 outliers among 100 measurements (11.00%)
  7 (7.00%) high mild
  4 (4.00%) high severe
simple_struct/json_deserialize/medium
                        time:   [122.95 ns 123.13 ns 123.40 ns]
Found 11 outliers among 100 measurements (11.00%)
  7 (7.00%) high mild
  4 (4.00%) high severe
simple_struct/json_deserialize/large
                        time:   [145.21 ns 145.33 ns 145.46 ns]
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) high mild
  1 (1.00%) high severe

simple_list/fory_serialize/small
                        time:   [153.08 ns 153.53 ns 154.07 ns]
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high mild
simple_list/fory_serialize/medium
                        time:   [1.5830 µs 1.5838 µs 1.5846 µs]
Found 4 outliers among 100 measurements (4.00%)
  2 (2.00%) high mild
  2 (2.00%) high severe
simple_list/fory_serialize/large
                        time:   [19.972 µs 20.003 µs 20.034 µs]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high severe
simple_list/fory_deserialize/small
                        time:   [175.43 ns 175.56 ns 175.70 ns]
Found 7 outliers among 100 measurements (7.00%)
  5 (5.00%) high mild
  2 (2.00%) high severe
simple_list/fory_deserialize/medium
                        time:   [1.5407 µs 1.5416 µs 1.5427 µs]
Found 11 outliers among 100 measurements (11.00%)
  1 (1.00%) low mild
  5 (5.00%) high mild
  5 (5.00%) high severe
simple_list/fory_deserialize/large
                        time:   [12.578 µs 12.589 µs 12.603 µs]
Found 10 outliers among 100 measurements (10.00%)
  1 (1.00%) low mild
  3 (3.00%) high mild
  6 (6.00%) high severe
simple_list/protobuf_serialize/small
                        time:   [152.12 ns 152.46 ns 152.80 ns]
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe
simple_list/protobuf_serialize/medium
                        time:   [2.0026 µs 2.0058 µs 2.0089 µs]
simple_list/protobuf_serialize/large
                        time:   [18.936 µs 18.952 µs 18.970 µs]
Found 12 outliers among 100 measurements (12.00%)
  7 (7.00%) high mild
  5 (5.00%) high severe
simple_list/protobuf_deserialize/small
                        time:   [159.17 ns 159.26 ns 159.37 ns]
Found 6 outliers among 100 measurements (6.00%)
  4 (4.00%) high mild
  2 (2.00%) high severe
simple_list/protobuf_deserialize/medium
                        time:   [2.5118 µs 2.5156 µs 2.5196 µs]
Found 6 outliers among 100 measurements (6.00%)
  2 (2.00%) low mild
  3 (3.00%) high mild
  1 (1.00%) high severe
simple_list/protobuf_deserialize/large
                        time:   [21.034 µs 21.058 µs 21.082 µs]
Found 6 outliers among 100 measurements (6.00%)
  4 (4.00%) high mild
  2 (2.00%) high severe
simple_list/json_serialize/small
                        time:   [149.56 ns 149.69 ns 149.84 ns]
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) high mild
  4 (4.00%) high severe
simple_list/json_serialize/medium
                        time:   [1.9383 µs 1.9405 µs 1.9434 µs]
Found 11 outliers among 100 measurements (11.00%)
  7 (7.00%) high mild
  4 (4.00%) high severe
simple_list/json_serialize/large
                        time:   [22.094 µs 22.135 µs 22.192 µs]
Found 10 outliers among 100 measurements (10.00%)
  4 (4.00%) high mild
  6 (6.00%) high severe
simple_list/json_deserialize/small
                        time:   [225.49 ns 225.62 ns 225.75 ns]
Found 6 outliers among 100 measurements (6.00%)
  2 (2.00%) high mild
  4 (4.00%) high severe
simple_list/json_deserialize/medium
                        time:   [2.7217 µs 2.7236 µs 2.7257 µs]
Found 8 outliers among 100 measurements (8.00%)
  8 (8.00%) high severe
simple_list/json_deserialize/large
                        time:   [26.327 µs 26.373 µs 26.448 µs]
Found 8 outliers among 100 measurements (8.00%)
  4 (4.00%) high mild
  4 (4.00%) high severe

simple_map/fory_serialize/small
                        time:   [196.63 ns 196.81 ns 197.02 ns]
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) high mild
  3 (3.00%) high severe
simple_map/fory_serialize/medium
                        time:   [3.3440 µs 3.3464 µs 3.3488 µs]
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) high mild
  4 (4.00%) high severe
simple_map/fory_serialize/large
                        time:   [43.687 µs 43.799 µs 43.926 µs]
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild
simple_map/fory_deserialize/small
                        time:   [294.75 ns 294.99 ns 295.24 ns]
Found 5 outliers among 100 measurements (5.00%)
  4 (4.00%) high mild
  1 (1.00%) high severe
simple_map/fory_deserialize/medium
                        time:   [4.2809 µs 4.2839 µs 4.2873 µs]
Found 10 outliers among 100 measurements (10.00%)
  4 (4.00%) high mild
  6 (6.00%) high severe
simple_map/fory_deserialize/large
                        time:   [55.515 µs 56.344 µs 57.165 µs]
simple_map/protobuf_serialize/small
                        time:   [275.37 ns 275.69 ns 276.02 ns]
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) low mild
  2 (2.00%) high mild
  1 (1.00%) high severe
simple_map/protobuf_serialize/medium
                        time:   [4.2858 µs 4.2898 µs 4.2935 µs]
Found 5 outliers among 100 measurements (5.00%)
  1 (1.00%) low mild
  3 (3.00%) high mild
  1 (1.00%) high severe
simple_map/protobuf_serialize/large
                        time:   [47.745 µs 47.808 µs 47.880 µs]
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) high mild
  1 (1.00%) high severe
simple_map/protobuf_deserialize/small
                        time:   [244.98 ns 245.51 ns 246.09 ns]
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe
simple_map/protobuf_deserialize/medium
                        time:   [8.1810 µs 8.1879 µs 8.1947 µs]
Found 5 outliers among 100 measurements (5.00%)
  1 (1.00%) low mild
  3 (3.00%) high mild
  1 (1.00%) high severe
simple_map/protobuf_deserialize/large
                        time:   [102.32 µs 102.87 µs 103.40 µs]
Found 8 outliers among 100 measurements (8.00%)
  7 (7.00%) low mild
  1 (1.00%) high mild
simple_map/json_serialize/small
                        time:   [202.96 ns 203.63 ns 204.34 ns]
simple_map/json_serialize/medium
                        time:   [3.8316 µs 3.8414 µs 3.8508 µs]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild
simple_map/json_serialize/large
                        time:   [47.103 µs 47.533 µs 47.942 µs]
Found 9 outliers among 100 measurements (9.00%)
  1 (1.00%) low severe
  7 (7.00%) low mild
  1 (1.00%) high mild
simple_map/json_deserialize/small
                        time:   [318.27 ns 318.98 ns 319.72 ns]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild
simple_map/json_deserialize/medium
                        time:   [7.3319 µs 7.3477 µs 7.3641 µs]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild
simple_map/json_deserialize/large
                        time:   [92.675 µs 93.079 µs 93.511 µs]
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high mild

person/fory_serialize/small
                        time:   [443.74 ns 443.92 ns 444.11 ns]
Found 12 outliers among 100 measurements (12.00%)
  6 (6.00%) high mild
  6 (6.00%) high severe
person/fory_serialize/medium
                        time:   [2.2502 µs 2.2559 µs 2.2627 µs]
Found 12 outliers among 100 measurements (12.00%)
  2 (2.00%) high mild
  10 (10.00%) high severe
person/fory_serialize/large
                        time:   [12.094 µs 12.121 µs 12.153 µs]
Found 6 outliers among 100 measurements (6.00%)
  2 (2.00%) high mild
  4 (4.00%) high severe
person/fory_deserialize/small
                        time:   [640.93 ns 641.37 ns 641.87 ns]
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe
person/fory_deserialize/medium
                        time:   [2.2199 µs 2.2238 µs 2.2282 µs]
Found 7 outliers among 100 measurements (7.00%)
  6 (6.00%) high mild
  1 (1.00%) high severe
person/fory_deserialize/large
                        time:   [8.9466 µs 8.9513 µs 8.9565 µs]
Found 9 outliers among 100 measurements (9.00%)
  5 (5.00%) high mild
  4 (4.00%) high severe
person/protobuf_serialize/small
                        time:   [463.69 ns 463.97 ns 464.28 ns]
Found 9 outliers among 100 measurements (9.00%)
  5 (5.00%) high mild
  4 (4.00%) high severe
person/protobuf_serialize/medium
                        time:   [2.0094 µs 2.0108 µs 2.0121 µs]
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe
person/protobuf_serialize/large
                        time:   [8.5951 µs 8.6069 µs 8.6244 µs]
Found 6 outliers among 100 measurements (6.00%)
  2 (2.00%) high mild
  4 (4.00%) high severe
person/protobuf_deserialize/small
                        time:   [504.96 ns 505.18 ns 505.43 ns]
Found 9 outliers among 100 measurements (9.00%)
  3 (3.00%) high mild
  6 (6.00%) high severe
person/protobuf_deserialize/medium
                        time:   [3.3605 µs 3.3644 µs 3.3692 µs]
Found 13 outliers among 100 measurements (13.00%)
  3 (3.00%) high mild
  10 (10.00%) high severe
person/protobuf_deserialize/large
                        time:   [14.383 µs 14.416 µs 14.447 µs]
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe
person/json_serialize/small
                        time:   [575.28 ns 576.60 ns 579.18 ns]
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) high mild
  4 (4.00%) high severe
person/json_serialize/medium
                        time:   [2.3026 µs 2.3065 µs 2.3107 µs]
Found 4 outliers among 100 measurements (4.00%)
  4 (4.00%) high mild
person/json_serialize/large
                        time:   [10.090 µs 10.116 µs 10.157 µs]
Found 9 outliers among 100 measurements (9.00%)
  5 (5.00%) high mild
  4 (4.00%) high severe
person/json_deserialize/small
                        time:   [725.83 ns 726.21 ns 726.62 ns]
Found 8 outliers among 100 measurements (8.00%)
  5 (5.00%) high mild
  3 (3.00%) high severe
person/json_deserialize/medium
                        time:   [3.2053 µs 3.2077 µs 3.2107 µs]
Found 7 outliers among 100 measurements (7.00%)
  2 (2.00%) high mild
  5 (5.00%) high severe
person/json_deserialize/large
                        time:   [13.823 µs 13.831 µs 13.840 µs]
Found 9 outliers among 100 measurements (9.00%)
  7 (7.00%) high mild
  2 (2.00%) high severe

company/fory_serialize/small
                        time:   [701.06 ns 701.81 ns 702.70 ns]
Found 6 outliers among 100 measurements (6.00%)
  2 (2.00%) high mild
  4 (4.00%) high severe
company/fory_serialize/medium
                        time:   [22.946 µs 22.975 µs 23.004 µs]
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) high mild
  3 (3.00%) high severe
Benchmarking company/fory_serialize/large: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 6.1s, enable flat sampling, or reduce sample count to 60.
company/fory_serialize/large
                        time:   [1.2003 ms 1.2022 ms 1.2041 ms]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high severe
company/fory_deserialize/small
                        time:   [977.44 ns 979.32 ns 981.22 ns]
company/fory_deserialize/medium
                        time:   [22.977 µs 22.995 µs 23.016 µs]
Found 7 outliers among 100 measurements (7.00%)
  2 (2.00%) high mild
  5 (5.00%) high severe
Benchmarking company/fory_deserialize/large: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 5.0s, enable flat sampling, or reduce sample count to 70.
company/fory_deserialize/large
                        time:   [995.23 µs 996.34 µs 997.56 µs]
Found 6 outliers among 100 measurements (6.00%)
  3 (3.00%) high mild
  3 (3.00%) high severe
company/protobuf_serialize/small
                        time:   [788.53 ns 788.97 ns 789.42 ns]
Found 5 outliers among 100 measurements (5.00%)
  1 (1.00%) high mild
  4 (4.00%) high severe
company/protobuf_serialize/medium
                        time:   [20.657 µs 20.670 µs 20.682 µs]
Found 5 outliers among 100 measurements (5.00%)
  2 (2.00%) high mild
  3 (3.00%) high severe
company/protobuf_serialize/large
                        time:   [957.08 µs 959.59 µs 963.04 µs]
Found 7 outliers among 100 measurements (7.00%)
  3 (3.00%) high mild
  4 (4.00%) high severe
company/protobuf_deserialize/small
                        time:   [985.71 ns 987.58 ns 989.65 ns]
Found 9 outliers among 100 measurements (9.00%)
  7 (7.00%) high mild
  2 (2.00%) high severe
company/protobuf_deserialize/medium
                        time:   [36.173 µs 36.194 µs 36.219 µs]
Found 9 outliers among 100 measurements (9.00%)
  1 (1.00%) low mild
  4 (4.00%) high mild
  4 (4.00%) high severe
Benchmarking company/protobuf_deserialize/large: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 7.8s, enable flat sampling, or reduce sample count to 50.
company/protobuf_deserialize/large
                        time:   [1.5459 ms 1.5472 ms 1.5487 ms]
Found 10 outliers among 100 measurements (10.00%)
  4 (4.00%) high mild
  6 (6.00%) high severe
company/json_serialize/small
                        time:   [1.0676 µs 1.0689 µs 1.0703 µs]
Found 5 outliers among 100 measurements (5.00%)
  3 (3.00%) high mild
  2 (2.00%) high severe
company/json_serialize/medium
                        time:   [23.665 µs 23.678 µs 23.692 µs]
Found 3 outliers among 100 measurements (3.00%)
  1 (1.00%) high mild
  2 (2.00%) high severe
Benchmarking company/json_serialize/large: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 5.5s, enable flat sampling, or reduce sample count to 60.
company/json_serialize/large
                        time:   [1.0890 ms 1.0911 ms 1.0933 ms]
Found 7 outliers among 100 measurements (7.00%)
  5 (5.00%) high mild
  2 (2.00%) high severe
company/json_deserialize/small
                        time:   [1.3039 µs 1.3061 µs 1.3086 µs]
Found 6 outliers among 100 measurements (6.00%)
  5 (5.00%) high mild
  1 (1.00%) high severe
company/json_deserialize/medium
                        time:   [35.894 µs 35.918 µs 35.947 µs]
Found 7 outliers among 100 measurements (7.00%)
  2 (2.00%) high mild
  5 (5.00%) high severe
Benchmarking company/json_deserialize/large: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 7.7s, enable flat sampling, or reduce sample count to 50.
company/json_deserialize/large
                        time:   [1.5231 ms 1.5245 ms 1.5259 ms]
Found 9 outliers among 100 measurements (9.00%)
  2 (2.00%) high mild
  7 (7.00%) high severe

ecommerce_data/fory_serialize/small
                        time:   [2.3465 µs 2.3477 µs 2.3489 µs]
Found 13 outliers among 100 measurements (13.00%)
  1 (1.00%) low mild
  5 (5.00%) high mild
  7 (7.00%) high severe
ecommerce_data/fory_serialize/medium
                        time:   [138.25 µs 138.35 µs 138.44 µs]
Found 6 outliers among 100 measurements (6.00%)
  5 (5.00%) high mild
  1 (1.00%) high severe
ecommerce_data/fory_serialize/large
                        time:   [2.4117 ms 2.4165 ms 2.4237 ms]
Found 5 outliers among 100 measurements (5.00%)
  3 (3.00%) high mild
  2 (2.00%) high severe
ecommerce_data/fory_deserialize/small
                        time:   [3.7797 µs 3.7824 µs 3.7853 µs]
Found 9 outliers among 100 measurements (9.00%)
  6 (6.00%) high mild
  3 (3.00%) high severe
ecommerce_data/fory_deserialize/medium
                        time:   [170.56 µs 171.07 µs 171.76 µs]
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe
ecommerce_data/fory_deserialize/large
                        time:   [2.5833 ms 2.5871 ms 2.5910 ms]
Found 6 outliers among 100 measurements (6.00%)
  2 (2.00%) low mild
  4 (4.00%) high mild
ecommerce_data/protobuf_serialize/small
                        time:   [2.8946 µs 2.8968 µs 2.8992 µs]
Found 5 outliers among 100 measurements (5.00%)
  1 (1.00%) low mild
  1 (1.00%) high mild
  3 (3.00%) high severe
ecommerce_data/protobuf_serialize/medium
                        time:   [171.15 µs 171.42 µs 171.69 µs]
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe
ecommerce_data/protobuf_serialize/large
                        time:   [2.6098 ms 2.6179 ms 2.6278 ms]
Found 12 outliers among 100 measurements (12.00%)
  1 (1.00%) low mild
  5 (5.00%) high mild
  6 (6.00%) high severe
ecommerce_data/protobuf_deserialize/small
                        time:   [3.5810 µs 3.5840 µs 3.5872 µs]
Found 5 outliers among 100 measurements (5.00%)
  3 (3.00%) high mild
  2 (2.00%) high severe
ecommerce_data/protobuf_deserialize/medium
                        time:   [226.29 µs 227.09 µs 228.09 µs]
Found 9 outliers among 100 measurements (9.00%)
  1 (1.00%) low mild
  4 (4.00%) high mild
  4 (4.00%) high severe
ecommerce_data/protobuf_deserialize/large
                        time:   [3.8585 ms 3.8645 ms 3.8710 ms]
Found 10 outliers among 100 measurements (10.00%)
  1 (1.00%) low mild
  5 (5.00%) high mild
  4 (4.00%) high severe
ecommerce_data/json_serialize/small
                        time:   [3.9836 µs 3.9887 µs 3.9940 µs]
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild
ecommerce_data/json_serialize/medium
                        time:   [190.16 µs 191.02 µs 191.80 µs]
Found 11 outliers among 100 measurements (11.00%)
  4 (4.00%) low severe
  5 (5.00%) low mild
  1 (1.00%) high mild
  1 (1.00%) high severe
ecommerce_data/json_serialize/large
                        time:   [2.8643 ms 2.8741 ms 2.8848 ms]
Found 8 outliers among 100 measurements (8.00%)
  6 (6.00%) high mild
  2 (2.00%) high severe
ecommerce_data/json_deserialize/small
                        time:   [5.1308 µs 5.1343 µs 5.1382 µs]
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) high mild
  3 (3.00%) high severe
ecommerce_data/json_deserialize/medium
                        time:   [247.37 µs 248.00 µs 248.58 µs]
ecommerce_data/json_deserialize/large
                        time:   [4.0153 ms 4.0227 ms 4.0304 ms]
Found 15 outliers among 100 measurements (15.00%)
  5 (5.00%) low mild
  7 (7.00%) high mild
  3 (3.00%) high severe

system_data/fory_serialize/small
                        time:   [1.0595 µs 1.0602 µs 1.0610 µs]
Found 8 outliers among 100 measurements (8.00%)
  7 (7.00%) high mild
  1 (1.00%) high severe
system_data/fory_serialize/medium
                        time:   [57.589 µs 57.675 µs 57.761 µs]
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe
system_data/fory_serialize/large
                        time:   [890.71 µs 892.49 µs 894.80 µs]
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe
system_data/fory_deserialize/small
                        time:   [1.7670 µs 1.7694 µs 1.7719 µs]
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild
system_data/fory_deserialize/medium
                        time:   [67.091 µs 67.217 µs 67.335 µs]
Found 2 outliers among 100 measurements (2.00%)
  1 (1.00%) high mild
  1 (1.00%) high severe
system_data/fory_deserialize/large
                        time:   [909.51 µs 910.45 µs 911.43 µs]
Found 5 outliers among 100 measurements (5.00%)
  3 (3.00%) high mild
  2 (2.00%) high severe
system_data/protobuf_serialize/small
                        time:   [1.2555 µs 1.2567 µs 1.2580 µs]
Found 4 outliers among 100 measurements (4.00%)
  1 (1.00%) high mild
  3 (3.00%) high severe
system_data/protobuf_serialize/medium
                        time:   [54.462 µs 54.569 µs 54.670 µs]
Found 6 outliers among 100 measurements (6.00%)
  3 (3.00%) low mild
  2 (2.00%) high mild
  1 (1.00%) high severe
system_data/protobuf_serialize/large
                        time:   [772.12 µs 775.26 µs 779.07 µs]
Found 5 outliers among 100 measurements (5.00%)
  2 (2.00%) high mild
  3 (3.00%) high severe
system_data/protobuf_deserialize/small
                        time:   [1.6431 µs 1.6446 µs 1.6463 µs]
Found 4 outliers among 100 measurements (4.00%)
  3 (3.00%) high mild
  1 (1.00%) high severe
system_data/protobuf_deserialize/medium
                        time:   [92.775 µs 92.924 µs 93.083 µs]
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high severe
Benchmarking system_data/protobuf_deserialize/large: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 6.5s, enable flat sampling, or reduce sample count to 60.
system_data/protobuf_deserialize/large
                        time:   [1.4527 ms 1.4544 ms 1.4562 ms]
Found 7 outliers among 100 measurements (7.00%)
  2 (2.00%) high mild
  5 (5.00%) high severe
system_data/json_serialize/small
                        time:   [1.7491 µs 1.7534 µs 1.7578 µs]
Found 3 outliers among 100 measurements (3.00%)
  3 (3.00%) high mild
system_data/json_serialize/medium
                        time:   [72.577 µs 72.712 µs 72.841 µs]
Found 3 outliers among 100 measurements (3.00%)
  2 (2.00%) high mild
  1 (1.00%) high severe
system_data/json_serialize/large
                        time:   [977.94 µs 979.30 µs 980.68 µs]
Found 8 outliers among 100 measurements (8.00%)
  6 (6.00%) high mild
  2 (2.00%) high severe
system_data/json_deserialize/small
                        time:   [2.2170 µs 2.2205 µs 2.2256 µs]
Found 12 outliers among 100 measurements (12.00%)
  6 (6.00%) high mild
  6 (6.00%) high severe
system_data/json_deserialize/medium
                        time:   [100.76 µs 101.20 µs 101.66 µs]
Benchmarking system_data/json_deserialize/large: Warming up for 3.0000 s
Warning: Unable to complete 100 samples in 5.0s. You may wish to increase target time to 7.0s, enable flat sampling, or reduce sample count to 50.
system_data/json_deserialize/large
                        time:   [1.3962 ms 1.3991 ms 1.4030 ms]
Found 7 outliers among 100 measurements (7.00%)
  2 (2.00%) high mild
  5 (5.00%) high severe

@urlyy
Copy link
Contributor Author

urlyy commented Oct 10, 2025

@chaokunyang cargo-criterion can export output in json/csv/plots format, This is more readable compared to the current command-line output.
https://bheisler.github.io/criterion.rs/book/user_guide/csv_output.html

@urlyy
Copy link
Contributor Author

urlyy commented Oct 10, 2025

btw, https://github.com/apache/fory/actions/runs/18417030950/job/52483058475?pr=2737, this CI takes too much time, 17 minutes! I can't bare this.

@urlyy
Copy link
Contributor Author

urlyy commented Oct 10, 2025

Using raw pointers is unsafe, but as long as we don’t continue holding references after deserialization and only use the reference within a single thread, it won’t cause any issues.

Copy link
Collaborator

@chaokunyang chaokunyang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, I will finish remaining refactor in later PR

@chaokunyang chaokunyang merged commit f1187b1 into apache:main Oct 11, 2025
53 checks passed
chaokunyang added a commit that referenced this pull request Oct 15, 2025
## Why?

Simplify the serialization interface for better ergonomics API

## What does this PR do?

- Remove `Fory` from `Serializer` trait
- Make `WriteContext` as only enviroment for serialization
- Make `ReadContext` as only enviroment for deserialization
- Use `OnceLock` for  thread-safe, lazily initialization for `Pool`

## Related issues

#2737

## Does this PR introduce any user-facing change?

<!--
If any user-facing interface changes, please [open an
issue](https://github.com/apache/fory/issues/new/choose) describing the
need to do so and update the document if necessary.

Delete section if not applicable.
-->

- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?

## Benchmark

<!--
When the PR has an impact on performance (if you don't know whether the
PR will have an impact on performance, you can submit the PR first, and
if it will have impact on performance, the code reviewer will explain
it), be sure to attach a benchmark data here.

Delete section if not applicable.
-->
rajuyadav03 pushed a commit to rajuyadav03/fory that referenced this pull request Oct 20, 2025
…ort se/de in multi-thread (apache#2737)

## What does this PR do?

1. Remove the lifetime annotations from `WriteContext` and `ReadContext`
because managing their lifetimes was too troublesome. The **trade-off**
is that, previously, `MetaWriterResolver` held references to the
corresponding `TypeDef` obtained from `TypeResolver`, and both contexts
also fetched references to `Harness` objects managed by `TypeResolver`.
Now, all these references have been replaced with `clone()` to simplify
lifetime management. This may introduce a non-negligible performance
overhead, but it was the only practical solution I could implement.🥲

2. Remove `&fory` from the member variables of `Context`. Instead,
`&fory` is now passed in as a function parameter rather than being
retrieved via `context.get_fory()`. This change modified many API
signatures.

3. Add two pools to `Fory`’s member variables to allow reuse of both
types of contexts. Tests confirmed that the same context addresses were
reused multiple times. However, since automatic recycling would require
`Arc<Fory>`, only manual recycling has been implemented so far — this
operation is handled internally(within `serialize()/deserialize()`), and
users don’t need to recycle contexts manually. Also, for the
`de/serialize_with_context(context)` functions, if users call them
directly, the user's manually managed contexts will **not** be returned
to the pool.

4. Add `reset()` methods to be executed on `Context objects` before
recycling.

5. Modified `TypeResolver::sorted_field_names_map` from `RefCell<...>`
to `RwLock<...>`, and changed `MetaReaderResolver::reading_type_defs`
from `Vec<Rc<TypeMeta>>` to `Vec<Arc<TypeMeta>>`. Split
`Fory::MetaStringResolver` to `ReadContext::MetaStringResolver` and
`WriteContext::MetaStringResolver`. In addition, `RefReader` was
unsafely marked as `Send` and `Sync`. These changes allow `Fory` to
support serialization across multiple threads. A concrete example can be
found in `rust/tests/tests/test_multi_thread.rs`. However, I’m not sure
whether using `Lock` and `Arc` will impact single-thread performance.
But it may be troublesome to write another `ThreadSafeFory`.

6. The reason why I `unsafe impl Send/Sync for RefReader {}`, is that ,
`RefReader` contains `Box<dyn Any>`, which by default is not
`Send`/`Sync`. But In our usage, each ref_reader is only accessed within
a context, by `one` thread at a time, so it is safe to implement
`Send`/`Sync` manually using `unsafe`.


## Related issues
- close apache#2717 

## Does this PR introduce any user-facing change?
yes, like implementing in EXT, need to pass a extra parameter `fory`.
rajuyadav03 pushed a commit to rajuyadav03/fory that referenced this pull request Oct 20, 2025
## Why?

Simplify the serialization interface for better ergonomics API

## What does this PR do?

- Remove `Fory` from `Serializer` trait
- Make `WriteContext` as only enviroment for serialization
- Make `ReadContext` as only enviroment for deserialization
- Use `OnceLock` for  thread-safe, lazily initialization for `Pool`

## Related issues

apache#2737

## Does this PR introduce any user-facing change?

<!--
If any user-facing interface changes, please [open an
issue](https://github.com/apache/fory/issues/new/choose) describing the
need to do so and update the document if necessary.

Delete section if not applicable.
-->

- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?

## Benchmark

<!--
When the PR has an impact on performance (if you don't know whether the
PR will have an impact on performance, you can submit the PR first, and
if it will have impact on performance, the code reviewer will explain
it), be sure to attach a benchmark data here.

Delete section if not applicable.
-->
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.

[Rust] reuse context to manage reduce object allocation

2 participants