-
Notifications
You must be signed in to change notification settings - Fork 556
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: faster append_formatted_to_byte_array #5427
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: 0 of 1 files reviewed, 1 unresolved discussion (waiting on @Th0rgal)
corelib/src/to_byte_array.cairo
line 124 at r1 (raw file):
append_big_digits_util(@new_value, ref byte_array, base_nz); byte_array.append_byte(get_big_base_digit_representation(:digit_as_u8)); }
no need for inline.
and since you pre-checked zero value - you can reorder the functions:
Suggestion:
}
#[inline]
fn append_small_digits_util<T, +Drop<T>, +Copy<T>, +DivRem<T>, +TryInto<T, u8>, +Zeroable<T>,>(
mut value: @T, ref byte_array: ByteArray, base_nz: NonZero<T>,
) {
let (new_value, digit) = DivRem::div_rem(*value, base_nz);
let digit_as_u8: u8 = digit.try_into().unwrap();
if new_value.is_zero() {
append_big_digits_util(@new_value, ref byte_array, base_nz);
}
byte_array.append_byte(digit_as_u8 + '0');
}
#[inline]
fn append_big_digits_util<T, +Drop<T>, +Copy<T>, +DivRem<T>, +TryInto<T, u8>, +Zeroable<T>,>(
mut value: @T, ref byte_array: ByteArray, base_nz: NonZero<T>,
) {
let (new_value, digit) = DivRem::div_rem(*value, base_nz);
let digit_as_u8: u8 = digit.try_into().unwrap();
if new_value.is_zero() {
append_big_digits_util(@new_value, ref byte_array, base_nz);
}
byte_array.append_byte(get_big_base_digit_representation(:digit_as_u8));
}
Thanks for the suggestion, let's save one more check. I think you forgot to let (new_value, digit) = DivRem::div_rem(*value, base_nz);
let digit_as_u8: u8 = digit.try_into().unwrap();
if !new_value.is_zero() {
append_big_digits_util(@new_value, ref byte_array, base_nz);
};
byte_array.append_byte(get_big_base_digit_representation(:digit_as_u8)); I now get:
I tried removing the inline but it consumes a bit more gas, not sure why as I would expect it to be inlined automatically:
Should I remove it anyway? |
Co-authored-by: Nicolas Marchand <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed all commit messages.
Reviewable status: 0 of 1 files reviewed, 3 unresolved discussions (waiting on @Th0rgal)
corelib/src/to_byte_array.cairo
line 100 at r2 (raw file):
} #[inline]
still remove the inlines - as this is "more efficient" just because it performs one inline of the recursive function - rather not create more bytecode for now.
corelib/src/to_byte_array.cairo
line 101 at r2 (raw file):
#[inline] fn append_small_digits_util<T, +Drop<T>, +Copy<T>, +DivRem<T>, +TryInto<T, u8>, +Zeroable<T>,>(
doc
corelib/src/to_byte_array.cairo
line 113 at r2 (raw file):
#[inline] fn append_big_digits_util<T, +Drop<T>, +Copy<T>, +DivRem<T>, +TryInto<T, u8>, +Zeroable<T>,>(
doc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 1 files at r3, all commit messages.
Reviewable status: complete! all files reviewed, all discussions resolved (waiting on @Th0rgal)
Interesting, it seems that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the change exactly?
Reviewable status: 0 of 1 files reviewed, all discussions resolved (waiting on @yuvalsw)
before: 141_400 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
all the values of the test - not just a singular value.
also - please compare runs with --print_resource_usage
to get exact resource usage.
Reviewable status: 0 of 1 files reviewed, all discussions resolved (waiting on @yuvalsw)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 1 files at r4, all commit messages.
Reviewable status: complete! all files reviewed, all discussions resolved (waiting on @yuvalsw)
Thank you, here is what I get from the test, I'll retry with
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 1 of 1 files at r4, all commit messages.
Reviewable status: all files reviewed, 5 unresolved discussions (waiting on @Th0rgal)
corelib/src/to_byte_array.cairo
line 100 at r4 (raw file):
} /// Appends ascii representation of value in base_nz to byte_array for single digit base.
this is confusing as here you refer to decimal while we may have different bases. Moreover, 10 is not single digit even in decimal base.
Suggestion:
to byte_array for base <= 10.
corelib/src/to_byte_array.cairo
line 101 at r4 (raw file):
/// Appends ascii representation of value in base_nz to byte_array for single digit base. fn append_small_digits_util<T, +Drop<T>, +Copy<T>, +DivRem<T>, +TryInto<T, u8>, +Zeroable<T>,>(
Suggestion:
+Zeroable<T>>
corelib/src/to_byte_array.cairo
line 101 at r4 (raw file):
/// Appends ascii representation of value in base_nz to byte_array for single digit base. fn append_small_digits_util<T, +Drop<T>, +Copy<T>, +DivRem<T>, +TryInto<T, u8>, +Zeroable<T>,>(
Suggestion:
fn append_formatted_to_byte_array_small_base<
corelib/src/to_byte_array.cairo
line 112 at r4 (raw file):
} /// Appends ascii representation of value in base_nz to byte_array for any base.
append_formatted_to_byte_array_small_base if the base is <=10 as it's more efficient.
Suggestion:
/// Appends ascii representation of value in base_nz to byte_array for any base.
/// Prefer to use
corelib/src/to_byte_array.cairo
line 113 at r4 (raw file):
/// Appends ascii representation of value in base_nz to byte_array for any base. fn append_big_digits_util<T, +Drop<T>, +Copy<T>, +DivRem<T>, +TryInto<T, u8>, +Zeroable<T>,>(
Suggestion:
fn append_formatted_to_byte_array_big_base
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: all files reviewed, 8 unresolved discussions (waiting on @Th0rgal)
corelib/src/to_byte_array.cairo
line 97 at r4 (raw file):
assert(base <= 36, 'base must be <= 36'); append_big_digits_util(value, ref byte_array, base_nz); }
Suggestion:
if base <= LARGE_BASE_REPR_BOUND {
append_digits_util::<SmallBaseDigitRepr>(value, ref byte_array, base_nz);
} else {
assert(base <= 36, 'base must be <= 36');
append_digits_util::<LargeBaseDigitRepr>(value, ref byte_array, base_nz);
}
corelib/src/to_byte_array.cairo
line 110 at r4 (raw file):
}; byte_array.append_byte(digit_as_u8 + '0'); }
.
Suggestion:
/// Appends ascii representation of value in base_nz to byte_array for single digit base.
fn append_digits_util<impl repr: DigitRepr, T, +Drop<T>, +Copy<T>, +DivRem<T>, +TryInto<T, u8>, +Zeroable<T>,>(
mut value: @T, ref byte_array: ByteArray, base_nz: NonZero<T>,
) {
let (new_value, digit) = DivRem::div_rem(*value, base_nz);
let digit_as_u8: u8 = digit.try_into().unwrap();
if !new_value.is_zero() {
append_digits_util::<repr>(@new_value, ref byte_array, base_nz);
};
byte_array.append_byte(repr::repr(digit_as_u8));
}
corelib/src/to_byte_array.cairo
line 132 at r4 (raw file):
digit_as_u8 - 10 + 'a' } }
.
Suggestion:
trait DigitRepr {
fn repr(value: u8) -> u8;
}
impl SmallBaseDigitRepr of DigitRepr {
fn repr(value: u8) -> u8 {
'0' + value
}
}
const LARGE_BASE_REPR_BOUND: u8 = 10;
const LARGE_BASE_REPR_OFFSET: u8 = 'a' - 10;
impl LargeBaseDigitRepr of DigitRepr {
fn repr(value: u8) -> u8 {
if value < LARGE_BASE_REPR_BOUND {
SmallBaseDigitRepr::repr(value)
} else {
LARGE_BASE_REPR_OFFSET + value
}
}
}
This pull request makes bytes_array formatting slightly faster (~10% cheaper in gas usage).
The previous implementation used to append digits to an array via a first loop and loop again over it to reverse it. This code avoids the second iteration by using recursion to reorder the append calls and directly add the digits reversed.
I think it also makes the code cleaner.
cargo run --bin cairo-test -- --single-file ./corelib/src/test/fmt_test.cairo
Before changes:
After changes:
This change is