Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么在这个方法中添加一个If语句会大大降低它的速度?_Java_Android_Performance - Fatal编程技术网

Java 为什么在这个方法中添加一个If语句会大大降低它的速度?

Java 为什么在这个方法中添加一个If语句会大大降低它的速度?,java,android,performance,Java,Android,Performance,这是我在一次旅行中偶然发现的。我试图诊断哪个代码更改对速度有更大的影响。我在for循环中使用了一个布尔标志,在使用helper方法来构造 有趣的是,当我决定哪一个更快时,删除了if,代码的速度放大了10倍。前140毫秒,后13毫秒。我应该只从循环中删除大约7个计算中的一个。为什么速度会有如此大的提高 慢速代码:(当helperMethods为false时,将在141毫秒内运行)*请参见编辑2 public static void applyAlphaGetPixels(Bitmap b, Bit

这是我在一次旅行中偶然发现的。我试图诊断哪个代码更改对速度有更大的影响。我在for循环中使用了一个布尔标志,在使用helper方法来构造

有趣的是,当我决定哪一个更快时,删除了if,代码的速度放大了10倍。前140毫秒,后13毫秒。我应该只从循环中删除大约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);
}
编辑2:我很笨。真的很傻。在前面的调用堆栈中,我使用了另一个布尔标志在使用此方法和使用另一个使用
getPixel
而不是
getPixels
的方法之间切换。对于所有具有
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);
        }
    }
}
publicstaticvoidapplyalphagetpixel(位图b、位图bAlpha、布尔帮助方法){
int w=b.getWidth();
inth=b.getHeight();
对于(int y=0;y

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

在“快速代码”中,您从未运行过该语句

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

但在“慢代码”中,如果布尔值至少在运行此附加语句后设置为true,则会延长时间。如果您的条件始终为false,那么在循环的每次迭代中,If语句将被检查大约7次。尝试将if放置在回路外部。

尝试将条件提升到回路外部:

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]);
    }
}
if(帮助方法){
对于(int j=0;j
可能是您的评测代码让您感到困惑。试着隔离你想要分析的代码部分,只测量那部分,避免在你的案例中创建位图之类的GCable操作

如果我调用你的测试代码

testing.loadDrawable(this, false, true, false)
它跑得很慢。但如果我把它叫做

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

这是一个类似(更糟糕)的数字。因此,useGetPixels带来了所有的不同。我猜这会将位图数据放入本地缓冲区,稍后再设置结果。

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

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

if语句可能使代码更难优化。分支/分支预测?Traceview可能会愚弄您,因为这将禁用JIT。请提供更详细的信息。在哪种情况下是多快?刚刚删除了if或if及其主体?
helperMethods
对于整个循环为true/false。所以这不可能是分支预测,这很有趣。看起来情况也一样。在143ms内使用
helperMethods
false运行。不过分支预测应该能很好地处理它。。。嗯,我试过了,代码运行速度仍然很慢。快了8毫秒,很有趣。大O分析…:)我不认为它在技术上是大O,因为它是由一个算法运行的时间与数据集相比来定义的。对。然而,它一定是消耗时间的东西,可能是在较低级别的某个地方,这听起来像是我的错误如果问题是GC,这不意味着只有第一次运行会很快,因为只有后面的运行会因为GC清除早期测试而陷入困境吗?这也是我所听说的GC对性能影响最大的一次,而且似乎是无中生有。我如何预测GC何时会导致如此大规模的问题?这感觉我接近答案了,但我仍然想知道到底发生了什么。在这个答案中,我并不声称问题是由于GCs造成的,但您的代码太乱,无法正确地进行分析。我相信您的问题是
useGetPixels
,当您启用它时,运行时间会增加。否则,
if
as-clain不会改变运行时间。所以我很困惑。你是说getPixels的运行时间增加了?对我来说,每次都更快。您的“快速”版本是
loadDrawableHard(this,true,true)
。我改了名字,这样我就能很容易地分辨出哪个是硬编码的。在这个版本中,除了调用了
applyalphagettpixelshard()
和'applyGetPixelHard()`之外,所有代码都是相同的。如果我在运行时将
useGetPixels
设置为false,我看不到同样的改进。我最初编写的
loadDrawableHard()
只使用
applyAlphaGetPixelsHard()
,但添加了
applyGetPixelHard()
以消除可能的差异。我简直不敢相信
testing.loadDrawable(this, false, true, false)
testing.loadDrawable(this, true, true, false)