简体   繁体   中英

How to decrease resource loading times from classpath?

I'm currently building an application which is very resource heavy, featuring lots of images and some PDF files that the user can display and interact with. For now I'm loading the images when they are needed using

MainMenu.class.getResource("ImageName.png");

which is then set to a JPanel or similar to be displayed. However, loading these images sometimes takes a long time and slows the application to a halt while it tries to load them. This happens even on my work laptop which is a decent spec nevermind the user's PCs which are likely to be older.

Does anyone have a more streamlined way of doing this?

Since you mentionned that your whole application grinds to a halt, you should make sure the loading work is not done in the Event-Processing Thread . You should execute it in a SwingWorker :

public class ImageLoadingWorker extends SwingWorker<URL, Object> {

    private String resourceName;

    public ImageLoadingWorker(String resourceName) {
        this.resourceName = resourceName;
    }

    @Override
    protected URL doInBackground() throws Exception {
        return getClass().getClassLoader().getResource(resourceName);
    }

    @Override
    protected void done() {
        // use result here 
        URL result = get();
        // ...
    }
}

And then:

new ImageLoadingWorker("dummy/dummy/Ima‌​geName.png").execute();

Check this oracle documentation for more details: Improve Application Performance With SwingWorker in Java SE 6

I would suggest to profiling the read operation with a tool like JProfiler, or a free one.

  1. It might be possible that you are suffering of slow I/O. Once you retrieved the url you have to open an inputstream, make sure to use a BufferedInputStream.

  2. Additionally you could try to extract the resources to a temp directory and read them of there, this would save you the overhead of jar decompression.

  3. Also you might consider reducing the image sizes, use a tool like tiny png and try reduce the png files in size. The smaller they are the faster they import.

  4. You could use an image library, like JAI (Java Advanced Image API), since you are not presenting the rendering code, it is hard to tell where the problem occurs.

  5. Consider using a swing worker, as the previous post suggests.

regards,

  1. A minimal effect but very eye catching: check where the heavy work is done.

Do not load the images (or other heavy processing) while handling an action event:

@Override
public void actionPerformed(ActionEvent event) {
    ... ImageIO.readImage(...);
}

This immediately freezes the system. Instead a bit of postponing already keeps the system responsive:

@Override
public void actionPerformed(ActionEvent event) {
    SwingUtilities.invokeLater(() -> {
        ... ImageIO.readImage(...);
    });
}

Doing things in the background (swing worker was mentioned) might be a further step when asynchrone is feasible.

  1. Use FindBugs

Memory leaks, race conditions, QA.

  1. Profile the application

Drill down to bottle necks, memory and CPU usage.

  1. Reduce resources

The last resort is to reduce resources. This can partly be utilising the system itself: Desktop.getDesktop().open(pdf); instead your own PDF viewer. Combining several images into one. Selecting between PropertyResourceBundle and ListResourceBundle. No trivial images (buttons with different texts).

Probably some of the above you already did. May it then help others.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM