ollix / MetalNanoVG

The Metal port of NanoVG.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

objc_release taking significant cpu time in profile

wtholliday opened this issue · comments

I'm noticing that objc_release is taking significant cpu time.

image

Looking at the generated assembly for mtlnvg__convexFill, it seems that a retain/release is due to using a @property for pipelineState.

Based on examining generated assembly, I think the solution may be to use methods on MNVGcontext to access the instance variables directly. For example:

-(void) convexFill:(MNVGcall*)call {
    
    const int kIndexBufferOffset = call->indexOffset * _indexSize;
    [self setUniforms:call->uniformOffset image: call->image];
    [_renderEncoder setRenderPipelineState:_pipelineState];
    
    if (call->indexCount > 0) {
        [_renderEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle
                                      indexCount:call->indexCount
                                       indexType:MTLIndexTypeUInt32
                                     indexBuffer:_buffers.indexBuffer
                               indexBufferOffset:kIndexBufferOffset];
    }
    
    // Draw fringes
    if (call->strokeCount > 0) {
        [_renderEncoder drawPrimitives:MTLPrimitiveTypeTriangleStrip
                              vertexStart:call->strokeOffset
                              vertexCount:call->strokeCount];
    }
    
}

and then

static void mtlnvg__convexFill(MNVGcontext* mtl, MNVGcall* call) {
   [mtl convexFill: call];
}

This seems to work. I made the change to convexFill and it no longer appears on the profile.

@wtholliday Thanks. I created a new branch and moved MNVGcontext-related implementation to the Objective C part. Can you try if it works for you? It would be nice if you can take another profiling screenshot for the changes. https://github.com/ollix/MetalNanoVG/tree/objc

@olliwang that was fast! :)

It's improved, but I'm still seeing a bit of retain/release:

image

It's still accessing properties of MNVGbuffers. Is there a clean way to avoid that?

Actually, you can declare an ivar @public. I didn't know that.

So perhaps a cleaner solution to all of this is to use public ivars, which would avoid the objc_msgSend I'm seeing creep into the profile (2.5%):

image

See https://stackoverflow.com/questions/17508777/need-to-declare-a-public-instance-variable-in-objective-c

@wtholliday I'm not sure if it works. Try the latest commit. 68fe3b2

@olliwang There are still properties on MNVGbuffers. I tried making one into a public ivar and it seemed to help.

I would make all the properties on MNVGcontext into public ivars and get rid of the methods I suggested earlier.

No retain/release, and no msg_send.

Getting there :)

@wtholliday All rest properties are strong references. Wouldn't that be a problem in ARC?

@olliwang I think the public ivars will work fine in terms of ARC.

I converted one of the properties over to a public ivar, and I saw a call to objc_storeStrong in the assembly when assigning the ivar.

@wtholliday Is the strong object released properly when assigning a new object to the same public ivar?

@olliwang I assume objc_storeStrong does that.

I converted commandBuffer (created per frame) over to a public ivar and I don't see any leaks in the memory graph debugger or in the leaks instrument.

@wtholliday Thanks. I just updated the branch. Please check if the latest commit works.

Resovled in 583f163