In my OpenGL loop, Instruments is showing a total of 14% of my processor time in my particle processing loop going to objc_object::sidetable_release(bool)
and objc_object:sidetable_retain()
. This is significant, because the loop is using 100% of a CPU on an iPhone 5.
I'm wondering if there's a way I can reduce this. I don't know what causes it, and I don't see these in very many of my methods. I think they are related to doing a fast enumeration of an array of objects.
Here is what the offending method looks like:
-(void) updateWithTime:(ccTime)dt sceneHeightAboveHorizon:(CGFloat)yMax{
_elapsed = (_elapsed+dt) ;
float farTotalWidth = EQ_SCENE_WIDTH + 2*EQ_SIZE_FAR;
float farHalfWidth = farTotalWidth/2.0;
for (MyParticleData *data in self.farParticleData){
//Calculate position
float newX = data.pos.x + data.xVelocity * dt;
if (newX > 1)
newX -= 1;
float newY = data.y0 + EQ_A_FAR*sin(EQ_F_FAR*_elapsed+data.phasePosition);
data.pos = cc3v(newX,newY,0);
//Apply new position to sprites
data.sprite.position = cc3v(newX*farTotalWidth-farHalfWidth, newY*yMax, 0);
data.reflectedSprite.position = cc3v(data.sprite.position.x,-data.sprite.position.y,0);
//Calculate color
float f = MIN(14, MAX(data.pos.x*14.0, 0));
ccColor4F newColor = cycBlendColors(self.settings.eqColumnColors[(int)f], self.settings.eqColumnColors[(int)f+1], f-(int)f);
float colorAmp = MAX(0, (sin(data.frequencyColor*_elapsed+data.phaseColor)+1)/2.0);
newColor = cycScaleColor(newColor,colorAmp);
colorAmp *= colorAmp;//the alpha (white component) should be squared twice
newColor.a *= colorAmp*colorAmp;
//Apply new color to sprites
data.sprite.color4F = newColor;
data.reflectedSprite.color4F = cycScaleColor(newColor, self.settings.eqReflectionBrightness);
}
}
I'll try and psychically debug here -
1) You have ARC enabled
2) Some of the intermediate variables in your expressions (ex. data.sprite, self.settings) are Objective-C objects
3) One or more of these intermediate objects are weak or atomic (or are themselves accessing weak or atomic properties), both of which will require extra retain/release handling when accessed. - IIRC atomic properties won't involve the side table rigamarole, just normal autoreleasing, but no guarantees on that.
I would try assigning some/all of these references to a local (on the stack) variable before enumeration, and inside your loop use the local references exclusively. This will have the added benefit of shaving off some accessor time from your loop as well.
If you know these references will remain strongly referenced through the entire enumeration 100% of the time, then you can use the __unsafe_unretained specifier on your local variables, which will (mostly) prevent any ARC shenanigans whatsoever from occurring in this method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With