chaokunyang opened a new issue, #2721:
URL: https://github.com/apache/fory/issues/2721
### Feature Request
unroll rust struct serialization loop for better peprformance to reduce
field name compare, and loop unroll can speed up code cache and give better
branch predict too.
### Is your feature request related to a problem? Please describe
_No response_
### Describe the solution you'd like
Currently `ForyObject` macro generate code like:
```rust
impl fory_core::serializer::Serializer for Node {
fn fory_get_type_id(fory: &fory_core::fory::Fory) -> u32 {
fory.get_type_resolver().get_type_id(&std::any::TypeId::of::<Self>(), 0u32)
}
fn fory_type_id_dyn(&self, fory: &fory_core::fory::Fory) -> u32 {
Self::fory_get_type_id(fory)
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn fory_reserved_space() -> usize {
<Vec<
Rc<RefCell<Node>>,
> as fory_core::serializer::Serializer>::fory_reserved_space()
+ fory_core::types::SIZE_OF_REF_AND_TYPE
+ <RcWeak<
RefCell<Node>,
> as fory_core::serializer::Serializer>::fory_reserved_space()
+ fory_core::types::SIZE_OF_REF_AND_TYPE
+ <i32 as
fory_core::serializer::Serializer>::fory_reserved_space()
+ fory_core::types::SIZE_OF_REF_AND_TYPE
}
fn fory_write_type_info(
context: &mut fory_core::resolver::context::WriteContext,
is_field: bool,
) {
fory_core::serializer::struct_::write_type_info::<Self>(context,
is_field)
}
fn fory_read_type_info(
context: &mut fory_core::resolver::context::ReadContext,
is_field: bool,
) {
fory_core::serializer::struct_::read_type_info::<Self>(context,
is_field)
}
fn fory_write_data(
&self,
context: &mut fory_core::resolver::context::WriteContext,
is_field: bool,
) {
let sorted_field_names = <Self as
fory_core::serializer::StructSerializer>::fory_get_sorted_field_names(
context.get_fory(),
);
for field_name in sorted_field_names {
match field_name.as_str() {
"children" => {
fory_core::serializer::Serializer::fory_write(
&self.children,
context,
true,
);
}
"parent" => {
fory_core::serializer::Serializer::fory_write(
&self.parent,
context,
true,
);
}
"value" => {
let skip_ref_flag =
fory_core::serializer::get_skip_ref_flag::<
i32,
>(context.get_fory());
fory_core::serializer::write_ref_info_data::<
i32,
>(&self.value, context, true, skip_ref_flag, false);
}
_ => ::core::panicking::panic("internal error: entered
unreachable code"),
}
}
}
fn fory_read_data(
context: &mut fory_core::resolver::context::ReadContext,
is_field: bool,
) -> Result<Self, fory_core::error::Error> {
let mut _children: Option<Vec<Rc<RefCell<Node>>>> = None;
let mut _parent: Option<RcWeak<RefCell<Node>>> = None;
let mut _value: Option<i32> = None;
let sorted_field_names = <Self as
fory_core::serializer::StructSerializer>::fory_get_sorted_field_names(
context.get_fory(),
);
for field_name in sorted_field_names {
match field_name.as_str() {
"children" => {
_children = Some(
fory_core::serializer::Serializer::fory_read(context, true)?,
);
}
"parent" => {
_parent = Some(
fory_core::serializer::Serializer::fory_read(context, true)?,
);
}
"value" => {
let skip_ref_flag =
fory_core::serializer::get_skip_ref_flag::<
i32,
>(context.get_fory());
_value = Some(
fory_core::serializer::read_ref_info_data::<
i32,
>(context, true, skip_ref_flag, false)?,
);
}
_ => ::core::panicking::panic("internal error: entered
unreachable code"),
}
}
Ok(Self {
children: _children.unwrap_or_default(),
parent: _parent.unwrap_or_default(),
value: _value.unwrap_or_default(),
})
}
fn fory_write(
&self,
context: &mut fory_core::resolver::context::WriteContext,
is_field: bool,
) {
fory_core::serializer::struct_::write::<Self>(self, context,
is_field)
}
fn fory_read(
context: &mut fory_core::resolver::context::ReadContext,
is_field: bool,
) -> Result<Self, fory_core::error::Error> {
let ref_flag = context.reader.read_i8();
if ref_flag == (fory_core::types::RefFlag::NotNullValue as i8)
|| ref_flag == (fory_core::types::RefFlag::RefValue as i8)
{
match context.get_fory().get_mode() {
fory_core::types::Mode::SchemaConsistent => {
<Self as
fory_core::serializer::Serializer>::fory_read_type_info(
context,
false,
);
<Self as
fory_core::serializer::Serializer>::fory_read_data(
context,
false,
)
}
fory_core::types::Mode::Compatible => {
<Node as
fory_core::serializer::StructSerializer>::fory_read_compatible(
context,
)
}
_ => ::core::panicking::panic("internal error: entered
unreachable code"),
}
} else if ref_flag == (fory_core::types::RefFlag::Null as i8) {
Ok(<Self as fory_core::serializer::ForyDefault>::fory_default())
} else if ref_flag == (fory_core::types::RefFlag::Ref as i8) {
Err(fory_core::error::Error::Ref)
} else {
Err(
fory_core::error::AnyhowError::msg("Unknown ref flag,
value:{ref_flag}"),
)?
}
}
}
```
This is not efficient, especially the loop `for field_name in
sorted_field_names` compare field name every time.
### Describe alternatives you've considered
We should just generate code for every field instead of using loop
### Additional context
_No response_
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]