ClojureScript

Map entry much slower for first

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Patch:
    Code

Description

If you do apply first to the result of getting an entry from a map, things are now slower.

Before: (https://github.com/clojure/clojurescript/commit/9ddd356d344aa1ebf9bd9443dd36a1911c92d32f)

Benchmarking with V8
[me (first {:a 1})], (first me), 10000000 runs, 267 msecs
Benchmarking with SpiderMonkey
[me (first {:a 1})], (first me), 10000000 runs, 378 msecs
Benchmarking with JavaScriptCore
[me (first {:a 1})], (first me), 10000000 runs, 406 msecs
Benchmarking with Nashorn
[me (first {:a 1})], (first me), 10000000 runs, 2232 msecs
Benchmarking with ChakraCore
[me (first {:a 1})], (first me), 10000000 runs, 1204 msecs

After: (https://github.com/clojure/clojurescript/commit/91431bd556f7a11db59319fcc082737a448f651e)

Benchmarking with V8
[me (first {:a 1})], (first me), 10000000 runs, 1106 msecs
Benchmarking with SpiderMonkey
[me (first {:a 1})], (first me), 10000000 runs, 720 msecs
Benchmarking with JavaScriptCore
[me (first {:a 1})], (first me), 10000000 runs, 689 msecs
Benchmarking with Nashorn
[me (first {:a 1})], (first me), 10000000 runs, 6711 msecs
Benchmarking with ChakraCore
[me (first {:a 1})], (first me), 10000000 runs, 1969 msecs

Activity

Hide
Mike Fikes added a comment -

By creating an IndexedSeq. on a 2-element JavaScript array in the -seq implementation, we can regain most of the perf that we had with the prior implementation where map entries were 2-element persistent vectors:

After the patch is applied:

Benchmarking with V8
[me (first {:a 1})], (first me), 10000000 runs, 294 msecs
Benchmarking with SpiderMonkey
[me (first {:a 1})], (first me), 10000000 runs, 503 msecs
Benchmarking with JavaScriptCore
[me (first {:a 1})], (first me), 10000000 runs, 491 msecs
Benchmarking with Nashorn
[me (first {:a 1})], (first me), 10000000 runs, 5304 msecs
Benchmarking with ChakraCore
[me (first {:a 1})], (first me), 10000000 runs, 1390 msecs

While this helps with seq, first, and second, this also really helps a lot if code happens to call nth on the resulting seq.

The patch applies the change to all of the map entry types and also to the rseq implementations in those types.

Show
Mike Fikes added a comment - By creating an IndexedSeq. on a 2-element JavaScript array in the -seq implementation, we can regain most of the perf that we had with the prior implementation where map entries were 2-element persistent vectors: After the patch is applied:
Benchmarking with V8
[me (first {:a 1})], (first me), 10000000 runs, 294 msecs
Benchmarking with SpiderMonkey
[me (first {:a 1})], (first me), 10000000 runs, 503 msecs
Benchmarking with JavaScriptCore
[me (first {:a 1})], (first me), 10000000 runs, 491 msecs
Benchmarking with Nashorn
[me (first {:a 1})], (first me), 10000000 runs, 5304 msecs
Benchmarking with ChakraCore
[me (first {:a 1})], (first me), 10000000 runs, 1390 msecs
While this helps with seq, first, and second, this also really helps a lot if code happens to call nth on the resulting seq. The patch applies the change to all of the map entry types and also to the rseq implementations in those types.
Hide
Mike Fikes added a comment - - edited

I tried (List. nil key (List. nil val () 1 nil) 2 nil) as a replacement for {{(IndexedSeq. #js [key val] 0 nil)}} and for

(simple-benchmark [me (first {:a 1})] (first me) 10000000)

I get speedups of 0.88 for V8, 0.83 for SpiderMonkey, and 0.73 for JavaScriptCore relative to the IndexedSeq. version. (In other words, the List. construct is slower than the IndexedSeq. construct.)

Show
Mike Fikes added a comment - - edited I tried (List. nil key (List. nil val () 1 nil) 2 nil) as a replacement for {{(IndexedSeq. #js [key val] 0 nil)}} and for
(simple-benchmark [me (first {:a 1})] (first me) 10000000)
I get speedups of 0.88 for V8, 0.83 for SpiderMonkey, and 0.73 for JavaScriptCore relative to the IndexedSeq. version. (In other words, the List. construct is slower than the IndexedSeq. construct.)

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: