Я столкнулся с этим в ответом на другой вопрос. Я пытался диагностировать, какое изменение кода оказало большее влияние на скорость. Я использовал логический флаг в цикле for, чтобы переключаться между использованием вспомогательных методов для создания Color.
Интересное поведение заключается в том, что когда я решил, какой из них был быстрее и удален, если скорость кода усиливается 10 раз. Принимая 140 мс до и только через 13 мс. Я должен только удалить один расчет из примерно 7 из цикла. Почему такое резкое увеличение скорости?
Медленный код: (работает в 141 миллисекундах, когда * См. edit 2helperMethods
является ложным)
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);
}
EDIT: Кажется, проблема не в том, что 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);
}
EDIT 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 прогонов.