【发布时间】:2012-08-27 18:06:55
【问题描述】:
我在answering another question 中遇到了这个问题。我试图诊断哪些代码更改对速度的影响更大。我在 for 循环中使用了一个布尔标志来切换使用辅助方法来构造 Color。
有趣的行为是,当我决定哪一个更快并删除如果代码的速度放大 10 倍时。之前用了 140 毫秒,之后只用了 13 毫秒。我应该只从循环中删除大约 7 个计算中的一个。为什么速度会如此大幅提升?
慢代码:( *参见编辑 2helperMethods 为假时运行时间为 141 毫秒)
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);
}
快速代码:(运行时间为 13 毫秒)
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 提升到循环之外。代码运行速度稍快,但仍以 131 毫秒的速度运行:
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 的版本进行新调用时,我做对了。性能提升是因为 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 语句可能使代码更难优化。
-
Traceview 可能会欺骗您,因为这会禁用 JIT。
-
请提供更详细的信息。在什么情况下是什么速度?刚刚删除了 if 或 if 和它的主体?
-
helperMethods是整个循环的真/假。所以不能是分支预测。
标签: java android performance