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

[Perf] Reduce allocations when parsing Identifiers #2454

Merged

Conversation

ljedrz
Copy link
Contributor

@ljedrz ljedrz commented May 15, 2024

The Identifier is an object that gets parsed quite often; that process involves ensuring that it is not actually a LiteralType, and in order to do so, an attempt is made to parse the identifier as that object. However, this approach is quite wasteful due to the fact that it uses alt, which clones the given input for every member of its list until a hit is found, meaning we currently perform 17 redundant allocations every time the Identifier is valid.

Since we don't actually need to do true parsing here, we can instead perform a much simpler check that doesn't need to worry about advancing the parsed input, avoiding allocations. In a local run with 4 --dev nodes, this reduces the number of allocations/s in a validator node by ~26.5%.

The extra crate that was used, enum-iterator, is small, simple, and widely used in the ecosystem. A slightly less future-proof alternative would be to introduce a const list of all the variants of the LiteralType; the basic principle is the same.

Signed-off-by: ljedrz <ljedrz@gmail.com>
Signed-off-by: ljedrz <ljedrz@gmail.com>
Copy link
Contributor

@raychu86 raychu86 left a comment

Choose a reason for hiding this comment

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

I'm not too familiar with the enum-iterator APIs, but after looking at the docs, this looks correct.

@raychu86
Copy link
Contributor

On a related note:

The Parse impl for LiteralType uses fixed strings for parsing. It may be preferable to use the type_name there as well:

Before:

    fn parse(string: &str) -> ParserResult<Self> {
        // Parse the type from the string.
        alt((
            map(tag("address"), |_| Self::Address),
            map(tag("boolean"), |_| Self::Boolean),
            map(tag("field"), |_| Self::Field),
            map(tag("group"), |_| Self::Group),
            ...

After:

    fn parse(string: &str) -> ParserResult<Self> {
        // Parse the type from the string.
        alt((
            map(tag(Self::Address.type_name()), |_| Self::Address),
            map(tag(Self::Boolean.type_name()), |_| Self::Boolean),
            map(tag(Self::Field.type_name()), |_| Self::Field),
            map(tag(Self::Group.type_name()), |_| Self::Group),
            ...

Not sure if there are any performance hits from this.

@ljedrz
Copy link
Contributor Author

ljedrz commented May 20, 2024

Not sure if there are any performance hits from this.

There shouldn't be any; I'm happy to include this one change here or separately, in a refactor PR together with similar applications - your call.

@raychu86
Copy link
Contributor

It'd likely be better in a new PR 👍

@howardwu howardwu merged commit a471281 into AleoNet:mainnet-staging May 23, 2024
zosorock added a commit that referenced this pull request May 24, 2024
…type_parsing"

This reverts commit a471281, reversing
changes made to 757e5d5.
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.

None yet

3 participants