I am writing a small Java application to analyze a large number of image files. At the moment, he finds the brightest image in the folder, averaging the brightness of each pixel in the image and comparing it with other images in the folder.
Sometimes I get a speed of 100+ images per second right after launch, but it almost always drops to <20 images per second, and I'm not sure why. When it is 100+ images / sec, CPU usage is 100%, but then it drops to about 20%, which seems too low.
Here is the main class:
public class ImageAnalysis { public static final ConcurrentLinkedQueue<File> queue = new ConcurrentLinkedQueue<>(); private static final ConcurrentLinkedQueue<ImageResult> results = new ConcurrentLinkedQueue<>(); private static int size; private static AtomicInteger running = new AtomicInteger(); private static AtomicInteger completed = new AtomicInteger(); private static long lastPrint = 0; private static int completedAtLastPrint; public static void main(String[] args){ File rio = new File(IO.CAPTURES_DIRECTORY.getAbsolutePath() + File.separator + "Rio de Janeiro"); String month = "12"; Collections.addAll(queue, rio.listFiles((dir, name) -> { return (name.substring(0, 2).equals(month)); })); size = queue.size(); ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1); for (int i = 0; i < 8; i++){ AnalysisThread t = new AnalysisThread(); t.setPriority(Thread.MAX_PRIORITY); executor.execute(t); running.incrementAndGet(); } } public synchronized static void finished(){ if (running.decrementAndGet() <= 0){ ImageResult max = new ImageResult(null, 0); for (ImageResult r : results){ if (r.averageBrightness > max.averageBrightness){ max = r; } } System.out.println("Max Red: " + max.averageBrightness + " File: " + max.file.getAbsolutePath()); } } public synchronized static void finishedImage(ImageResult result){ results.add(result); int c = completed.incrementAndGet(); if (System.currentTimeMillis() - lastPrint > 10000){ System.out.println("Completed: " + c + " / " + size + " = " + ((double) c / (double) size) * 100 + "%"); System.out.println("Rate: " + ((double) c - (double) completedAtLastPrint) / 10D + " images / sec"); completedAtLastPrint = c; lastPrint = System.currentTimeMillis(); } } }
And stream class:
public class AnalysisThread extends Thread { @Override public void run() { while(!ImageAnalysis.queue.isEmpty()) { File f = ImageAnalysis.queue.poll(); BufferedImage image; try { image = ImageIO.read(f); double color = 0; for (int x = 0; x < image.getWidth(); x++) { for (int y = 0; y < image.getHeight(); y++) {
source share