繁体   English   中英

为什么在这个方法中添加一个If语句会大大减慢它?

[英]Why does adding an If-statement inside a this method slow it down so drastically?

我在回答另一个问题时遇到了这个问题 我试图诊断哪个代码更改对速度有更大的影响。 我在for循环中使用了一个布尔标志来在使用辅助方法构建Color之间切换。

有趣的行为是,当我决定哪一个更快并删除了如果代码的速度放大了10倍。 以前需要140ms,之后只需13ms。 我应该只从循环中删除大约7个计算。 为什么速度如此急剧增加?

慢代码:(helperMethods为false时运行141毫秒) *参见编辑2

public static void applyAlphaGetPixels(Bitmap b, Bitmap bAlpha, boolean helperMethods) {
    int w = b.getWidth();
    int h = b.getHeight();
    int[] colorPixels = new int[w*h];
    int[] alphaPixels = new int[w*h];
    b.getPixels(colorPixels, 0, w, 0, 0, w, h);
    bAlpha.getPixels(alphaPixels, 0, w, 0, 0, w, h);
    for(int j = 0; j < colorPixels.length;j++){
        if(helperMethods){
            colorPixels[j] = Color.argb(Color.alpha(alphaPixels[j]), Color.red(colorPixels[j]), Color.green(colorPixels[j]), Color.blue(colorPixels[j]));
        } else colorPixels[j] = alphaPixels[j] | (0x00FFFFFF & colorPixels[j]);
    }
    b.setPixels(colorPixels, 0, w, 0, 0, w, h);
}

快速代码:(运行13ms)

public static void applyAlphaGetPixels(Bitmap b, Bitmap bAlpha) {
    int w = b.getWidth();
    int h = b.getHeight();
    int[] colorPixels = new int[w*h];
    int[] alphaPixels = new int[w*h];
    b.getPixels(colorPixels, 0, w, 0, 0, w, h);
    bAlpha.getPixels(alphaPixels, 0, w, 0, 0, w, h);
    for(int j = 0; j < colorPixels.length;j++){
        colorPixels[j] = alphaPixels[j] | (0x00FFFFFF & colorPixels[j]);
    }
    b.setPixels(colorPixels, 0, w, 0, 0, w, h);
}

编辑:似乎问题不在于if在循环内部的事实。 如果我提升循环外的if 代码运行速度稍快但仍处于131ms的低速:

public static void applyAlphaGetPixels(Bitmap b, Bitmap bAlpha, boolean helperMethods) {
    int w = b.getWidth();
    int h = b.getHeight();
    int[] colorPixels = new int[w*h];
    int[] alphaPixels = new int[w*h];
    b.getPixels(colorPixels, 0, w, 0, 0, w, h);
    bAlpha.getPixels(alphaPixels, 0, w, 0, 0, w, h);
    if (helperMethods) {
        for (int j = 0; j < colorPixels.length;j++) {
            colorPixels[j] = Color.argb(Color.alpha(alphaPixels[j]),
                                        Color.red(colorPixels[j]),
                                        Color.green(colorPixels[j]),
                                        Color.blue(colorPixels[j]));
        }
    } else {
        for (int j = 0; j < colorPixels.length;j++) {
             colorPixels[j] = alphaPixels[j] | (0x00FFFFFF & colorPixels[j]);
        }
    }

    b.setPixels(colorPixels, 0, w, 0, 0, w, h);
}

编辑2:我很蠢。 真的很蠢。 在调用堆栈的早期,我使用另一个布尔标志在使用此方法和使用另一个使用getPixel而不是getPixels方法之间切换。 我为所有具有helperMethod参数的调用设置了此标志。 当我在没有helperMethod的情况下helperMethod版本进行新调用时,我helperMethod 性能提升是因为getPixels不是if语句。

实际慢速代码:

public static void applyAlphaGetPixel(Bitmap b, Bitmap bAlpha, boolean helperMethods) {
    int w = b.getWidth();
    int h = b.getHeight();
    for(int y=0; y < h; ++y) {
        for(int x=0; x < w; ++x) {
            int pixel = b.getPixel(x,y);
            int finalPixel;
            if(helperMethods){
                finalPixel = Color.argb(Color.alpha(bAlpha.getPixel(x,y)), Color.red(pixel), Color.green(pixel), Color.blue(pixel));
            } else{
                finalPixel = bAlpha.getPixel(x,y) | (0x00FFFFFF & pixel);
            }
            b.setPixel(x,y,finalPixel);
        }
    }
}

注意:所有速度平均为100次运行。

尝试将条件提升出循环:

if (helperMethods) {
    for (int j = 0; j < colorPixels.length;j++) {
        colorPixels[j] = Color.argb(Color.alpha(alphaPixels[j]),
                                    Color.red(colorPixels[j]),
                                    Color.green(colorPixels[j]),
                                    Color.blue(colorPixels[j]));
    }
} else {
    for (int j = 0; j < colorPixels.length;j++) {
         colorPixels[j] = alphaPixels[j] | (0x00FFFFFF & colorPixels[j]);
    }
}

在“快速代码”中,您永远不会运行该语句

colorPixels[j] = Color.argb(Color.alpha(alphaPixels[j]), Color.red(colorPixels[j]), Color.green(colorPixels[j]), Color.blue(colorPixels[j])); 

但是在'慢代码'中,如果布尔值至少设置为true,则运行此addiotional语句会使时间更长。 如果您的条件总是为假,则在循环的每次迭代中检查if语句大约7次。 尝试将if置于循环外部。

这可能是您的分析代码,让您感到困惑。 尝试隔离要分析的代码部分,并仅测量该部分,避免GCable操作,如在您的情况下创建位图。

如果我用你的测试代码

testing.loadDrawable(this, false, true, false)

它运行缓慢。 但如果我打电话给它

testing.loadDrawable(this, true, true, false)

这是一个类似的(更糟糕的)数字。 所以useGetPixels会发挥重要作用。 我想将Bitmap数据放入本地缓冲区并稍后设置结果。

在快速代码中,根本不使用类Color。 我假设这个类的初始化需要一些时间,它有很多静态方法和静态代码。

您可以尝试执行以下操作:确保在进行测试之前完全加载并初始化Color类(可以在调用applyAlphaGetPixels()方法之前调用Color类中的任何静态方法)。 然后运行测试并比较结果。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM