在Android设备上for循环非常慢

时间:2012-04-12 10:05:15

标签: java android performance for-loop heap

我在尝试为Android设备编写位图操作算法时遇到了一个问题。

我有一个1680x128像素的位图,需要对它应用滤镜。但这个非常简单的代码实际上花了将近15-20秒在我的Android设备上运行(带有1Ghz处理器的xperia ray)。

所以我试图找到瓶颈并减少尽可能多的代码行,并最终得到循环本身,这几乎花了相同的时间来运行。

for (int j = 0; j < 128; j++) {
    for (int i = 0; i < 1680; i++) {
         Double test = Math.random();
    }
}

这样的设备在简单的for循环中花费这么多时间而没有困难的操作是否正常?

我对移动设备上的编程非常陌生,所以请原谅这个问题可能是愚蠢的。

更新:现在通过一些更简单的操作加快了速度。

但回到我的主要问题:

public static void filterImage(Bitmap img, FilterStrategy filter) {
    img.prepareToDraw();
    int height = img.getHeight();
    int width = img.getWidth();
            RGB rgb;
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            rgb = new RGB(img.getPixel(i, j));
            if (filter.isBlack(rgb)) {
                img.setPixel(i, j, 0);
            } else
                img.setPixel(i, j, 0xffffffff);
        }
    }
    return;
}

上面的代码是我真正需要在设备上运行得更快的代码。 (几乎立即) 你认为它有任何优化潜力吗?

RGB只是一个计算红色,绿色和蓝色值的类,如果所有三个颜色部分都低于100或任何其他指定值,则过滤器只返回true。 围绕img.getPixel(i,j)或setPixel的循环已经需要20秒或更长时间。这是一项如此昂贵的操作吗?

4 个答案:

答案 0 :(得分:3)

可能是因为创建了太多Double类型的对象..因此它增加了堆大小并且设备开始冻结..

方法是

double[] arr = new double[128]
for (int j = 0; j < 128; j++) {
    for (int i = 0; i < 1680; i++) {
         arr[i]  = Math.random();
    }
}

答案 1 :(得分:1)

下面的文档中有一个免责声明可能会影响性能,尝试自己创建一个实例而不是使用静态版本,我已经用粗体突出显示了性能免责声明:

返回伪随机双n,其中n> = 0.0&amp;&amp; n&lt; 1.0。此方法重用Random的单个实例。此方法是线程安全的,因为对Random的访问是同步的,但这会损害可伸缩性。 应用程序可以通过为每个线程分配一个Random来获得性能优势。

尝试创建自己的随机数作为类的静态字段,以避免同步访问:

private static Random random = new Random();

然后按如下方式使用:

double r = random.nextDouble();

如果你不需要双精度,也可以考虑使用float(random.nextFloat())。

答案 2 :(得分:1)

首先,Stephen C提出了一个很好的论点:尽量避免创建一堆RGB对象。

其次,只需拨打一次getPixels

,就可以将相对昂贵的来电替换为getPixel,从而取得巨大进步。

我进行了一些快速测试,并设法将运行时间减少到大约10%。试试看。这是我使用的代码:

int[] pixels = new int[height * width];
img.getPixels(pixels, 0, width, 0, 0, width, height);

for(int pixel:pixels) {
    // check the pixel
}

答案 3 :(得分:0)

  

RGB只是一个计算红色,绿色和蓝色值的类,如果所有三个颜色部分都低于100或任何其他指定值,则过滤器只返回true。

一个问题是您正在创建RGB类的height * width个实例,只是为了测试单个pizel是否为黑色。用静态方法调用替换该方法,该方法将要测试的像素作为参数。


更一般地说,如果你不知道为什么某段代码很慢...... 描述它。在这种情况下,探查器会告诉您RGB构造函数花费了大量时间。内存分析器会告诉您正在创建大量RGB对象并收集垃圾。