Closed Bug 1244836 Opened 9 years ago Closed 1 year ago

Loading asm.js modules from cache is single-threaded/sequential and not accessible in parallel by multiple workers.

Categories

(Core :: JavaScript Engine, defect)

defect

Tracking

()

RESOLVED INCOMPLETE
Tracking Status
firefox47 --- affected

People

(Reporter: jujjyl, Unassigned)

Details

STR: Following the repro from bug 1244833, i.e. 1. Download https://dl.dropboxusercontent.com/u/40949268/emcc/bugs/PhysicsStressTest_16threads/PhysicsStressTest_16threads.zip 2. Unzip and double-click on 12_PhysicsStressTest.html to open. 3. Open page console. 4. Wait for the page to load. 5. Reload the page so that all the asm.js modules will already have been cached and will be loaded from cache instead of being compiled. Observed: The time taken to load up the asm.js module increases linearly by the number of times the module is being loaded. The page prints: Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js Preallocating 16 workers for a pthread spawn pool. 12_PhysicsStressTest.html:1242:13 loading ......in _PhysicsStressTest.data from cache 12_PhysicsStressTest.js:255:17 : Successfully compiled asm.js code (loaded from cache in 506ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 704ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 938ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 1177ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 1402ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 1630ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 1868ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 2110ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 2341ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 2571ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 2831ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 3087ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 3364ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 3610ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 3878ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 4124ms) 12_PhysicsStressTest.js which looks like each subsequent loading of the module carries an added impact/slowdown of ~ +200 msecs to load the module. This is suspicious, assumably each cache load should so the same amount of work, and the time taken to load from cache should be constant? Expected: The page should print something like Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js Preallocating 16 workers for a pthread spawn pool. 12_PhysicsStressTest.html:1242:13 loading ......in _PhysicsStressTest.data from cache 12_PhysicsStressTest.js:255:17 : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js : Successfully compiled asm.js code (loaded from cache in 251ms) 12_PhysicsStressTest.js
Flags: needinfo?(luke)
Access to the cache is single-threaded (by the QuotaManager) so I think what's happening here is that we start the compilation, start the timer timer, start the lookup, block on the origin's quota lock, and then one by one the origins get to do their load from cache. I'm not sure if there is a quick fix here given the dom/asmjscache interactions. B/c of this and the independent source/code-size issues, I expect we'll practically want to clamp the number of workers to something small (e.g. 4).
Flags: needinfo?(luke)
Ah right, Luke's explanation looks correct. Indeed each compilation does take about 250 msecs by itself, but each worker reports time including what it took to compile, plus the time that the worker waited for other threads before it to compile. So loading content from the cache is a sequential single-threaded activity, so only one worker is able to proceed at a time. Luke, does this sound like something that would be sensible to fix? Isn't loading from the cache a read-only operation, so should not be a limitation why multiple workers could not proceed at the same time to read? Not expecting any quick fixes, but fundamentally sounds doable?
Summary: Odd performance impact: loading an asm.js module from cache takes longer the more times it is loaded → Loading asm.js modules from cache is single-threaded/sequential and not accessible in parallel by multiple workers.
Yes we could effectively use a RW lock. I think the QuotaManager even already supports this kind of usage, but we're using it in a pretty simplistic way that simply takes the origin lock. With a bit of work, though, we could improve dom/asmjscache to use the more general mechanism. I should add that, if we do end up making caching explicit in wasm (WASM.compile would produce an uninstantiated, structured-cloneable module that could be stored in IDB), we'll sidestep this whole path. Furthermore, wasm won't need N workers for N threads.
Per policy at https://wiki.mozilla.org/Bug_Triage/Projects/Bug_Handling/Bug_Husbandry#Inactive_Bugs. If this bug is not an enhancement request or a bug not present in a supported release of Firefox, then it may be reopened.
Status: NEW → RESOLVED
Closed: 7 years ago
Resolution: --- → INACTIVE
Status: RESOLVED → REOPENED
Resolution: INACTIVE → ---
Severity: normal → S3
Status: REOPENED → RESOLVED
Closed: 7 years ago1 year ago
Resolution: --- → INCOMPLETE
You need to log in before you can comment on or make changes to this bug.