Skip to content
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

Add && Impl new trait ToCompactStr #16

Merged
merged 60 commits into from
Apr 26, 2022
Merged

Add && Impl new trait ToCompactStr #16

merged 60 commits into from
Apr 26, 2022

Conversation

NobodyXu
Copy link
Contributor

Similar to std::string::ToString, ToCompactStr convert any value implements fmt::Display into a CompactStr efficiently.

However, due to the fact that Arc::<[MaybeUninit<T>]> is still unstable, there is no way to implement HeapString efficiently without first creating a String, then copy it onto the buffer and deallocate the original String.

It seems that the compiler may not be able to optimize these calls, especially with std::format! calling format.

Signed-off-by: Jiahao XU [email protected]

@ParkMyCar
Copy link
Owner

Thanks for the PR!

I really like the idea of a ToCompactStr trait. But you're right, without the nightly compiler we can't do this very efficiently. The HeapString representation will be changing soon, see #12, I plan to spend some time on it this weekend. Let's hold off on landing this until we make the changes to HeapString

@NobodyXu
Copy link
Contributor Author

NobodyXu commented Oct 1, 2021

Sure, I will wait for #12

@ParkMyCar
Copy link
Owner

Hey @NobodyXu, now that CompactStr is more stable, would you want to take another shot at this?

I think the idea of a ToCompactStr trait is great, I'm a bit apprehensive of manually implementing it for any type that implements Display though because of performance. Maybe we could define the trait, and then manually implement for a few common types like all the number types (e.g. u8, isize, f32, etc), and then maybe bool and char? IMO that would go a fairly long way for common use cases, what do you think?

For efficiently converting number types to strings take a look at itoa and ryu

@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 1, 2022

Hey @NobodyXu, now that CompactStr is more stable, would you want to take another shot at this?

Yes, sure.

I think the idea of a ToCompactStr trait is great, I'm a bit apprehensive of manually implementing it for any type that implements Display though because of performance. Maybe we could define the trait, and then manually implement for a few common types like all the number types (e.g. u8, isize, f32, etc), and then maybe bool and char? IMO that would go a fairly long way for common use cases, what do you think?

Hmmm, I don't like the idea of implementing only for common types, as it would make ToCompactStr less useful and
provide different semantics compared to ToString.

For common number types, maybe we can provide a optional specialization for them using
castaway and gate it using a feature flag?

@ParkMyCar
Copy link
Owner

ParkMyCar commented Apr 1, 2022

Hmmm, I don't like the idea of implementing only for common types, as it would make ToCompactStr less useful and
provide different semantics compared to ToString.

Fair enough, that makes sense to me!

Ugh I wish specialization was stable. Regardless, castaway looks pretty cool, let's give it a shot!

@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 3, 2022

Hmmm, I don't like the idea of implementing only for common types, as it would make ToCompactStr less useful and
provide different semantics compared to ToString.

Fair enough, that makes sense to me!

Ugh I wish specialization was stable. Regardless, castaway looks pretty cool, let's give it a shot!

I am quite busy recently, so it might take me some time to implement it.

@NobodyXu NobodyXu closed this Apr 3, 2022
Signed-off-by: Jiahao XU <[email protected]>
@NobodyXu NobodyXu reopened this Apr 3, 2022
@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 3, 2022

Sorry I accidentally closed this PR, now it is reopened.

@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 3, 2022

@ParkMyCar I have implemented trait ToCompactStr without specialisation using castaway.

I will implement the specialisation later, but now you can probably start looking at my code and providing me with feedback so that we can ensure the implementation is correct before doing any optimization.

Copy link
Owner

@ParkMyCar ParkMyCar left a comment

Choose a reason for hiding this comment

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

Thanks for doing this work!

compact_str/src/lib.rs Outdated Show resolved Hide resolved
compact_str/src/lib.rs Outdated Show resolved Hide resolved
compact_str/src/lib.rs Outdated Show resolved Hide resolved
compact_str/src/utility.rs Outdated Show resolved Hide resolved
Impl new function `InlineString::from_fmt` to avoid copying the buffer
for `InlineString`.

Signed-off-by: Jiahao XU <[email protected]>
into `InlineString::from_fmt`

Signed-off-by: Jiahao XU <[email protected]>
Instead of using `std::io::Cursor`.

Signed-off-by: Jiahao XU <[email protected]>
`[u8; _]::as_mut_slice` is only present in rust >= 1.57.0

Signed-off-by: Jiahao XU <[email protected]>
@NobodyXu NobodyXu requested a review from ParkMyCar April 7, 2022 03:42
@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 7, 2022

For efficiently converting number types to strings take a look at itoa and ryu

I am doubtful on using ryu as it might give different output compared to the builtin format!, I think this might break some code.

@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 7, 2022

Hmmm, I don't like the idea of implementing only for common types, as it would make ToCompactStr less useful and
provide different semantics compared to ToString.

Fair enough, that makes sense to me!

Ugh I wish specialization was stable. Regardless, castaway looks pretty cool, let's give it a shot!

I just realized that castaway requires the type to be of 'static lifetime due to std::any::TypeId::of requires static lifetime, which is impossible to use within ToCompactStr.

I am now thinking of adding another trait FromBuiltinTypes.

It is just unfortunate that Rust doesn't have specialisation stabilised.

@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 8, 2022

I also asked the question sagebind/castaway#5 on castaway to see if there is any alternative solution.

Edit:

Turns out it is actually feasible sagebind/castaway#6

@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 21, 2022

Hmmm, I don't like the idea of implementing only for common types, as it would make ToCompactStr less useful and
provide different semantics compared to ToString.

Fair enough, that makes sense to me!
Ugh I wish specialization was stable. Regardless, castaway looks pretty cool, let's give it a shot!

I just realized that castaway requires the type to be of 'static lifetime due to std::any::TypeId::of requires static lifetime, which is impossible to use within ToCompactStr.

I am now thinking of adding another trait FromBuiltinTypes.

It is just unfortunate that Rust doesn't have specialisation stabilised.

With sagebind/castaway#6 merged in and released as https://github.com/sagebind/castaway/releases/tag/0.2.0, this is no longer an issue.

I will continue my work on specialisation for ToCompactStr.

`castaway::cast!` cannot cast reference of `T: ?Sized` to primitive
types

Signed-off-by: Jiahao XU <[email protected]>
Use `Sink(0)` directly to make optimization easier.

Signed-off-by: Jiahao XU <[email protected]>
to avoid using macro `count!` in `Repr::from_fmt`, which uses
`core::format_args!`, making it harder to optimize.

Signed-off-by: Jiahao XU <[email protected]>
For `LifetimeFree` impl for `NonZeroUsize`.

Signed-off-by: Jiahao XU <[email protected]>
Test different float values in the same `assert_eq` so that if one
`assert_eq`, we can obtain value of the formatting of all float values
we provided.

Signed-off-by: Jiahao XU <[email protected]>
@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 23, 2022

I just tried to reproduce this on my own x86_64 linux box by running:

cross +nightly test --release --all-features --manifest-path=compact_str/Cargo.toml --target powerpc-unknown-linux-gnu

however, all tests passed without problem...

Sorry I used the wrong command.

Copy link
Owner

@ParkMyCar ParkMyCar left a comment

Choose a reason for hiding this comment

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

Thanks for all the work here @NobodyXu! I've been pretty busy lately so haven't had a chance to look super in-depth, but I think we're getting close!

.github/workflows/msrv.yml Outdated Show resolved Hide resolved
compact_str/Cargo.toml Outdated Show resolved Hide resolved
compact_str/src/repr/inline.rs Outdated Show resolved Hide resolved
compact_str/src/lib.rs Outdated Show resolved Hide resolved
compact_str/src/tests.rs Outdated Show resolved Hide resolved
Instead of calling `Repr::from_fmt`, then forward it to
`Inline::from_fmt` or formatting into preallocated `String`,
this commit uses `CompactStr::with_capacity` to preallocate required
space ahead of time to avoid repeated heap allocation and copying, then
use `fmt::Write` implementation for `CompactStr` to format value into
the `CompactStr` with preallocated space.

Signed-off-by: Jiahao XU <[email protected]>
 - Module `io` only present in `std`, while `fmt` present in `core`.
 - `io::Write` requires additional `flush` method to be implemented.
 - `io::Write::write` requires the len of bytes written to be returned.

Signed-off-by: Jiahao XU <[email protected]>
by implementing `fmt::Write::write_char`

Signed-off-by: Jiahao XU <[email protected]>
To make this PR easier to review.

Signed-off-by: Jiahao XU <[email protected]>
Copy link
Owner

@ParkMyCar ParkMyCar left a comment

Choose a reason for hiding this comment

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

Thanks for all the hard work here @NobodyXu and making all the changes I asked for!

Looks like there's just one failing test on PowerPC Little Endian with float formatting? If we can fix the test that would be great, otherwise I'm fine with ignoring it. Once you make that change we can merge!

Thanks again for all the work! 🙂

@NobodyXu
Copy link
Contributor Author

NobodyXu commented Apr 25, 2022

Looks like there's just one failing test on PowerPC Little Endian with float formatting? If we can fix the test that would be great, otherwise I'm fine with ignoring it. Once you make that change we can merge!

Unfortunately that is a compiler bug rust-lang/rust#96306 which I cannot fix.

@ParkMyCar I think this PR is ready for merging as the failure on powepc64le has nothing to do with this PR.

@ParkMyCar
Copy link
Owner

Merging, thanks @NobodyXu!

@ParkMyCar ParkMyCar merged commit ad93a70 into ParkMyCar:main Apr 26, 2022
@NobodyXu
Copy link
Contributor Author

NobodyXu commented May 2, 2022

@ParkMyCar Now that we have more unit tests and fuzzing added for ToCompactStr, maybe it is a good time to release a new minor version?

nottirb pushed a commit to nottirb/compact_str that referenced this pull request May 15, 2022
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.

3 participants