Skip to content

Conversation

@jacoscaz
Copy link
Collaborator

@jacoscaz jacoscaz commented Mar 24, 2022

While researching #44 , @jeswr discovered that the performance of .map() and .filter() could be greatly improved by adding simple dedicated iterators for mapping and filtering, respectively. The impact of using these simplified iterators grows with the length of the chain of iterators.

As measured on a 13'' 2020 MacBook Pro (Apple Silicon, M1, 16 GB RAM), this PR makes the following test run in ~30ms. Before this PR the same test would terminate after ~300ms - a 10x difference.

let i = 0;
const arr = new Array(200000).fill(true).map(() => i++);

class RangeIterator<O> extends AsyncIterator<O> {
  constructor(source: O[]) {
    super();
    let i = 0;
    let l = source.length;
    this.read = (): O | null => {
      if (i >= l) {
        this.close();
        return null;
      }
      return source[i++];
    };
    Promise.resolve().then(() => {
      this.emit('readable');
    });
  }
}

const iterator = new RangeIterator(arr)
  .map((item: number) => item)
  .map((item: number) => item)
  .map((item: number) => item)
  .map((item: number) => item)
  .map((item: number) => item)
  .map((item: number) => item)
  .map((item: number) => item)
  .map((item: number) => item)
  .map((item: number) => item)
  .map((item: number) => item);

const now = Date.now();
iterator.on('data', () => {}).on('end', () => {
  console.log('elapsed', Date.now() - now);
});

Note that the RangeIterator class is just a stopgap for #47 .

@jacoscaz jacoscaz changed the title Simpler and faster filtering and mapping Simpler and faster filtering, mapping, filtering and limiting Mar 24, 2022
@jacoscaz jacoscaz changed the title Simpler and faster filtering, mapping, filtering and limiting Simpler and faster filtering, mapping, skipping and limiting Mar 24, 2022
@jacoscaz
Copy link
Collaborator Author

@RubenVerborgh if you like where this is going I can spend some time refining those new iterators (cleaning up event handlers, implementing read() as an actual class method, ...).

@RubenVerborgh
Copy link
Owner

if you like where this is going I can spend some time refining those new iterators (cleaning up event handlers, implementing read() as an actual class method, ...).

@jacoscaz Yes please. However, is this still relevant after #50?

@jacoscaz
Copy link
Collaborator Author

#50 is still about TransformIterator, which extends BufferedIterator. The gains in #46 will make the impact of this PR less significant for sure but there should still be a difference between buffering and no buffering. I'll do some comparison between the state of things now that #46 has been merged and this PR (and also #49 ) and report back.

@coveralls
Copy link

coveralls commented Mar 26, 2022

Coverage Status

Coverage remained the same at 100.0% when pulling d7ab7d9 on jacoscaz:faster-filtering-mapping into 8b01b5e on RubenVerborgh:main.

@jacoscaz
Copy link
Collaborator Author

jacoscaz commented Mar 26, 2022

With main as it is right now, after merging #46 , going through the following chain takes ~210 ms with an array of 200k items (MacBook Pro, Apple Silicon, M1, 16 GB RAM). With this PR that goes down to ~30 ms, so roughly 7x faster.

new ArrayIterator(arr)
      .map((item: number) => item)
      .map((item: number) => item)
      .map((item: number) => item)
      .map((item: number) => item)
      .map((item: number) => item)
      .map((item: number) => item)
      .map((item: number) => item)
      .map((item: number) => item)
      .map((item: number) => item)
      .map((item: number) => item)

@jacoscaz
Copy link
Collaborator Author

@RubenVerborgh this should be in a better place now. Those new iterators likely deserve dedicated tests but before that, should anything more be done In _destroy() when it comes to event handling?

@jeswr jeswr mentioned this pull request Mar 27, 2022
@jacoscaz
Copy link
Collaborator Author

This PR now includes @jeswr work from #53 , focused on combining subsequent map() and filter() operations into one single iterator.

@jacoscaz
Copy link
Collaborator Author

Superseded by #57

@jacoscaz jacoscaz closed this Mar 30, 2022
@jacoscaz jacoscaz deleted the faster-filtering-mapping branch May 9, 2022 08:52
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.

4 participants