Re: [css-houdini-drafts] Improve potential for generating multiple animation frames in parallel

Here are the relevant IRC log discussions:
**till**: The internal state that has to be transferred to a worklet means that it's not possible to ever parallize this further. 
**till**: If instead we did something like provide a velocity of the current scroll, or last location, we could potentially do away with internal state, and speculatively execute multiple steps in the timline, and use them if necessary. 
**flackr**: It's worth pointing out that you can run each aniamtor independently. 
**till**: Understood. 
**flackr**: We'd have to specify all different pieces of state ... 
**TabAtkins**: Not necessarily all, just some useful stuff. With a properly designed API, could detect when they're only relying on pure state. 
**till**: Or restrict them to only pure state, if that's not too restrictive. 
**flackr**: Another header example is where your action depends on scroll direction in the past... 
**till**: Right, we could pass that in. 
**TabAtkins**: Or just, instead of mutating, always have it run on pure state that it can produce new versions of. 
**flackr**: Yeah, maybe your animation could specify that it's clean, and we could have a policy of regularly disposing of "clean" animations. 
**till**: This isn't about tearing down an animation, it's about running multiple frames interleaved, and reducing the risk of getting jank in this one animation. That's only possible with pure state. 
**TabAtkins**: Yeah, this could easily be an array of pure position/velocity state, and just returning an updated clone. 
**iank_**: A concer was the cost of structred cloning every frame. Would be better if we could just clone every N frames. 
**flackr**: This is coming from the world where devs would usually write this as a main-thread effect, so here at least they can be run separately. 
**till**: Right, so I see that being able to keep internal state is more powerful, but it keeps you from parallelizing. 
**flackr**: I wonder if there's verification possibility - analyze the script to see if it's pure enough. 
**till**: No, we tried that with parallel.js 
**TabAtkins**: And it's easy to fall out of the pit of success for no apparent reason. 
**iank_**: So if we returned the state every frame from animate, and passed it back in, we could do pure state. 
**till**: Not quite - we want to ask for frame N, *and* start working on frame N+1, without waiting for frame N to finish. 
**TabAtkins**: Ah, so that does require only relying on UA-provided state. 
**dbaron** **till**: You could increase your frame budget from 16ms to 32ms if you're doing frames on 2 different cores 
**till**: Yeah, letting us take care of animations on multiple cores. 
**surma**: People are already asking for how to depend on user input. That breaks speculation, right? 
**till**: People don't usually change the velocity of their input in short timescales (30ms or so). You'll occasionally mis-speculate, but mostly will be okay. 
**birtles**: And doing multiple frames at slight offsets to produce motion blur. 
**TabAtkins**: I think this is all quite tractable with minimal changes. 
**iank_**: Would you be okay with starting with a mode that says you only use pure state, and we'll tear down your object regularly to preven tyou from relying on impure state? 
**till**: I probably can't convince you to actually produce fresh objects on every frame, so yeah. 
**TabAtkins**: Get all the JS engines to give us cheap immutable state, and we'll talk. ^_^ 
**till**: And spec some additional pure state info the UA can provide to the animator. 
**iank_**: Velocity, accel, maybe last N frames of scroll data... 
**iank_**: So thinking maybe we start with a separate mode, see what people are using with it, start adding more data. 
**jack**: Could we pass in velocity and acceleration by default? You pretty much have to calculate that anyway. 
**till**: Problem with the flag is that we can't default to that. Maybe if we just speculate wrongly for the first N frames we can switch to the stateful version? 
**flackr**: We have this idea that we can add info to the timeline that contains this extra info, like user input too. 
**iank_**: We could invert the flag - default to not passing in new state, you can flag it on to get user-defined state passed around. 
**till**: Seems useful regardless of speculative execution. 
**iank_** https://gist.github.com/anonymous/e22250dbdfa92da59508a220b8087d9d 
**till**: If we always pass in these values, people can rely on it, and we can just assume things are pure unless we fail speculation. 
**TabAtkins**: How do you speculate if people *are* using mutating state? Seems you'd mess up the state. 
astearns "useful regardless of speculative execution" should go into someone's twitter bio 
**till**: Run one thread as source of truth for a while, speculatively run the same frames ahead of time on another thread. If speculation fails for more than N out of the first M frames (speculation gives different result than the "real" thread), assume they're using mutating state and stop speculating. Otherwise, continue speculating. 
**surma** waves at brucel 
**till**: Something that could be helped by sequential speculative execution is power usage - better to spike the CPU in bursts rather than run it continuously. 
**brucel**: And with 120Hz animation, letting the animator idle as much as possible would be good. 
surma s/brucel/dino 
**till**: And with 4 cores, you can split frames between them, have better guarantee of hitting every frame. 
**dino**: So I think you're saying - based on what's happening now, you'll be issuing a lot of updates in a short amoutn of time, so you want to use other cores to pregen some frames ahead now, so they're ready when needed. 
**dino**: So the speculative ones return frames, timestamped, the system uses them? 
**TabAtkins**: Yeah. Speculate for the first N frames along with primary thread, compare values; assume speculation is safe if it succeeds. 
**dino**: Why not let the worklet return multiple successive frames? 
**TabAtkins**: That doesn't solve the problem, right? You're still spending the same amount of CPU as calling it multiple times. 
**dino**: Like, if I know the animation wants to run at 120Hz, but I'll be called at 60Hz, you can do two frames at once. 
**till**: That still requires you to calculate frames at 120Hz. With speculation you can actually pump frames at 60Hz, just every other frame on each core. 
**iank_** thinks this flag should be: "static callMeMaybe = true;" 
**TabAtkins**: Probably useful to have a flag that specifies whether you think you're safe to speculate or not. If you claim you are, we do some things to keep you honest (tear down your object regularly); if you claim you're not, UAs might still do speculation speculatively to see if you really are, as till described earlier. 
**flackr**: This sounds sensible. 
**till**: This is also based on impl experience we're having with Paint Worklet, we're already doing speculation there. Slightly different cases there, but similar API. 
**till** PR for speculative paint worklet execution: https://github.com/servo/servo/pull/17810 

-- 
GitHub Notification of comment by majido
Please view or discuss this issue at https://github.com/w3c/css-houdini-drafts/issues/812#issuecomment-417053873 using your GitHub account

Received on Wednesday, 29 August 2018 18:19:36 UTC