Java代码 - 编译时优化

时间:2014-09-15 17:39:24

标签: java optimization time

我是编程新手,编写了一个java程序,用于计算随机点的voronoi图并将其绘制在图片上 - 1080 x 1920像素。在这里,您可以看到result

问题是编译代码需要将近四分钟。请帮我进行代码优化。您可以在下面找到代码:

class Voronoi {
private static Random r;
private static KDTree<Integer> kd;
private static double[][] keys;
private static int counter;
private static int x;

public static void main(String[] args) throws IOException,
        KeySizeException, KeyDuplicateException {
    BufferedImage img = null;
    Scanner sc = new Scanner(System.in);
    x = sc.nextInt();
    // input an image

    img = ImageIO.read(new File("input.jpg"));
    // get image Height and Width
    int w = img.getWidth();
    int h = img.getHeight();
    // make array with equal size like the image and populate it with the 0
    // make an empty array and populate it
    int[][] empty = new int[h][w];
    for (int row = 0; row < h; row++) {
        for (int col = 0; col < w; col++) {
            empty[row][col] = 0;

        }
    }
    // make a D-dimensional KD-tree
    keys = new double[x][2];
    kd = new KDTree<Integer>(2);
    ArrayList<Color> b = new ArrayList<Color>();
    int[] totalBlue = new int[x];
    int[] totalGreen = new int[x];
    int[] totalRed = new int[x];
    int[] counter_sec = new int[x];
    // Generate random centers and populate them with 1

    for (int i = 0; i < x; i++) {
        generateCentre(empty, h, w);
        // b.add(new Color(r.nextInt(256),r.nextInt(256),r.nextInt(256)));

    }
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            double[] array = new double[2];
            array[0] = i;
            array[1] = j;
            Color c = new Color(img.getRGB(j, i));
            totalBlue[kd.nearest(array)] = totalBlue[kd.nearest(array)]
                    + c.getBlue();
            totalRed[kd.nearest(array)] = totalRed[kd.nearest(array)]
                    + c.getRed();
            totalGreen[kd.nearest(array)] = totalGreen[kd.nearest(array)]
                    + c.getGreen();
            // img.setRGB(j, i, b.get(kd.nearest(array)).getRGB());
            counter_sec[kd.nearest(array)] = counter_sec[kd.nearest(array)] + 1;
        }
    }
    for (int i = 0; i < h; i++) {
        for (int j = 0; j < w; j++) {
            double[] array = new double[2];
            array[0] = i;
            array[1] = j;
            Color c = new Color(img.getRGB(j, i));
            // img.setRGB(j, i, b.get(kd.nearest(array)).getRGB());
            Color color = new Color(totalRed[kd.nearest(array)]/counter_sec[kd.nearest(array)], totalGreen[kd.nearest(array)]/counter_sec[kd.nearest(array)],totalBlue[kd.nearest(array)]/counter_sec[kd.nearest(array)]);
            img.setRGB(j, i, color.getRGB());
        }
    }
    File outputfile = new File("image.jpg");
    ImageIO.write(img, "jpg", outputfile);
    System.out.println(totalRed[0]/counter_sec[0]+" "+totalGreen[0]/counter_sec[0]+" "+totalBlue[0]/counter_sec[0]);
}

public static void generateCentre(int[][] empty, int h, int w)
        throws KeySizeException, KeyDuplicateException {
    r = new Random();
    int height = r.nextInt(h);
    int width = r.nextInt(w);
    for (int row = 0; row < h; row++) {
        for (int col = 0; col < w; col++) {
            if (row == height && col == width && empty[height][width] == 0) {
                empty[height][width] = 1;
                keys[counter][0] = row;
                keys[counter][2] = col;
                kd.insert(keys[counter], counter);
            }/*else if (row == height && col == width
                    && empty[height][width] != 0) {
                generateCentre(empty, h, w);
            }*/
        }
    }


    System.out.println(kd.search(keys[counter]));
    if (counter < x) {
        counter++;
    }
}
}

1 个答案:

答案 0 :(得分:2)

虽然我没有完全理解您的代码,但我发现了一个可能导致速度放缓的原因:

        totalBlue[kd.nearest(array)] = totalBlue[kd.nearest(array)]
                + c.getBlue();
        totalRed[kd.nearest(array)] = totalRed[kd.nearest(array)]
                + c.getRed();
        totalGreen[kd.nearest(array)] = totalGreen[kd.nearest(array)]
                + c.getGreen();
        // img.setRGB(j, i, b.get(kd.nearest(array)).getRGB());
        counter_sec[kd.nearest(array)] = counter_sec[kd.nearest(array)] + 1;

你似乎在反复调用kd.nearest(array),这可能不是一个非常便宜的操作。你应该调用它一次并将其存储在局部变量中。我会按如下方式重写你的密钥循环:

double[] coords = new double[2];
for (int i = 0; i < h; i++) {
  for (int j = 0; j < w; j++) {
    coords[0] = i;
    coords[1] = j;
    final int nearest = kd.nearest(coords);
    final Color c = new Color(img.getRGB(j, i));
    totalBlue[nearest] += c.getBlue();
    totalRed[nearest] += c.getRed();
    totalGreen[nearest] += c.getGreen();
    counter_sec[nearest]++;
  }
}

在这里,我使用了+=++运算符来缩短和提高可读性。我还在循环外提升了坐标数组,因为它可以在每次迭代时安全地重复使用。这减少了GC时间,但更重要的是它有助于CPU缓存。

将相同的更改应用于生成输出图像的第二个循环。