Open Bug 874174 Opened 11 years ago Updated 2 years ago

ClojureScript benchmark

Categories

(Core :: JavaScript Engine, defect)

x86
macOS
defect

Tracking

()

People

(Reporter: dherman, Unassigned)

References

(Blocks 1 open bug)

Details

(Keywords: perf)

Attachments

(1 file)

107.76 KB, application/x-javascript
Details
It'd be great to give ClojureScript more perf work, since they're exercising some interesting computational idioms (such as persistent data structures and functional update). We're not doing as well as we should on this benchmark:

http://jsperf.com/objmap-vs-persistentarraymap-assoc-7kv

Dave
Blocks: IonSpeed
No longer blocks: IonSpeed
Attached file Shell testcase
SM:

ObjMap: 209 ms.
PersistentArrayMap: 218 ms.

d8 from a few weeks/months ago:

ObjMap: 43 ms.
PersistentArrayMap: 24 ms.
So for the ObjMap part, we have a bunch of GC sweeping off on a background thread.  On the main thread, 65% of our time is under the js::SetObjectElement stubcall from ion.  Another 9% is js_Array.  And then some minor stuff with ion::DoUseCountFallback and refillFreeList.  And about 20% ion jitcode.

For the PersistentArrayMap part, the profile looks largely identical.

So why are we ending up in that stubcall?
(In reply to Boris Zbarsky (:bz) from comment #2)
> So why are we ending up in that stubcall?

What's happening is that we create an array of length 16 (using "Array(a)" where a == 16 99% of the time). Then that array is filled, but we have to reallocate the array elements multiple times (since they are allocated lazily). See the following micro-benchmark:

function f(x) {
    for (var i=0; i < 400000; i++) {
	var arr = Array(x);
        for (var j = 0; j < x; j++) {
            arr[j] = j;
        }
    }
}
var t = new Date;
f(16);
print(new Date - t);

SM: 352 ms
d8:  21 ms

Generational GC should help here, since we will be able to allocate the elements in the nursery instead of going through the (much slower) malloc/realloc.

More importantly, we should allocate dense elements more eagerly, so that we don't have to reallocate at all, see bug 799122. v8 is doing this already.

With the patch in that bug, I get 118 ms for the micro-benchmark, and numbers for the attached shell benchmark:

ObjMap: 82 ms.
PersistentArrayMap: 92 ms.

So that closes most of the gap, the rest is Generational GC (fast allocation + GC) and inlining Array(x) where x is not a constant.
Depends on: 799122
Depends on: GenerationalGC
With the patch in bug 799122, what is the perf on the ClojureScript benchmark in comment 1?
(In reply to Luke Wagner [:luke] from comment #4)
> With the patch in bug 799122, what is the perf on the ClojureScript
> benchmark in comment 1?

It's in comment 3, but to summarize:

SM before:

ObjMap: 209 ms.
PersistentArrayMap: 218 ms.

SM + bug 799122:

ObjMap: 82 ms.
PersistentArrayMap: 92 ms.

d8:

ObjMap: 43 ms.
PersistentArrayMap: 24 ms.
Oops, sorry, I misread comment 3.  Thanks!
Assignee: general → nobody
It would be good to know if we match v8 now.
Flags: needinfo?(jdemooij)
(In reply to Tom Schuster [:evilpie] from comment #7)
> It would be good to know if we match v8 now.

SM:

ObjMap: 34 ms.
PersistentArrayMap: 33 ms.

d8:

ObjMap: 34 ms.
PersistentArrayMap: 20 ms.

So ObjMap is now as fast as V8, PersistentArrayMap is still slower (but way faster than before).

Bug 1100513 improved this a lot, but we now spend a lot of time (> 40%) in js::ArrayConstructorOneArg. This is from an Array(x) where x is always 16. Now with GGC, Ion should be able to allocate external elements inline...
Depends on: 1100513
Clearing the NI but leaving the bug open. We're no longer embarrassingly slow. The optimization in comment 8 would be nice and would likely make us faster than V8, hopefully I can get to this in a few months.
Flags: needinfo?(jdemooij)
Keywords: perf
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.