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

Optimize even more #2

Open
Andarist opened this issue Apr 24, 2018 · 3 comments
Open

Optimize even more #2

Andarist opened this issue Apr 24, 2018 · 3 comments
Assignees
Labels
enhancement New feature or request

Comments

@Andarist
Copy link

You'd probably get even better results if you remove the function calls within loop. You have to be careful about inserted identifiers and such, but it should be fairly easy to generate this:

// Compiled with faster.js
const arr = [1, 2, 3];
const results = [];
for (let _i = 0; _i < arr.length; _i++) {
  results.push(2 * arr[_i]);
}

Maybe you could even preallocate results in case of .map based on arr.length, but aint sure what's better in majority of use cases. Maybe you could decide about this based on this comment from v8 team.

@vzhou842
Copy link
Owner

I thought about removing function calls, but inlining function bodies gets tricky. For example, consider this scenario:

let x = 1;
const f1 = a => a + x;
(() => {
	let x = 2;
	console.log([0, 1, 2].map(f1));
})();

Inlining f1 here would lead to incorrect results because of the redeclaration of x in the closure scope.

Your suggestion about preallocating results is a great idea, though! I ran the following benchmark:

[1, 5, 10, 16, 25, 50, 100, 200, 500, 1000].forEach(arrSize => {
	console.log(`> array size ${arrSize}`);

	const numLoops = 100000000 / arrSize;

	let start = Date.now();
	for (let i = 0; i < numLoops; i++) {
		const results = [];
		for (let j = 0; j < arrSize; j++) {
			results.push(Math.sqrt(j));
		}
	}
	const t1 = Date.now() - start;

	start = Date.now();
	for (let i = 0; i < numLoops; i++) {
		const results = new Array(arrSize);
		for (let j = 0; j < arrSize; j++) {
			results[j] = Math.sqrt(j);
		}
	}
	const t2 = Date.now() - start;

	console.log(`${t1} vs ${t2}`);
});

and got these results:

> array size 1
1948 vs 844
> array size 5
474 vs 301
> array size 10
378 vs 355
> array size 16
388 vs 375
> array size 25
489 vs 393
> array size 50
568 vs 440
> array size 100
599 vs 447
> array size 200
585 vs 454
> array size 500
593 vs 457
> array size 1000
639 vs 462

I'll go ahead and implement preallocation.

@Andarist
Copy link
Author

I thought about removing function calls, but inlining function bodies gets tricky.

Sure thing, but many cases could get optimized - especially inline arrow functions.

Your suggestion about preallocating results is a great idea, though!

According to what I understand this optimize creation but not necessarily future operations on the created array. Hard to tell what's better thouggh 🤷‍♂️ especially for a generic use case

@vzhou842
Copy link
Owner

Yeah you're right, arrow functions probably wouldn't be hard to inline + are pretty widely used.

Think I'm going to stick with preallocation for array-map, it may be true that some future ops on the array could be slower but IMO this is worth it for most cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants