[Webkit-unassigned] [Bug 246009] New: Object.entries() is 1.5x slower in JSC compared to V8
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Tue Oct 4 00:28:20 PDT 2022
https://bugs.webkit.org/show_bug.cgi?id=246009
Bug ID: 246009
Summary: Object.entries() is 1.5x slower in JSC compared to V8
Product: WebKit
Version: WebKit Nightly Build
Hardware: Unspecified
OS: Unspecified
Status: NEW
Severity: Normal
Priority: P2
Component: JavaScriptCore
Assignee: webkit-unassigned at lists.webkit.org
Reporter: jarred at jarredsumner.com
Created attachment 462781
--> https://bugs.webkit.org/attachment.cgi?id=462781&action=review
Launch_bun_2022-10-03_23.22.34_2576143F.trace.zip
I've attached an Instruments trace and sampling profiler output of using Rollup.js to bundle the "@babel/standalone" npm package. End-to-end, it runs about 1.6x slower in JSC (bun) compared to V8 (node). Nearly all the time is spent in JSC.
I think it's _mostly_ because of Object.entries() (which is why the issue is titled about Object.entries()). Rollup seems to use Object.entries() in their code a _lot_. In @babel/standalone's case, Object.entries() is called 550,000 times. For larger objects, Object.entries() is around 1.5x slower than in V8 (microbenchmark). It looks like ObjectKeys exists in DFGSpeculateJIT64.cpp but ObjectEntries and ObjectValues do not. Maybe adding it as a JIT operation would help? I don't know if that's the whole story though. It feels like there's a side effects tracking thing that would enable skipping some of the PropertyTable::find lookups, maybe?
```
❯ bun /Users/jarred/Code/bun/bench/snippets/object-entries.mjs
cpu: Apple M1 Max
runtime: bun 0.1.14 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
--------------------------------------------------------------- -----------------------------
Object.entries(26 keys) 1.27 µs/iter (1.21 µs … 1.99 µs) 1.28 µs 1.99 µs 1.99 µs
Object.keys(26 keys) 515.77 ns/iter (477.57 ns … 628.68 ns) 526.63 ns 617.05 ns 628.68 ns
Object.entries(2 keys) 132.46 ns/iter (125.25 ns … 205.22 ns) 127.54 ns 194.48 ns 196.87 ns
Object.keys(2 keys) 4.68 ns/iter (4.12 ns … 219.59 ns) 4.42 ns 7.48 ns 10.22 ns
```
```
❯ node /Users/jarred/Code/bun/bench/snippets/object-entries.mjs
cpu: Apple M1 Max
runtime: node v18.9.1 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
--------------------------------------------------------------- -----------------------------
Object.entries(26 keys) 830.02 ns/iter (803.19 ns … 1.07 µs) 821.85 ns 1.07 µs 1.07 µs
Object.keys(26 keys) 327.72 ns/iter (319.58 ns … 421.81 ns) 329.03 ns 400.85 ns 421.81 ns
Object.entries(2 keys) 98.28 ns/iter (96.05 ns … 452.63 ns) 97.19 ns 105.5 ns 108.87 ns
Object.keys(2 keys) 13.36 ns/iter (10.75 ns … 76.29 ns) 15.3 ns 17.92 ns 21.13 ns
```
-
Benchmark:
```
import { bench, run } from "../../node_modules/mitata/src/cli.mjs";
const obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
h: 8,
i: 9,
j: 10,
k: 11,
l: 12,
m: 13,
n: 14,
o: 15,
p: 16,
q: 17,
r: 18,
s: 19,
t: 20,
u: 21,
v: 22,
w: 23,
x: 24,
y: 25,
z: 26,
};
bench("Object.entries(26 keys)", () => {
var k;
for (let [key, value] of Object.entries(obj)) {
value = key;
}
return k;
});
bench("Object.keys(26 keys)", () => {
var k;
for (let [key, value] of Object.keys(obj)) {
value = key;
}
return k;
});
bench("Object.entries(2 keys)", () => {
var k;
for (let [key, value] of Object.entries({ a: 1, b: 2 })) {
value = key;
}
return k;
});
bench("Object.keys(2 keys)", () => {
var k;
for (let item of Object.keys({ a: 1, b: 2 })) {
}
return k;
});
await run();
```
Sampling profiler output:
Sampling rate: 100.000000 microseconds. Total samples: 19077
Top functions as <numSamples 'functionName#hash:sourceID'>
4028 'include#<nil>:5'
1552 'parseNode#<nil>:5'
1299 '#<nil>:5'
1089 'entries#<nil>:4294967295'
979 'includeCallArguments#<nil>:5'
809 'create#<nil>:4294967295'
656 'hasEffects#<nil>:5'
606 'arrayIteratorNextHelper#<nil>:7'
568 'NodeBase#<nil>:5'
547 '#<nil>:4294967295'
506 'bind#<nil>:5'
495 'render#<nil>:5'
Sampling rate: 100.000000 microseconds. Total samples: 19077
Tier breakdown:
-----------------------------------
LLInt: 184 (0.964512%)
Baseline: 935 (4.901190%)
DFG: 3991 (20.920480%)
FTL: 10469 (54.877601%)
js builtin: 862 (4.518530%)
Wasm: 0 (0.000000%)
Host: 559 (2.930230%)
RegExp: 115 (0.602820%)
C/C++: 0 (0.000000%)
Unknown Frame: 4 (0.020968%)
Unknown Executable: 2820 (14.782198%)
Hottest bytecodes as <numSamples 'functionName#hash:JITType:bytecodeIndex'>
1089 'entries#<nil>:None:<nil>'
1001 'include#<nil>:FTL:bc#33'
809 'create#<nil>:None:<nil>'
575 'parseNode#<nil>:FTL:bc#218'
547 '#<nil>:None:<nil>'
443 'parseNode#<nil>:FTL:bc#479'
411 'Set#<nil>:None:<nil>'
404 'include#<nil>:FTL:bc#107'
363 'include#<nil>:FTL:bc#296'
337 'include#<nil>:FTL:bc#93'
280 'arrayIteratorNextHelper#<nil>:FTL:bc#122'
272 'include#<nil>:FTL:bc#54'
251 'arrayIteratorNextHelper#<nil>:FTL:bc#58'
221 'includeCallArguments#<nil>:FTL:bc#59'
206 'includeProperties#<nil>:FTL:bc#59'
127 'Map#<nil>:None:<nil>'
117 'getEntities#<nil>:FTL:bc#180'
111 'include#<nil>:FTL:bc#0'
107 'parseModule#<nil>:None:<nil>'
106 'values#<nil>:None:<nil>'
106 'parseNode#<nil>:FTL:bc#760'
95 'includeCallArguments#<nil>:DFG:bc#201'
90 'include#<nil>:FTL:bc#138'
87 'getEntities#<nil>:FTL:bc#76'
84 'includeCallArguments#<nil>:FTL:bc#0'
81 'bind#<nil>:FTL:bc#262'
81 'delete#<nil>:None:<nil>'
81 'include#<nil>:FTL:bc#196'
77 '#<nil>:FTL:bc#0'
75 'createScope#<nil>:FTL:bc#11'
73 'include#<nil>:FTL:bc#27'
73 'include#<nil>:FTL:<nil>'
72 '/^(?:break|case|catch|continue|debugger|default|do|else|finally|for|function|if|return|switch|throw|try|var|while|with|null|true|false|instanceof|typeof|void|delete|new|in|this|const|class|extends|export|import|super)$/#<nil>:RegExp:<nil>'
72 'bind#<nil>:FTL:bc#65'
71 'includeCallArguments#<nil>:FTL:<nil>'
71 'includeProperties#<nil>:FTL:bc#19'
70 'include#<nil>:DFG:bc#54'
66 'includeProperties#<nil>:FTL:bc#70'
65 'includeUnknownTest#<nil>:DFG:bc#22'
65 'include#<nil>:FTL:bc#229'
--
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20221004/6e8eb883/attachment-0001.htm>
More information about the webkit-unassigned
mailing list