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

runtime: fix useArrowFunction and noArguments #1682

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

smorimoto
Copy link
Member

Note: this partially introduces ES6!

runtime/jslib.js Outdated Show resolved Hide resolved
var len = Math.min(arguments.length, arity);
for (var i = 0; i < len; i++) args[i] = arguments[i];
return (...args) => {
args.length = arity;
Copy link
Member Author

Choose a reason for hiding this comment

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

You can use this trick to change the length of an array. I will comment the benchmark later.

Copy link
Member Author

@smorimoto smorimoto Sep 25, 2024

Choose a reason for hiding this comment

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

runtime/jslib.js Outdated Show resolved Hide resolved
@TyOverby
Copy link
Collaborator

This PR looks like it contains some formatting changes (using arrow functions) and also rewrites some of the most foundational primitives in the jsoo runtime. Could you split these up so that that latter can be thouroughly reviewed and benchmarked?

@TyOverby
Copy link
Collaborator

TyOverby commented Sep 25, 2024

Also, why are you interested in using arrow functions and avoid using arguments?

@smorimoto
Copy link
Member Author

Context Differences

  • The Arrow function inherits this from its parent. This may reduce the overhead of binding this by using the Arrow function.
  • The function function binds this to its own scope, so you must explicitly bind this to prevent unintended behaviour in situations where this is treated differently.

The arrow function has no binding processing, so you might see some performance improvement in this case. That said, you should not see much difference in general.

@TyOverby
Copy link
Collaborator

The function function binds this to its own scope, so you must explicitly bind this to prevent unintended behaviour in situations where this is treated differently.

Does this ever come up in jsoo?

@smorimoto
Copy link
Member Author

@TyOverby See runtime/fs_fake.js

@smorimoto
Copy link
Member Author

Also, why are you interested in using arrow functions and avoid using arguments?

arguments is not Array, it's ArrayLike, and converting it to Array has some cost. Also, newer JS engines have better optimisation for the rest parameter.

@smorimoto
Copy link
Member Author

The rest parameter and arguments show almost no difference in the benchmark results for major browsers: https://jsben.ch/BQEVR

@TyOverby
Copy link
Collaborator

arguments is not Array, it's ArrayLike, and converting it to Array has some cost

But Chrome is converting it to an array under the hood too. I benchmarked this a few years ago and found that using the spread operator had no impact on speed

@smorimoto
Copy link
Member Author

The rest parameter seems to be faster for many arguments: https://jsben.ch/Krmit

@smorimoto
Copy link
Member Author

arguments is not Array, it's ArrayLike, and converting it to Array has some cost

But Chrome is converting it to an array under the hood too. I benchmarked this a few years ago and found that using the spread operator had no impact on speed

It's true, but it has a certain advantage here because it simplifies the runtime code. If we are going to introduce const/let, ES6 is required, and if we don't see any performance regression, I think we can consider this kind of change positively.

@TyOverby
Copy link
Collaborator

The rest parameter and arguments show almost no difference in the benchmark results for major browsers: https://jsben.ch/BQEVR

On my machine at least, the new code is reliably 4% slower.

The rest parameter seems to be faster for many arguments: https://jsben.ch/Krmit

I think we should prioritize calling functions that have a small number of arguments, as small-arity functions are more common in OCaml than functions with 100+ parameters.

It's true, but it has a certain advantage here because it simplifies the runtime code. If we are going to introduce const/let, ES6 is required, and if we don't see any performance regression, I think we can consider this kind of change positively.

I modified your benchmark so that the arrays aren't empty, and to do some fast computation with them instead of logging (logging is slow, and mucks with benchmark results), and this new benchmark shows that even for 100-parameter calls, the old method is twice as fast (on Chrome at least) than using the new syntax: https://jsben.ch/sGBgk

@smorimoto
Copy link
Member Author

I modified your benchmark so that the arrays aren't empty, and to do some fast computation with them instead of logging (logging is slow, and mucks with benchmark results), and this new benchmark shows that even for 100-parameter calls, the old method is twice as fast (on Chrome at least) than using the new syntax: https://jsben.ch/sGBgk

I'm seeing a strange result 🤔 (I'm also on the latest Chrome btw)

image

@TyOverby
Copy link
Collaborator

Yeah, very strange.
Screenshot from 2024-09-26 12-54-30

@smorimoto
Copy link
Member Author

I ran it on the latest Chrome with Apple Silicon. What's your environment?

@smorimoto
Copy link
Member Author

Here is the result from Safari on the latest iOS:
IMG_0344

@TyOverby
Copy link
Collaborator

I ran it on the latest Chrome with Apple Silicon. What's your environment?

Latest Chrome x86-64

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants