- Notifications
You must be signed in to change notification settings - Fork 7
Optimize allocations #128
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 allocations #128
Conversation
7c8e82a to 94dccaa Compare | if (js.typeOf(js.Dynamic.global.setImmediate) == Undefined) { | ||
| var nextHandle = 1 | ||
| val tasksByHandle = mutable.Map[Int, () => Unit]() | ||
| val tasksByHandle = new HashMap[Int, Runnable] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is going to reach ju.HashMap for every Scala.js codebase that uses this library, potentially increasing code size. Have you considered using a plain old JS object instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, that's what the upstream does.
https://github.com/YuzuJS/setImmediate/blob/f1ccbfdf09cb93aadf77c4aa749ea554503b9234/setImmediate.js#L9C9-L9C22
5ded57b to 643145f Compare | } | ||
| | ||
| case None => | ||
| val task = tasksByHandle(handle).asInstanceOf[js.UndefOr[Runnable]] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure you need tasksByHandle.selectDynamic(handle) here. As is, you're calling tasksByHandle with handle as an argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right ... messed up the refactor from an initial try with @BracketAccess. But selectDynamic requires a string, so going to try @BracketAccess again
| if (task.isDefined) { | ||
| currentlyRunningATask = true | ||
| try { | ||
| task.asInstanceOf[Runnable].run() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you're going to cast here anyway, using js.UndefOr only to get isDefined is more trouble than it's worth. You can use js.isUndefined(task) instead.
| nextHandle += 1 | ||
| | ||
| tasksByHandle += (handle -> k) | ||
| tasksByHandle(handle) = k.asInstanceOf[js.Any] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here (and below as well) you'll need updateDynamic.
643145f to 84b4dee Compare | } | ||
| | ||
| case None => | ||
| val task = tasksByHandle(handle) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With tasksByHandle(handle) now returning a Runnable, there will be an implicit cast to Runnable here that will CCE when it's undefined.
With a custom TaskMap (which really makes sense, btw), you'll get a better mileage by having the apply return a js.UndefOr[Runnable]. Then you could actually just call foreach on it, and you won't need the cast further down. Seems like a win overall.
I wonder how we could better test that each code path actually works. The code paths that are polyfilling really old stuff are under-tested, it seems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder how we could better test that each code path actually works. The code paths that are polyfilling really old stuff are under-tested, it seems.
Actually, I think the reason we are not hitting the CCE in the undefined case is because it's impossible for us. I don't think we need to consider this case at all.
It was cargo-culted from the upstream, but the upstream also implements clearImmediate.
https://github.com/YuzuJS/setImmediate/blob/f1ccbfdf09cb93aadf77c4aa749ea554503b9234/setImmediate.js#L31-L33
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah ah! That makes sense. In that case the logic looks good now. We should rename runIfPresent to run, though. Otherwise the next poor soul coming here will be confused.
5942ce0 to 1abfea2 Compare 1abfea2 to af120b0 Compare
Runnableas() => UnitMapandOption-basedgetwith an ordinaryjs.Object