简体   繁体   English

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

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

I came across this in answering another question . 我在回答另一个问题时遇到了这个问题 I was trying to diagnose which code change had a greater effect on the speed. 我试图诊断哪个代码更改对速度有更大的影响。 I used a boolean flag in a for loop to switch between using helper methods to construct a Color . 我在for循环中使用了一个布尔标志来在使用辅助方法构建Color之间切换。

The interesting behavior is that when I decided which one was faster and removed the if the speed of the code amplified 10x. 有趣的行为是,当我决定哪一个更快并删除了如果代码的速度放大了10倍。 Taking 140ms before and just 13ms afterward. 以前需要140ms,之后只需13ms。 I should only be removing one calculation out of about 7 from the loop. 我应该只从循环中删除大约7个计算。 Why such a drastic increase in speed? 为什么速度如此急剧增加?

Slow code: (runs in 141 milliseconds when helperMethods is false) *See edit 2 慢代码:(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);
}

Fast Code: (Runs in 13ms) 快速代码:(运行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);
}

EDIT: It seems the issue is not with the fact that the if is inside the loop. 编辑:似乎问题不在于if在循环内部的事实。 If I elevate the if outside of the loop. 如果我提升循环外的if The code runs slightly faster but still at the slow speeds with 131ms: 代码运行速度稍快但仍处于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);
}

EDIT 2: I'm dumb. 编辑2:我很蠢。 Really really dumb. 真的很蠢。 Earlier in the call stack I used another boolean flag to switch between between using this method and using another method that uses getPixel instead of getPixels . 在调用堆栈的早期,我使用另一个布尔标志在使用此方法和使用另一个使用getPixel而不是getPixels方法之间切换。 I had this flag set wrong for all of my calls that have the helperMethod parameter. 我为所有具有helperMethod参数的调用设置了此标志。 When I made new calls to the version without helperMethod I did it correct. 当我在没有helperMethod的情况下helperMethod版本进行新调用时,我helperMethod The performance boost is because of getPixels not the if statement. 性能提升是因为getPixels不是if语句。

Actual Slow code: 实际慢速代码:

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);
        }
    }
}

Note:All speeds are an average of 100 runs. 注意:所有速度平均为100次运行。

Try hoisting the condition out of the loop: 尝试将条件提升出循环:

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]);
    }
}

In the 'fast code' you never run the statement 在“快速代码”中,您永远不会运行该语句

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

But in the 'slow code' if the boolean is set to true at least once you run this addiotional statement that makes the time longer. 但是在'慢代码'中,如果布尔值至少设置为true,则运行此addiotional语句会使时间更长。 If your condition is always false then the if statement is checked about 7 times in each iteration through the loop. 如果您的条件总是为假,则在循环的每次迭代中检查if语句大约7次。 Try to place the if outside the loop. 尝试将if置于循环外部。

It is probably your profiling code, that confusing you. 这可能是您的分析代码,让您感到困惑。 Try to isolate the part of the code that you want to profile and just measure that part, avoid GCable operations like creating Bitmaps in your cases. 尝试隔离要分析的代码部分,并仅测量该部分,避免GCable操作,如在您的情况下创建位图。

If I call your test code with 如果我用你的测试代码

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

it runs slow. 它运行缓慢。 But if I call it with 但如果我打电话给它

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

That's a similar (still worse) number. 这是一个类似的(更糟糕的)数字。 So useGetPixels makes all the difference. 所以useGetPixels会发挥重要作用。 Which I guess gets the Bitmap data into a local buffer and set the results later. 我想将Bitmap数据放入本地缓冲区并稍后设置结果。

In your fast code you don't use class Color at all. 在快速代码中,根本不使用类Color。 I assume initialization of this class takes some time, it has lots of static method and static code. 我假设这个类的初始化需要一些时间,它有很多静态方法和静态代码。

You can try to do following: make sure Color class is fully loaded and initialized before making your test (you can call any static method from Color class before calling your applyAlphaGetPixels() method). 您可以尝试执行以下操作:确保在进行测试之前完全加载并初始化Color类(可以在调用applyAlphaGetPixels()方法之前调用Color类中的任何静态方法)。 Then run your test and compare results. 然后运行测试并比较结果。

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

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