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

refactor(3230): remove curryX dependency for internal transducer creator functions #3231

Merged
merged 2 commits into from
Mar 6, 2022

Conversation

xgbuils
Copy link
Contributor

@xgbuils xgbuils commented Feb 7, 2022

From issue #3230

Notice that now transducer creator functions just depend on themselves after removing curryX functions. This could facilitate ramda modularity because now it's easier to create a library that works just with transducers without rely in other parts of the library.

Copy link
Member

@customcommander customcommander left a comment

Choose a reason for hiding this comment

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

I think I understand your motivation. If I understand correctly your thinking is that the internal functions don't need to be curried because they are never called with their full arguments and always with the same set. So we could optimise by currying ourselves basically.

I think this is perfectly sensible but I need to get my head around _dispatchable as this function seems key in order to conduct a review (at least for me).

Do you have an idea of how much we gain performance wise?

Overall I think this is pretty nice. Good catch!

source/dropRepeats.js Show resolved Hide resolved
@xgbuils
Copy link
Contributor Author

xgbuils commented Feb 8, 2022

I think this is perfectly sensible but I need to get my head around _dispatchable as this function seems key in order to conduct a review (at least for me).

I'm thinking deeply about it and I can say that technically it doesn't depends on _dispatchable it's more about how transducers work. Transducer implementations requires:

  • transducer creators: functions that return transducers
  • transducers: functions that receive a transformer and returns a transformer. They are the functions that can be composed applying a performant way of transformation over arrays, iterables and so on.
  • transformers: objects that implement @@transducer/init, @@transducer/step and @@transducer/result methods.

Because of composition of transducers we won't need another way of partial application over transducer creators. Then, it seems we will never need to wrap internal transducer creators with curryX functions.

Do you have an idea of how much we gain performance wise?

I'm not sure how to check it. I've seen tables with benchmarks in #3048 but I don't know how they were created. Is there a standard way to create benchmarks in this project?

Thanks

@customcommander
Copy link
Member

I'm thinking deeply about it and I can say that technically it doesn't depends on _dispatchable it's more about how transducers work. Transducer implementations requires:

Yep you're right. I mentioned _dispatchable because it deals with creating transducers too which is the codepath that most of your changes will exercise I think.

We recently had this issue reported #3232 which seems to be a regression in 0.28 and I know we touched that part of the code recently. Any chance your changes improve anything there? (Don't think so but I thought I'd ask anyway)

I'd like another review from a maintainer if that's ok.

@xgbuils
Copy link
Contributor Author

xgbuils commented Feb 8, 2022

We recently had this issue reported #3232 which seems to be a regression in 0.28 and I know we touched that part of the code recently. Any chance your changes improve anything there? (Don't think so but I thought I'd ask anyway)

OK, I have a solution for this issue. I can send a PR there. It's working too with this change.

@xgbuils
Copy link
Contributor Author

xgbuils commented Feb 13, 2022

Do you have an idea of how much we gain performance wise?

I've added these bench tests:

    //  filter.bench.js
    'into([], filter(isEven), nums)': function() {
      into([], filter(isEven), nums);
    },
    'into([], filterEven, nums)': function() {
      into([], filterEven, nums);
    },
    //  map.bench.js
    'into([], map(sq), nums)': function() {
      into([], map(sq), nums);
    },
    'into([], mapSq, nums)': function() {
      into([], mapSq, nums);
    },

Original benchmarks:

┌────────────────────────┬────────────────────────┬────────────────────────┐
│ filter                 │ Hertz                  │ Margin of Error        │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ filter(isEven, nums)   │ 7,627,059              │ 0.77%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ filter(isEven)(nums)   │ 1,889,646              │ 2.87%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ filterEven(nums)       │ 2,230,079              │ 2.80%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ into([], filter(isEve… │ 350,420                │ 0.57%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ into([], filterEven, … │ 362,084                │ 0.69%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ native filter          │ 9,576,447              │ 0.14%                  │
└────────────────────────┴────────────────────────┴────────────────────────┘
┌────────────────────────┬────────────────────────┬────────────────────────┐
│ map                    │ Hertz                  │ Margin of Error        │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ map(sq, nums)          │ 9,675,896              │ 2.79%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ map(sq)(nums)          │ 2,090,064              │ 0.42%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ mapSq(nums)            │ 2,561,379              │ 0.41%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ into([], map(sq), num… │ 358,597                │ 0.34%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ into([], mapSq, nums)  │ 359,507                │ 0.78%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ native map             │ 10,826,670             │ 0.37%                  │
└────────────────────────┴────────────────────────┴────────────────────────┘

With the change:

┌────────────────────────┬────────────────────────┬────────────────────────┐
│ filter                 │ Hertz                  │ Margin of Error        │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ filter(isEven, nums)   │ 8,391,643              │ 0.60%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ filter(isEven)(nums)   │ 1,902,025              │ 0.28%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ filterEven(nums)       │ 2,227,084              │ 1.13%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ into([], filter(isEve… │ 389,342                │ 0.38%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ into([], filterEven, … │ 402,658                │ 0.87%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ native filter          │ 10,478,337             │ 0.20%                  │
└────────────────────────┴────────────────────────┴────────────────────────┘
┌────────────────────────┬────────────────────────┬────────────────────────┐
│ map                    │ Hertz                  │ Margin of Error        │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ map(sq, nums)          │ 10,496,247             │ 0.61%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ map(sq)(nums)          │ 1,748,662              │ 6.52%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ mapSq(nums)            │ 2,351,095              │ 0.23%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ into([], map(sq), num… │ 383,266                │ 0.27%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ into([], mapSq, nums)  │ 387,048                │ 0.73%                  │
├────────────────────────┼────────────────────────┼────────────────────────┤
│ native map             │ 9,842,714              │ 0.61%                  │
└────────────────────────┴────────────────────────┴────────────────────────┘

Do you think it could be interesting to add in the PR for testing transducer approach performance?

Copy link
Member

@CrossEye CrossEye 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 sorry to be slow on this one. I keep going to it, and seeing 24 changed files -- having to do with transducers, which I was never really a part of -- and saying, "Well, no time now. I'll look later."

I finally dug in to realize how simple a change this is. It makes perfect sense to me. The boost in performance is nice, but the code simplification is its biggest advantage.

Very nice! 🌿

@CrossEye CrossEye merged commit 0108fd1 into ramda:master Mar 6, 2022
@adispring adispring mentioned this pull request Apr 7, 2023
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