Obj-C 方法调用超慢,更多 CPU 用法?

Obj-C Method calls super slow, lots more CPU usage?

我正在进行像素处理,当我调用一个空的 Objective-C 方法时,它多使用了 25% CPU。

此外,另一个奇怪的情况是,如果我在该方法中有另一个 Obj-C 函数调用从未被调用,它会使 CPU 使用量额外增加 10%。

这是我调用的代码:

- (void)addLeftCorner:(struct Position)p top:(BOOL)top {
    if (top) {
        [blackBorderLock lock];
        [topLeftAllyMinionCorners addObject:[NSValue valueWithBytes:&p objCType:@encode(struct Position)]];
        [blackBorderLock unlock];
    } else {
        [blackBorderLock lock];
        [bottomLeftAllyMinionCorners addObject:[NSValue valueWithBytes:&p objCType:@encode(struct Position)]];
        [blackBorderLock unlock];
    }
}

- (void) processPixel:(uint8_t *)pixel x:(int)x y:(int)y{
    //Assume multithreaded

    if (pixel[0] == 0 && pixel[1] == 0 && pixel[2] == 0) {

        //Check if top left border
        if (x < imageData.imageWidth-1) {

            if (y < imageData.imageHeight-1) { //Check for top left bar

                //Check bottom right pixel
                uint8_t *bottomRightPixel = pixel + (imageData.imageWidth + 1)*4;

                if (bottomRightPixel[2] == 81 && bottomRightPixel[1] == 162 && bottomRightPixel[0] == 230) {

                    uint8_t *rightPixel = pixel + (1)*4;
                    if (rightPixel[0] == 0 && rightPixel[1] == 0 && rightPixel[2] == 0) {
                        uint8_t *bottomPixel = pixel + (imageData.imageWidth)*4;
                        if (bottomPixel[0] == 0 && bottomPixel[1] == 0 && bottomPixel[2] == 0) {
                            struct Position p;p.x=x;p.y=y;
                            [self addLeftCorner:p top:true];
                        }
                     }

                }
            }
            if (y > 0) { //Check for bottom left bar

                //Check top right pixel
                uint8_t *topRightPixel = pixel + (-imageData.imageWidth + 1)*4;
                if (topRightPixel[2] == 40 && topRightPixel[1] == 80 && topRightPixel[0] == 114) {
                    uint8_t *rightPixel = pixel + (1)*4;
                    if (rightPixel[0] == 0 && rightPixel[1] == 0 && rightPixel[2] == 0) {
                        uint8_t *topPixel = pixel - (imageData.imageWidth)*4;
                        if (topPixel[0] == 0 && topPixel[1] == 0 && topPixel[2] == 0) {
                            struct Position p;p.x=x;p.y=y;
                            [self addLeftCorner:p top:false];
                        }
                    }
                }

            }
        }
    }
}

在 运行 中,addLeftCorner 永远不会被调用,如果我将其注释掉,我将获得额外的 10% CPU 使用率。此外,仅调用方法 processPixel 就占用了 25% CPU 的使用量。

这是为什么?有没有办法优化它?我想拿回那 35% CPU。

TL;DR - 您将需要研究使用 NSObject -methodForSelector: 作为避免 Objective-C 运行时开销的方法。明智地使用它。

-

有一些来自 Smalltalk 的术语对于保持真实情况的心理模型很有用。我们通常指的是 invoking 一个 method 而不是调用一个函数来识别像 Objective-C 这样的动态语言在运行时解析函数地址,每次,响应消息接收者的那种对象。

这种动态调度是动态语言多态性的核心。虽然 Objective-C 运行时几乎达到超人的长度以使方法调用尽可能高效,但它永远不会像直接函数调用那样高效。

大多数时候,方法调用效率低下并不重要。人与应用程序的交互淹没了通常很小的效率损失。但是对于像图像处理这样的计算内核,低效率将变得明显。

通过使用 NSObject -methodForSelector:,您可以将方法解析为函数地址一次,然后跳过运行时查找。仔细研究文档。确保您了解 SEL is and what an IMP 是什么。将方法作为函数调用需要两个额外的参数,self_cmd。确保您了解它们是什么以及如何使用它们。

最重要的是,确保分析绝对证明像这样绕过运行时是必要的。根据您对问题的描述,我不完全相信您看到的正是问题所在。但您是最了解您的软件的人。

你将防止你正在使用这个 method/function 的对象的多态性的可能性,所以它有点具体地设置你设计的这个方面,没有动态语言通常的灵活性.