-
Notifications
You must be signed in to change notification settings - Fork 9
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
Performance is irregular on iOS8/iPad3 #246
Comments
In order to isolate the performance issue, I added this code throughout scenery's SVG update handling code: if (Date.now()-this.start>20000){
return;
} After setting up the behavior above and waiting for the remainder of the 20 seconds to elapse, the simulation runs at a consistent 60fps (while updating the model but not the graphics). |
I tried replacing the entire model step function with this to see if it could be caused by the physics: this.skater.position = new Vector2( 10 * Math.sin( Date.now() / 1000 / 3 ), Math.abs( 10 * Math.sin( Date.now() / 1000 / 7 / 3 ) ) );
this.skater.trigger( 'updated' ); This moves the skater all around the screen slowly. Normally it gives about 20fps on iPad3 but there are regions (such as the bottom right corner) where it gets noticeably smoother and reports 30fps. |
Remember how the behavior got chunky when an object was partially off the screen? phetsims/scenery#270 This may be a similar phenomenon |
I don't think the poor iOS8 performance is isolated to Energy Skate Park: Basics. I tested blast, and it is very nonsmooth and sluggish (even when removing css transforms). |
Same problem on iPad2/iOS8 |
When removing the skater graphic, the sim runs a smooth 60fps on iPad3/iOS8. When removing all graphics except the skater, the sim still runs sluggishly and getting faster/slower. Still true when replacing the skater image with a small circle. |
For this case, I'm seeing 55fps or so on average, but lots of stutters. |
Removing the red skateboard dot, removing the skaternode's parent node and using rendererOptions: {cssTransform: true} don't help at all. |
Rewriting SkaterNode using CanvasNode runs smoothly but 30fps (pretty slow compared to our normal 60fps). This is still with everything hidden except the skater like so: // Copyright 2002-2013, University of Colorado Boulder
/**
* Scenery node for the skater, which is draggable.
*
* Converted to composition instead of inheritance for SkaterNode to work around updateSVGFragment problem, see #123
*
* @author Sam Reid
*/
define( function( require ) {
'use strict';
// modules
var inherit = require( 'PHET_CORE/inherit' );
var Circle = require( 'SCENERY/nodes/Circle' );
var Image = require( 'SCENERY/nodes/Image' );
var SimpleDragHandler = require( 'SCENERY/input/SimpleDragHandler' );
var Matrix3 = require( 'DOT/Matrix3' );
var LinearFunction = require( 'DOT/LinearFunction' );
var Node = require( 'SCENERY/nodes/Node' );
var CanvasNode = require( 'SCENERY/nodes/CanvasNode' );
var Bounds2 = require( 'DOT/Bounds2' );
// images
var skaterLeftImage = require( 'image!ENERGY_SKATE_PARK_BASICS/skater-left.png' );
var skaterRightImage = require( 'image!ENERGY_SKATE_PARK_BASICS/skater-right.png' );
//Map from mass(kg) to scale
var massToScale = new LinearFunction( (100 + 25) / 2, 100, 0.34, 0.43 );
var LEFT_STRING = 'left';
/**
* SkaterNode constructor
*
* @param {Skater} skater
* @param {EnergySkateParkBasicsScreenView} view
* @param {ModelViewTransform} modelViewTransform
* @param {function} getClosestTrackAndPositionAndParameter function that gets the closest track properties, used when the skater is being dragged close to the track
* @param {function} getPhysicalTracks function that returns the physical tracks in the model, so the skater can try to attach to them while dragging
* @constructor
*/
function SkaterNode( skater, view, modelViewTransform, getClosestTrackAndPositionAndParameter, getPhysicalTracks ) {
this.skater = skater;
var skaterNode = this;
CanvasNode.call( this, {canvasBounds: new Bounds2( 0, 0, 1000, 1000 )} );
var imageWidth = 100;
var imageHeight = 100;
//Update the position and angle. Normally the angle would only change if the position has also changed, so no need for a duplicate callback there
//Uses pooling to avoid allocations, see #50
this.skater.on( 'updated', function() {
var mass = skater.mass;
var position = skater.position;
var direction = skater.direction;
var angle = skater.angle;
var view = modelViewTransform.modelToViewPosition( position );
//Translate to the desired location
var matrix = Matrix3.translation( view.x, view.y );
//Rotation and translation can happen in any order
var rotationMatrix = Matrix3.rotation2( angle );
matrix.multiplyMatrix( rotationMatrix );
rotationMatrix.freeToPool();
var scale = massToScale( mass );
skaterNode.image = direction === LEFT_STRING ? skaterLeftImage : skaterRightImage;
var scalingMatrix = Matrix3.scaling( scale, scale );
matrix.multiplyMatrix( scalingMatrix );
scalingMatrix.freeToPool();
//Think of it as a multiplying the Vector2 to the right, so this step happens first actually. Use it to center the registration point
var translation = Matrix3.translation( -imageWidth / 2, -imageHeight );
matrix.multiplyMatrix( translation );
translation.freeToPool();
// skaterNode.setMatrix( matrix );
skaterNode.storedMatrix = matrix;
skaterNode.invalidatePaint();
} );
//Show a red dot in the bottom center as the important particle model coordinate
// this.addChild( new Circle( 8, {fill: 'red', x: imageWidth / 2, y: imageHeight } ) );
var targetTrack = null;
var targetU = null;
this.addInputListener( new SimpleDragHandler(
{
start: function( event ) {
skater.dragging = true;
//Clear thermal energy whenever skater is grabbed, see https://github.com/phetsims/energy-skate-park-basics/issues/32
skater.thermalEnergy = 0;
//Jump to the input location when dragged
this.drag( event );
},
drag: function( event ) {
var globalPoint = skaterNode.globalToParentPoint( event.pointer.point );
var position = modelViewTransform.viewToModelPosition( globalPoint );
//make sure it is within the visible bounds
position = view.availableModelBounds.getClosestPoint( position.x, position.y, position );
//PERFORMANCE/ALLOCATION: lots of unnecessary allocations and computation here, biggest improvement could be to use binary search for position on the track
var closestTrackAndPositionAndParameter = getClosestTrackAndPositionAndParameter( position, getPhysicalTracks() );
var closeEnough = false;
if ( closestTrackAndPositionAndParameter && closestTrackAndPositionAndParameter.track && closestTrackAndPositionAndParameter.track.isParameterInBounds( closestTrackAndPositionAndParameter.u ) ) {
var closestPoint = closestTrackAndPositionAndParameter.point;
var distance = closestPoint.distance( position );
if ( distance < 0.5 ) {
position = closestPoint;
targetTrack = closestTrackAndPositionAndParameter.track;
targetU = closestTrackAndPositionAndParameter.u;
//Choose the right side of the track, i.e. the side of the track that would have the skater upside up
var normal = targetTrack.getUnitNormalVector( targetU );
skater.up = normal.y > 0;
skater.angle = targetTrack.getViewAngleAt( targetU ) + (skater.up ? 0 : Math.PI);
closeEnough = true;
}
}
if ( !closeEnough ) {
targetTrack = null;
targetU = null;
//make skater upright if not near the track
skater.angle = 0;
skater.up = true;
skater.position = position;
}
else {
skater.position = targetTrack.getPoint( targetU );
}
skater.updateEnergy();
skater.trigger( 'updated' );
},
end: function() {
//Record the state of the skater for "return skater"
skater.released( targetTrack, targetU );
}
} ) );
}
return inherit( CanvasNode, SkaterNode, {
paintCanvas: function( wrapper ) {
var context = wrapper.context;
//If the debug flag is enabled, it will show the bounds of the canvas
context.fillStyle = this.color;
// context.fillText( this.storedMatrix.toString(), 200, 200 );
this.storedMatrix.canvasAppendTransform( context );
context.fillRect( 0, 0, 100, 100 );
}
} );
} ); |
Putting back in the rest of the graphics except for the CanvasNode for the skater, the FPS is still 30FPS (which is good!). However, the FPS drops to 20fps when turning on piechart/barchart/grid/speedometer, which looks pretty slow. Also, if using CanvasNode for something draggable, we would have to find/create a solution for making the skater pickable. |
Simply putting |
When I ran the sin/sin test above, it revealed a region in the bottom right of the screen where the motion is very smooth and fast. You can see the same behavior by just dragging the skater. Dragging most of the places on the screen is very slow (30fps+stuttering) and dragging in the bottom right corner is very speedy (60fps and no hiccups). In this respect, the problem seems very similar to phetsims/scenery#270 |
After the above investigation, it seems like the best bets for continued development involve using webgl to render the skater (and possibly the charts), however this will delay publication of the sim significantly since this is a novel technology and doesn't integrate directly with our existing infrastructure (and since it should only apply to iOS8 devices). EDIT: If we need to publish before the above work can be completed, then we can use canvas renderer on iPad which will reduce the frame rate but fix the "speeding up and slowing down randomly" problem. |
Note: the same behavior as in the original issue comment occurs if you never create the skater node, but only show the pie chart. |
This renders the skater in Canvas: This renders the skater in Pixi: Minimal Pixi version: Minimial WebGL version: |
This version uses Scenery's initial webgl support for images + rectangles, moves all of the dynamic content to the front webgl layer, uses a custom (hack) speedometer needle: Issues/Concessions/Caveats/etc:
Results: I haven't tested this on iPad2 with iOS8, it would be good to see what that performance is like. Also, I don't have an iOS7 device and it would be good to test the performance there since numerous changes to the layering have been changed to push the dynamic content to the front. EDIT: reorganized notes above |
I tested iPad Air running iOS 8 today (for the SVG-rendered sim), and it had the same problem of speeding up and slowing down. WebGL, on the other hand is performing nicely on iPad3/iOS8. I'm going to merge webgl into master branch and continue there. |
Merge complete, and I deleted the webgl branch. |
@jbphet reports the following for iPad2/iOS7: 58fps average with all checkboxes off No reports of speeding up or slowing down as we saw for SVG/iOS8. The iOS8 performance is excellent. Closing. |
Energy skate park basics suffers from a significant problem on iOS8/iPad3. The motion speeds up and slows down dramatically at different parts in the track.
The text was updated successfully, but these errors were encountered: