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

wip: use arena-style cache when simplifying Expressions (DO NOT MERGE) #276

Draft
wants to merge 6 commits into
base: simplify-by-hand
Choose a base branch
from

Conversation

Shadow53
Copy link
Contributor

@Shadow53 Shadow53 commented Aug 9, 2023

This PR is meant as a reference and not to be merged (yet).

It is based on @genos' simplify-by-hand branch and attempts to improve performance by using an arena-based cache during Expression simplification.

Some internal benchmarks seem to show a good improvement (~17%) in runtime when the cache is actually useful, but an overhead of 1-5% when not useful (no repeated expressions). This may be conflated with the item below, which also helps performance -- I did not benchmark them separately.

One thing that may be useful enough to pull into its own PR is the change to not use hashing in the implementation of PartialEq for Expression, which also helps speed things up.

@Shadow53 Shadow53 marked this pull request as draft August 9, 2023 20:19
b.hash(state);
}
//InfixOperator::Plus | InfixOperator::Star => {
// // commutative, so put left & right in decreasing order by hash value
Copy link
Contributor

@genos genos Aug 9, 2023

Choose a reason for hiding this comment

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

I agree that this is costly, but we put it in for #27. Are we deciding to no longer ensure that, e.g., 1 + x == x + 1?

Copy link
Contributor

Choose a reason for hiding this comment

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

Alternatively, should we just derive Hash, PartialEq, and Eq and call it a day?

Copy link
Contributor

Choose a reason for hiding this comment

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

In fact, I think this is the way to go. #27 only handles commutativity, but not other rules that lead to equality between expressions. Since we're simplifying expressions with these rules, enforcing some but not all in the hashing & equality implementations seems wrong and wasteful. I'll open a new PR.

if let Ok(simpler) = simplification::run(self) {
*self = simpler;
}
let temp = std::mem::replace(self, Expression::PiConstant);
Copy link
Contributor

Choose a reason for hiding this comment

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

I really need to remember this trick 👍

genos pushed a commit that referenced this pull request Aug 10, 2023
BREAKING: Expressions no longer use hashing for implementing equality
BREAKING: Expression equality no longer takes commutativity into account

In #276, @Shadow53 noted

> One thing that may be useful enough to pull into its own PR is the
> change to not use hashing in the implementation of `PartialEq` for
> `Expression`, which also helps speed things up.

We originally put this together in #27 to ensure that equality held in
the face of commutativity, e.g., `1 + x == x + 1`. In addition to the
performance benefits of decoupling the hashing and equality
implementations, it makes sense to remove any special status for
commutative operations in light of all the work we're doing on
expression simplification. If we wished to ensure expressions are
`Eq` if and only if they represent the same mathematical expression,
we'd have to have equality contingent upon simplification, which would
be even more costly.
genos added a commit that referenced this pull request Aug 10, 2023
* feat!: Decouple expression hashing and equality

BREAKING: Expressions no longer use hashing for implementing equality
BREAKING: Expression equality no longer takes commutativity into account

In #276, @Shadow53 noted

> One thing that may be useful enough to pull into its own PR is the
> change to not use hashing in the implementation of `PartialEq` for
> `Expression`, which also helps speed things up.

We originally put this together in #27 to ensure that equality held in
the face of commutativity, e.g., `1 + x == x + 1`. In addition to the
performance benefits of decoupling the hashing and equality
implementations, it makes sense to remove any special status for
commutative operations in light of all the work we're doing on
expression simplification. If we wished to ensure expressions are
`Eq` if and only if they represent the same mathematical expression,
we'd have to have equality contingent upon simplification, which would
be even more costly.

* fix: Use Self::
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