-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ParametricSpringNode optimizations #3
Comments
More info... HookesLawSpringNode is the subtype of ParametricSpringNode that's used by the sim. One optimization would be to remove this feature from HookesLawSpringNode: // shrink the coil radius (y dimension) a bit when stretching the spring, to simulate radius change
spring.displacementProperty.link( function( displacement ) {
if ( displacement <= 0 ) {
// compressed
propertySet.aspectRatioProperty.set( options.aspectRatio );
}
else {
// stretched
propertySet.aspectRatioProperty.set( options.aspectRatio * ( 1 - 0.05 * displacement / spring.displacementRange.max ) );
}
} ); This is expensive, as it causes the gradients to be recomputed every time the displacement changes. Without this, gradients would be computed only once, at construction. Since this effect is subtle, I'm not sure that it's worth the cost. @arouinfar and @ariel-phet, how would you feel about dropping this bit of behavior? The coil radius would not shrink subtly when the spring is stretched. |
Btw... The performance improvement for dropping the above feature is noticeable, but not enough to make performance feel snappy on iPad. |
More info for @jonathanolson ... ParametricSpringNode has a lot of properties. But there are only 3 that change in this sim, as can be seen in HookesLawSpringNode (search for ".set"). The properties that change are: xScale, lineWidth and aspectRatio. |
@pixelzoom, I would be fine with dropping this behavior, especially since it has a noticeable impact on performance. While it's a nice touch, I doubt that many users will notice such a subtle change in the coil radius. I don't think it's worth sacrificing performance for it. |
CPU time is being taken up predominantly by computing bounds of the stroked part of the shape (which is redone every frame). I'll probably add a flag to do bounds computation in a way that doesn't figure out the exact stroked bounds (which should be much faster), and possibly an option to not compute bounds at all (see phetsims/scenery#433). |
@ariel-phet said via email:
|
After using boundsMethod:'unstroked', notes about Chrome desktop performance (relative numbers important):
|
On desktop, looks like the multilink is typically being called twice per frame while I drag (it's unnecessarily doing twice the work, since only the last update before the next animation frame is displayed): For this type of thing, I'd recommend attempting to update it only on the view step in general (since it's so potentially expensive). |
boundsMethod: 'none' instead of 'unstroked' could have a speed-up, since presumably we could calculate the approximate width based on just the inputs to the spring shape. On Chrome, profiling information notes that this probably isn't the biggest bottleneck however. Updating to iOS 8.4, will test on the iPad 3. |
Bottom-up profiling reveals Events.trigger0 to be the biggest contributor to CPU by 2x (next closest is lineToPoint itself). Second is kite.svgNumber. I'll potentially look into getting direct function references for each file, instead of requiring the kite.X lookup every time. |
Profiling from the iPad (using the web inspector from Safari, weinre/Valence/etc. were insufficient for profiling information): Most expensive codepath to inner loop (there seem to be 2 different paths to the inner loop):
Note that this is just the first screen, moving the single hook. |
My first proposed change is to not compute the bounds of the coil (use boundsMethod: 'none'), and my guess is that would have about a 35% speedup in execution time over boundsMethod: 'unstroked', which itself seemed to have been at least 2x faster than boundsMethod: 'accurate' (the default and latest dev version). For layout, instead of using the bounds, compute how big the spring will be. My second proposed change is more invasive, and will require a few more changes to Shape/Path. It would involve creating one Shape/Path, and on changes, mutating the Vector2s used in the Shape (and then invalidating the shape). Presumably we'd create a SpringNode with a certain number of points, and if the number of points needed to change (which I was told didn't need to happen during an animation) it would need to build a new Shape. So if you have a lineToPoint( p ), you would modify the x/y values of p to the new place. Otherwise, there are various inner-loop optimizations that can be made (factoring out 2_pi/pointsPerLoop, or xScale_radius/pointsPerLoop, etc.) in case the JIT isn't taking care of that. Let me know what you think about the proposed changes. |
7/14/15 call with @jonathanolson (1) I'll use (2) jonathan will add (3) Add a guard so that |
Kite/Scenery parts completed, feel free to assign me for further iPad 3 testing. |
More stuff I'll need to do: • Rewrite some of HookesLawIconFactory, which relies on accurate bounds of the springNode. For example, on my first attempt at using boundsMethod:'none', createIntroScreenIcon was failing an assertion in Node with "x not finite". • Figure out how to accurately attach the right spring to the left spring in SeriesSystemNode. |
One comment...if buttery smooth on iPad2 and a little sluggish on iPad 3, no need to optimize further (we can accept sluggishness on iPad 3) |
Roger. Butter ok on iPad2, molasses OK on iPad3. |
…ly, in preparation for using boundsMethod 'none'
…ONSTANT, where CONSTANT is determined empirically (in preparation for using boundsMethod:'none')
I've completed the first major optimization, that is using Here's a dev version that uses Compare to the previous dev version, which used @arouinfar @ariel-phet How does this feel to you? Sufficiently responsive? Should I proceed with additional (more invasive) optimizations (2) and (3), as described in #3 (comment)? Also interested in @jonathanolson's feedback on #3 (comment). And if you could profile again as you did above, that would be appreciated. I'm interested to see if we really got a >2x speed up by using |
Skype conversation with @jonathanolson:
So I think I should investigate why the callback to ParametricSpringNode.multilink is being called multiple times per animation frame. |
@pixelzoom I don't notice a difference in responsiveness on my Mac. I've been working remotely the last few days (out sick) so I don't have access to an iPad to test on. Perhaps @ariel-phet can take a look at this on iPad tomorrow. |
@arouinfar Unlikely that you'd notice much of a difference on a desktop computer, where the sim was already quite snappy. |
Will plan to test tomorrow with better access to devices. |
Since this is going to be migrate to scenery-phet (#16), I recommend implementing optimization (2) (see #3 (comment)) now. |
Tested, CPU is mostly involved with the Kite overhead, I believe optimization (2) should be the most helpful. |
…about the coil portion of the spring
Playing around with optimization (2), mutating vectors... Here's the signature of the multilink callback for the various Properties:
It's only possible to mutate vectors if loops, pointsPerLoop, phase and deltaPhase remain constant. If loops or pointsPerLoop change, then the number of vectors changes. If phase or deltaPhase changes, then the number of total vectors is the same, but they are distributed differently between the "front" and "back" Shapes for the coil. So I'll probably split this up into 2 multilink callbacks, where this one mutates vectors and calls
...and this one creates new Shapes and vectors:
... with some common code factored out that they both use. |
Here's a dev version that mutates vectors (optimization 2 above): Compare to previous dev version: The latest version is noticeably snappier, more responsive feeling. I'm satisfied with this. @ariel-phet Do you want to test drive, since @arouinfar is out? If this looks good, we can proceed to dev testing for hookes-law. |
@pixelzoom - I should be near an ipad later today, I will look at it then, but I am guessing that if you are satisfied it will be great. |
Tested on iPad2, looks awesome. Closing |
Hooke's Law feels a bit sluggish to me on iPad, especially after we started using the more complicated ParametricSpringNode for the spring view.
To demonstrate, compare this version that uses a simple spring view:
http://www.colorado.edu/physics/phet/dev/html/hookes-law/1.0.0-dev.17/hookes-law_en.html
... to this version with ParametricSpringNode:
http://www.colorado.edu/physics/phet/dev/html/hookes-law/1.0.0-dev.18/hookes-law_en.html
@jonathanolson Could you please review ParametricSpringNode for potential optimizations?
The text was updated successfully, but these errors were encountered: