Open Bug 1711412 Opened 3 years ago Updated 1 month ago

Slow wasm compared to nodejs 14: anyref boxing and table operations are slow

Categories

(Core :: JavaScript: WebAssembly, defect, P3)

defect

Tracking

()

People

(Reporter: amirouche, Unassigned)

References

(Depends on 1 open bug, Blocks 1 open bug)

Details

Attachments

(1 file, 2 obsolete files)

Attached file test.wasm (obsolete) —

User Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0

Steps to reproduce:

I created a wasm module and benchmarked it with jsshell nightly (1304 ms) and nodejs14 (245 ms). jsshell performs much less

Actual results:

jsshell nightly is slow.

Expected results:

jsshell is as fast or faster than nodejs

All the code can be found at https://git.sr.ht/~amirouche/xp-web-assembly

There are also lots of "out of line" returns conversions too. Looks like they are taking some of the time: the function returns number values, but wasm expects reference, so slow boxing is happening.

Blocking the Slow vcalls bug for now; revisit when some of those fixes have landed, and/or profile to see if there are inefficiencies in the JS/wasm conversion paths.

Blocks: 1340235
Severity: -- → N/A
Priority: -- → P3
Depends on: 1742930
No longer blocks: 1340235
Blocks: 1742930
No longer depends on: 1742930
No longer blocks: 1742930
Depends on: 1742930
Severity: N/A → S3
Type: enhancement → defect

Current results on my development system (Linux x64): SpiderMonkey 11.4s, node16 7.9s, still quite a large difference. I'll attach an archive of the cleaned-up test case. See the Makefile for more.

Attached file node-vs-jsshell.tar (obsolete) —
Attached file node-vs-jsshell.tar

Updated archive, this removes spurious differences between the JS and Node versions.

Attachment #9222109 - Attachment is obsolete: true
Attachment #9259398 - Attachment is obsolete: true
Status: UNCONFIRMED → NEW
Ever confirmed: true

No evidence of indirect calls being an important problem here.

No longer depends on: 1742930
Summary: Slow Web Assembly compared to nodejs 14 (function references and indirect calls) → Slow Web Assembly compared to nodejs 14

Table operations (probably mostly on table<externref>) and externref aka "anyref" boxing are very hot:

   3.98%  js         js                    [.] JS::WeakCache<JS::GCHashSet<js::WeakHeapPtr<js::Shape*>, js::InitialShapeHasher, js::SystemAllocPolicy> >::lookupForAdd                         ◆
   3.94%  js         js                    [.] js::wasm::Instance::tableGet                                                                                                                    ▒
   3.32%  js         js                    [.] js::wasm::Table::fillAnyRef                                                                                                                     ▒
   3.11%  js         js                    [.] js::wasm::Instance::tableSet                                                                                                                    ▒
   2.29%  js         js                    [.] js::InternalBarrierMethods<JSObject*, void>::postBarrier                                                                                        ▒
   1.87%  js         js                    [.] js::SharedShape::getInitialShape                                                                                                                ▒
   1.81%  js         js                    [.] js::NativeObject::create                                                                                                                        ▒
   1.70%  js         js                    [.] js::NewObjectWithGivenTaggedProto                                                                                                               ▒
   1.55%  js         js                    [.] BoxValue_Anyref                                                                                                                                 ▒
   1.54%  js         [JIT] tid 339227      [.] 0x0000272b6aeef3e2                                                                                                                              ▒
   1.35%  js         js                    [.] js::wasm::BoxAnyRef                                                                                                                             ▒
   1.30%  js         [JIT] tid 339227      [.] 0x0000272b6aeef3f5                                                                                                                              ▒
   1.20%  js         [JIT] tid 339227      [.] 0x0000272b6aeef5e9                                                                                                                              ▒
   1.11%  js         js                    [.] js::AllocateObject<(js::AllowGC)1>                                                                                                              ▒
   1.10%  js         [JIT] tid 339227      [.] 0x0000272b6aeef3ce                                                                                                                              ▒
   1.03%  js         [JIT] tid 339227      [.] 0x0000272b6aedf0d3                                                                                                                              ▒
   1.00%  js         [JIT] tid 339227      [.] 0x0000272b6aeef3b2                                                                                                                              ▒

Here, the hash table lookup, the getInitialShape, the NativeObject::create, the NewObjectWithGivenTaggedProto, both box methods, and AllocateObject are all related to boxing - totalling about 13%. The anyref boxes can probably be streamlined a lot, they were hastily implemented so that we could experiment.

Table access is generally slow at the moment. Here it's mostly anyref tables. Ryan was trying to optimize that recently but ran into problems with the write barrier, but this suggests that it may be worth it to try again.

In the future, a lot of code compiled from higher-level languages may have this type of profile.

Summary: Slow Web Assembly compared to nodejs 14 → Slow wasm compared to nodejs 14: anyref boxing and table operations are slow
Depends on: 1532556, 1642412

As Yury notes above, BoxValue_Anyref is the root of the callout boxing path that is taken when wasm expects a reference but JS returns something that is not.

You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: