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

Disable Value.tag in release mode #448

Merged
merged 13 commits into from
Oct 26, 2024

Conversation

Alex-Fischman
Copy link
Contributor

@Alex-Fischman Alex-Fischman commented Oct 18, 2024

This PR adds #[cfg(debug_assertions)] to the tag field of the Value struct.
This is intended to be an optimization; it would get faster for a few reasons:

  • Less memory required for tables -> better cache locality
  • Values fit into registers so they might be faster to move around

Unfortunately, partial application of unstable-fns currently relies on Values containing tags, so I have disabled it.

@saulshanabrook
Copy link
Member

FYI partial application of functions is required for some Python use cases now, ... I can try to have a look to see if I can get it to work with these changes.

Copy link

codspeed-hq bot commented Oct 18, 2024

CodSpeed Performance Report

Merging #448 will improve performances by 13.96%

Comparing Alex-Fischman:cfg-tag (ef44dea) with main (b9f4c58)

Summary

⚡ 3 improvements
✅ 5 untouched benchmarks

Benchmarks breakdown

Benchmark main Alex-Fischman:cfg-tag Change
cykjson 342.9 ms 320.4 ms +7.02%
eggcc-extraction 4.3 s 4.1 s +5.11%
math-microbenchmark 4.1 s 3.6 s +13.96%

src/lib.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@yihozhang yihozhang left a comment

Choose a reason for hiding this comment

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

I like the performance improvement but I think we need to be careful about this PR, since this makes the user do more bookkeeping and their code will likely look more tedious. Can we provide wrapped value/value arrays to the user that has the type information? E.g.

type ValueImpl = usize // internal representation as proposed in this PR.
type Schema = Vec<ArcSort>
struct Value(ValueImpl, ArcSort) // the current Value interface that we provide to the user.
struct Tuple(&Schema, Vec<ValueImpl>) // a tuple (= a vec of values) with type information
struct QueryResult(&Schema, Vec<ValueImpl>) // represents a table (= a vec of tuples), but shares the same schema

This way we can avoid imposing burdens to the user while making our internal Value representation more compact. Thoughts?

@Alex-Fischman
Copy link
Contributor Author

Alex-Fischman commented Oct 19, 2024

I think this is best done when we implement a Rust API.

@Alex-Fischman
Copy link
Contributor Author

@saulshanabrook I believe that it is possible to implement partial application for functions under this PR, because function names are unique (unlike primitives). Is this good enough for your use case?

@saulshanabrook
Copy link
Member

Yeah If we have to drop supporting builtin primitives in the function interface it's not a deal breaker for me. I mainly included it to be comprehensive and for "principle of least surprise" in terms of the user experience.

@Alex-Fischman
Copy link
Contributor Author

@saulshanabrook For some reason I am not allowed to "acknowledge" regressions on CodSpeed? Is this a power that can be shared? (I would like to acknowledge "regressions" that come from the parser.)

Copy link
Collaborator

@yihozhang yihozhang left a comment

Choose a reason for hiding this comment

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

Left some comments. Earlier I proposed that we avoid making our APIs harder to use by exposing to the user a wrapped Value struct that has the type information (which is essentially the old Value). It will make this PR a pure performance optimization. Are you planning to address that in this PR? Some instances include, for all of our pub fn that return a Value, letting it return a wrapped Value

src/lib.rs Show resolved Hide resolved
src/unionfind.rs Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
@Alex-Fischman
Copy link
Contributor Author

Some instances include, for all of our pub fn that return a Value, letting it return a wrapped Value

Are there instances of this other than eval_lit? (There's find but you now have to pass a sort in so it seems unnecessary.) I can do this if you really feel strongly but it does feel like unnecessary repetition to me.

@saulshanabrook
Copy link
Member

Not that anyone was asking, but just FYI there is once place in the egglog bindings I deal more directly with values by evaling primitive expressions into their values. I wanted to note that I plan on removing this and just doing "eval" of primitive expressions at the Python level by looking at the AST. So just that from the Python side, we aren't using values at all.

@saulshanabrook
Copy link
Member

Could we remove tags from all modes instead of just in release mode? (to clean up the code a bit)

@yihozhang
Copy link
Collaborator

Are there instances of this other than eval_lit? (There's find but you now have to pass a sort in so it seems unnecessary.) I can do this if you really feel strongly but it does feel like unnecessary repetition to me.

I'm thinking about the interface of at least extract, eval_expr, and inner_values. Let's talk more offline about what I meant. Maybe a more radical version of my proposal is to make the Value definition in this PR pub(crate).

@Alex-Fischman
Copy link
Contributor Author

Conclusion from in-person discussion: this API change is better done in another PR since it touches functions that are unrelated to this optimization

Copy link
Collaborator

@yihozhang yihozhang 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 going to approve this PR since it seems the only thing we disagree on is whether an Id should be a u64 or a wrapper of u64. Two things to consider in the future:

  • API change so that users don't need to do bookkeeping around types
  • Change value.tag from Symbol to ArcSort

@Alex-Fischman Alex-Fischman merged commit 2e16561 into egraphs-good:main Oct 26, 2024
5 checks passed
@Alex-Fischman Alex-Fischman deleted the cfg-tag branch October 26, 2024 00:11
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