Skip to content

Instantly share code, notes, and snippets.

@lawrencelomax
Last active December 12, 2015 03:58
Show Gist options
  • Save lawrencelomax/4711119 to your computer and use it in GitHub Desktop.
Save lawrencelomax/4711119 to your computer and use it in GitHub Desktop.
ARC Retain/Release overhead in tight loops
/**
An inline (read: no overhead) function that will perform the physics increment for a given particle
@return A boolean for whether the particle has expired and needs to be removed
*/
extern inline BOOL updateParticle(BILParticleAtomConventional * atom, BILParticleModel * model, NSTimeInterval deltaTime)
{
// Time to Live
atom->atom.timeToLive -= deltaTime;
// Return early if expired
if(atom->atom.timeToLive <= 0)
{
atom->atom.timeToLive = -1;
return YES;
}
// Mode A: gravity, direction, tangential accel & radial accel
if(model.emitterMode == BILParticleModelEmitterModeGravity)
{
__unsafe_unretained BILParticleModelGravity * gravityModel = (BILParticleModelGravity *)model;
// Vector from the start position of this particle
GLKVector2 displacementFromStart = GLKVector2Subtract(atom->atom.position, atom->atom.startPosition);
// Dont divide by zero
if(displacementFromStart.x != 0 || displacementFromStart.y != 0)
displacementFromStart = GLKVector2Normalize(displacementFromStart);
// Radial & Tangential Acceleration
GLKVector2 radialAcceleration = GLKVector2MultiplyScalar(displacementFromStart, atom->mode.gravity.radialAcceleration);
// Tangential Acceleration
GLKVector2 tangentialAcceleration = displacementFromStart;
float newY = tangentialAcceleration.x;
tangentialAcceleration.x = -tangentialAcceleration.y;
tangentialAcceleration.y = newY;
tangentialAcceleration = GLKVector2MultiplyScalar(tangentialAcceleration, atom->mode.gravity.tangentialAcceleration);
// Component of all accelerations
GLKVector2 accelerationVector = GLKVector2Add(gravityModel.gravity, GLKVector2Add(tangentialAcceleration, radialAcceleration));
//GLKVector2 accelerationVector = model.gravity;
// Velocity Delta (accelleration * time)
GLKVector2 velocity = GLKVector2MultiplyScalar(accelerationVector, deltaTime);
// Velocity (velocity + deltaVelocity)
velocity = GLKVector2Add(atom->mode.gravity.velocity, velocity);
// Update Particle Velocity
atom->mode.gravity.velocity = velocity;
// Update Particle Position (position + (velocity * time))
atom->atom.position = GLKVector2Add(atom->atom.position, GLKVector2MultiplyScalar(velocity, deltaTime));
}
// Mode B: radius movement
else
{
// Update the angle and radius of the particle.
atom->mode.radial.angle += atom->mode.radial.anglePerSecond * deltaTime;
atom->mode.radial.radius += atom->mode.radial.deltaRadius * deltaTime;
GLKVector2 position = atom->atom.startPosition;
position.x += (- cosf(atom->mode.radial.angle) * atom->mode.radial.radius);
position.y += (- sinf(atom->mode.radial.angle) * atom->mode.radial.radius);
atom->atom.position = position;
}
// Interpolate Color
atom->atom.color.r += (atom->delta.deltaColor.r * deltaTime);
atom->atom.color.g += (atom->delta.deltaColor.g * deltaTime);
atom->atom.color.b += (atom->delta.deltaColor.b * deltaTime);
atom->atom.color.a += (atom->delta.deltaColor.a * deltaTime);
// Modify the Particle size
atom->atom.size += (atom->delta.sizeDelta * deltaTime);
atom->atom.size = MAX(0, atom->atom.size);
// Update the Angle
atom->atom.rotation += (atom->delta.rotationDelta * deltaTime);
return NO;
}
@lawrencelomax
Copy link
Author

The retain and release that ARC puts in on line 21 accounts for 90% of the cycles for this loop. Placing the __unsafe_unretained here removes ARCs influence entirely. All this is, is a cast of a parameter!

Trace Before
Trace Before

Trace After
Trace After

CPU Usage Before
CPU Usage Before

CPU Usage After
CPU Usage After

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment