Skip to content

Reduce LfnBuffer size from 24 to 16 bytes on 32-bits sys.#218

Merged
thejpster merged 3 commits intorust-embedded-community:developfrom
Conaclos:conaclos/lfnbuffer-reduce-size
Jan 23, 2026
Merged

Reduce LfnBuffer size from 24 to 16 bytes on 32-bits sys.#218
thejpster merged 3 commits intorust-embedded-community:developfrom
Conaclos:conaclos/lfnbuffer-reduce-size

Conversation

@Conaclos
Copy link
Contributor

@Conaclos Conaclos commented Jan 22, 2026

  • Reduce LfnBuffer size from 24 to 16 bytes on 32-bits sys.
  • Reduce LfnBuffer size from 32 to 24 bytes on 64-bits sys.

The reduction comes from the observation that the required buffer doesn't need to exceed the maximum bytes required to represent a LFN. A LFN has at most 255 UTF-16 characters. The buffer holds UTF-8 characters. A UTF-8 character takes at most 3 bytes. So, the buffer doesn't need to exceed 255*3 bytes. Thus, free can be stored in a u16.

To avoid a breaking change, the buffer is sliced in order to retain at most u16::MAX bytes.

Note that the optimization could go beyond, however this could become too complex IMO.

@Conaclos Conaclos force-pushed the conaclos/lfnbuffer-reduce-size branch from edee1b9 to 15a996b Compare January 22, 2026 23:00
And from 32 bytes to 24 bytes on 64bits systems.

The reduction comes from the observation that the required buffer
doesn't need to exceed the maximum bytes required to represent a lfn.
A lfn has at most 255 UTF-16 characters.
The buffer holds UTF-8 characters.
A UTF-8 character takes at most 3 bytes.
So, the buffer doesn't need to exceed 255*3 = 765 bytes.
Thus, `free` can be stored in a u16.

To avoid a breaking change, we accept buffer larger than u16::MAX
and just slice it to retain at most u16::MAX bytes.

Note that the optimization could go beyond by replacing `inner` with
a pointer to the data and storing the length in a u16.
`unpaired_surrogate` could also be a `Option<NonZeroU16>` because
`0` is not a valid surrogate character.
Finally we could encode the `overflow` bool in the msb of `free`.
All these optimizations make the code too complex IMO.
@thejpster
Copy link
Member

Thank you for the PR. Looking at this, I think I can just about justify the complexity for the memory saving. But perhaps you could add a function like:

fn free(&self) -> usize {
    usize::from(self.free)
}

That would avoid the need to do so many u16 to usize conversions in the code.

Have you found the eight byte saving to be significant in your application?

@Conaclos
Copy link
Contributor Author

Conaclos commented Jan 23, 2026

Have you found the eight byte saving to be significant in your application?

The gain is not significative at an application level. However, I thought it was a good tradeoff between complexity/gain. If you think it is not worth the complexity, feel free to reject it :)

@thejpster thejpster added this pull request to the merge queue Jan 23, 2026
Merged via the queue into rust-embedded-community:develop with commit 8d30ebc Jan 23, 2026
7 checks passed
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.

2 participants