Improve j2me.js Klass Constructor Performance




JavaScript Engine
3 years ago
2 years ago


(Reporter: mbx, Unassigned)


Firefox Tracking Flags

(Not tracked)



(1 attachment)

4.19 KB, application/x-javascript


3 years ago
Created attachment 8581171 [details]

j2me.js generates initializer functions for every Java class that initialize fields to their default values. The usual format is:

function Foo () {
  this.f0 = 0;
  this.f1 = 0;
  this.f2 = null;
  this.f3 = 0;

At the moment, we generate and eval these functions at runtime. This however, is fairly slow, especially during startup.

I've attached a benchmark that uses 5 different ways of accomplishing the same thing. On my machine the results are:

Klasses with (1, eval)
Generete 2000 Klasses: 24.0927734375
Construct 200000 Klass Instances: 705.926025390625

Klasses with new Function()
Generete 2000 Klasses: 19.496826171875
Construct 200000 Klass Instances: 686.377197265625

Klasses with closures.
Generete 2000 Klasses: 0.600830078125
Construct 200000 Klass Instances: 985.54296875

Klasses with closures and field arrays.
Generete 2000 Klasses: 0.68896484375
Construct 200000 Klass Instances: 307.618896484375

Klasses with (1, eval) and field arrays.
Generete 2000 Klasses: 19.511962890625
Construct 200000 Klass Instances: 961.655029296875

For the most part the numbers make sense. What surprises me is the last result. Why would it be slower to access the fields of an object constructed with eval? Especially, when the first approach is faster than the 3rd. (Hopefully, this is not caused by a GC).

Any ideas on how to improve the generation of Java class constructors?


3 years ago
Flags: needinfo?(jdemooij)
(In reply to Michael Bebenita [:mbx] from comment #0)
> For the most part the numbers make sense. What surprises me is the last
> result. Why would it be slower to access the fields of an object constructed
> with eval?

I looked at the last one. Unfortunately it's not very representative, but some comments:

(1) "new Int32Array(5)" is pretty slow atm, because Int32Array has to lookup the calling script, then do a hashtable lookup to get the ObjectGroup based on that allocation site. We should optimize this, but in a profile I see we spend a lot of time there. Apparently the 2000 constructors slow down this hashtable lookup.

(2) "new klass()" is mega-morphic and not optimized well. Each of those constructors has its own ObjectGroup, and our TypeSets can't track 2000 groups so we deoptimize.

This makes the "new klass()" itself + the "k.a[0]++;" accesses slower. For the ++ it's especially the set part that's slow, it's hard to use IC's there because we have to ensure our heap types are sound when we store properties. Gets don't have this problem and there we can use ICs and shape guards.

(3) I'd recommend Function instead of eval, as the second test does. The "Int32Array" name lookup in the constructor within the eval isn't fast right now, that's bug 1146080.
Flags: needinfo?(jdemooij)
As Bill Walker notes in bug 1177394, comment 24, he has directed his engineering team to stop work on RunWhatsApp in favor of our new focus on progressive web apps.  So the PluotSorbet project (née j2me.js) is moribund, and this is no longer a priority for us.  Thus I'm resolving it incomplete; but feel free to reopen it if you still want to use it to track some general perf improvement.
Last Resolved: 2 years ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.